• 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_ES31_InitShaderVariables : public GLSLTest
549 {};
550 
BuildBigInitialStackShader(int length)551 std::string BuildBigInitialStackShader(int length)
552 {
553     std::string result;
554     result += "void main() { \n";
555     for (int i = 0; i < length; i++)
556     {
557         result += "  if (true) { \n";
558     }
559     result += "  int temp; \n";
560     for (int i = 0; i <= length; i++)
561     {
562         result += "} \n";
563     }
564     return result;
565 }
566 
567 // Tests a shader from conformance.olges/GL/build/build_017_to_024
568 // This shader uses chained assign-equals ops with swizzle, often reusing the same variable
569 // as part of a swizzle.
570 
571 // Skipped on NV: angleproject:7029
TEST_P(GLSLTest,SwizzledChainedAssignIncrement)572 TEST_P(GLSLTest, SwizzledChainedAssignIncrement)
573 {
574     constexpr char kFS[] =
575         R"(
576         precision mediump float;
577         void main() {
578             vec2 v = vec2(1,5);
579             // at the end of next statement, values in
580             // v.x = 12, v.y = 12
581             v.xy += v.yx += v.xy;
582             // v1 and v2, both are initialized with (12,12)
583             vec2 v1 = v, v2 = v;
584             v1.xy += v2.yx += ++(v.xy);  // v1 = 37, v2 = 25 each
585             v1.xy += v2.yx += (v.xy)++;  // v1 = 75, v2 = 38 each
586             gl_FragColor = vec4(v1,v2)/255.;  // 75, 75, 38, 38
587         })";
588 
589     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
590     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
591     ASSERT_GL_NO_ERROR();
592     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(75, 75, 38, 38));
593 }
594 
TEST_P(GLSLTest,NamelessScopedStructs)595 TEST_P(GLSLTest, NamelessScopedStructs)
596 {
597     constexpr char kFS[] = R"(precision mediump float;
598 void main()
599 {
600     struct
601     {
602         float q;
603     } b;
604 
605     gl_FragColor = vec4(1, 0, 0, 1);
606     gl_FragColor.a += b.q;
607 })";
608 
609     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
610 }
611 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)612 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
613 {
614     constexpr char kFS[] = R"(#version 300 es
615 precision mediump float;
616 out vec4 fragColor;
617 uniform vec3 a[3];
618 uniform vec3 b[3];
619 void main() {
620   bool same = a == b;
621   fragColor = vec4(0);
622   if (same) {
623     fragColor = vec4(1);
624   }
625 }
626 )";
627 
628     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
629     glUseProgram(program);
630 
631     GLint aLocation = glGetUniformLocation(program, "a");
632     GLint bLocation = glGetUniformLocation(program, "b");
633     EXPECT_NE(aLocation, -1);
634     EXPECT_NE(bLocation, -1);
635 
636     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
637     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
638 
639     static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
640     glUniform3fv(bLocation, 9, almostZeros);
641 
642     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
643     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
644 
645     glUniform3fv(aLocation, 9, almostZeros);
646     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
647     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
648 
649     ASSERT_GL_NO_ERROR();
650 }
651 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)652 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
653 {
654     constexpr char kFS[] = R"(#version 300 es
655 precision mediump float;
656 out vec4 fragColor;
657 uniform mat3 a[3];
658 uniform mat3 b[3];
659 void main() {
660   bool same = a == b;
661   fragColor = vec4(0);
662   if (same) {
663     fragColor = vec4(1);
664   }
665 }
666 )";
667 
668     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
669     glUseProgram(program);
670 
671     GLint aLocation = glGetUniformLocation(program, "a");
672     GLint bLocation = glGetUniformLocation(program, "b");
673     EXPECT_NE(aLocation, -1);
674     EXPECT_NE(bLocation, -1);
675 
676     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
677     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
678 
679     static float almostZeros[] = {
680         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
681     };
682     glUniformMatrix3fv(bLocation, 27, false, almostZeros);
683 
684     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
685     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
686 
687     glUniformMatrix3fv(aLocation, 27, false, almostZeros);
688     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
689     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
690 
691     ASSERT_GL_NO_ERROR();
692 }
693 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)694 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
695 {
696     constexpr char kFS[] = R"(#version 300 es
697 precision mediump float;
698 out vec4 fragColor;
699 uniform float a[3];
700 uniform float b[3];
701 void main() {
702   bool same = a == b;
703   fragColor = vec4(0);
704   if (same) {
705     fragColor = vec4(1);
706   }
707 }
708 )";
709 
710     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
711     glUseProgram(program);
712 
713     GLint aLocation = glGetUniformLocation(program, "a");
714     GLint bLocation = glGetUniformLocation(program, "b");
715     EXPECT_NE(aLocation, -1);
716     EXPECT_NE(bLocation, -1);
717 
718     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
719     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
720 
721     static float almostZeros[] = {
722         0,
723         0,
724         1,
725     };
726     glUniform1fv(bLocation, 3, almostZeros);
727 
728     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
729     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
730 
731     glUniform1fv(aLocation, 3, almostZeros);
732     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
733     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
734 
735     ASSERT_GL_NO_ERROR();
736 }
737 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)738 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
739 {
740     constexpr char kFS[] = R"(#version 300 es
741 precision mediump float;
742 out vec4 fragColor;
743 uniform vec3 a[3];
744 uniform vec3 b[3];
745 void main() {
746   bool notSame = a != b;
747   fragColor = vec4(0);
748   if (notSame) {
749     fragColor = vec4(1);
750   }
751 }
752 )";
753 
754     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
755     glUseProgram(program);
756 
757     GLint aLocation = glGetUniformLocation(program, "a");
758     GLint bLocation = glGetUniformLocation(program, "b");
759     EXPECT_NE(aLocation, -1);
760     EXPECT_NE(bLocation, -1);
761 
762     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
763     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
764 
765     static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
766     glUniform3fv(bLocation, 9, almostZeros);
767 
768     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
769     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
770 
771     glUniform3fv(aLocation, 9, almostZeros);
772     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
773     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
774 
775     ASSERT_GL_NO_ERROR();
776 }
777 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)778 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
779 {
780     constexpr char kFS[] = R"(#version 300 es
781 precision mediump float;
782 out vec4 fragColor;
783 uniform mat3 a[3];
784 uniform mat3 b[3];
785 void main() {
786   bool notSame = a != b;
787   fragColor = vec4(0);
788   if (notSame) {
789     fragColor = vec4(1);
790   }
791 }
792 )";
793 
794     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
795     glUseProgram(program);
796 
797     GLint aLocation = glGetUniformLocation(program, "a");
798     GLint bLocation = glGetUniformLocation(program, "b");
799     EXPECT_NE(aLocation, -1);
800     EXPECT_NE(bLocation, -1);
801 
802     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
804 
805     static float almostZeros[] = {
806         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
807     };
808     glUniformMatrix3fv(bLocation, 27, false, almostZeros);
809 
810     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
811     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
812 
813     glUniformMatrix3fv(aLocation, 27, false, almostZeros);
814     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
815     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
816 
817     ASSERT_GL_NO_ERROR();
818 }
819 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)820 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
821 {
822     constexpr char kFS[] = R"(#version 300 es
823 precision mediump float;
824 out vec4 fragColor;
825 uniform float a[3];
826 uniform float b[3];
827 void main() {
828   bool notSame = a != b;
829   fragColor = vec4(0);
830   if (notSame) {
831     fragColor = vec4(1);
832   }
833 }
834 )";
835 
836     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
837     glUseProgram(program);
838 
839     GLint aLocation = glGetUniformLocation(program, "a");
840     GLint bLocation = glGetUniformLocation(program, "b");
841     EXPECT_NE(aLocation, -1);
842     EXPECT_NE(bLocation, -1);
843 
844     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
845     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
846 
847     static float almostZeros[] = {
848         0,
849         0,
850         1,
851     };
852     glUniform1fv(bLocation, 3, almostZeros);
853 
854     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
855     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
856 
857     glUniform1fv(aLocation, 3, almostZeros);
858     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
859     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
860 
861     ASSERT_GL_NO_ERROR();
862 }
863 
864 // Test that array of fragment shader outputs is processed properly and draws
865 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)866 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
867 {
868     GLuint fbo;
869     glGenFramebuffers(1, &fbo);
870     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
871 
872     GLuint textures[4];
873     glGenTextures(4, textures);
874 
875     for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
876     {
877         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
878         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
879                      GL_UNSIGNED_BYTE, nullptr);
880     }
881 
882     GLint maxDrawBuffers;
883     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
884     ASSERT_GE(maxDrawBuffers, 4);
885 
886     GLuint readFramebuffer;
887     glGenFramebuffers(1, &readFramebuffer);
888     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
889 
890     constexpr char kFS[] = R"(#version 300 es
891 precision highp float;
892 
893 out vec4 frag_color[4];
894 
895 void main()
896 {
897     frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
898     frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
899     frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
900     frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
901 }
902 )";
903 
904     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
905 
906     GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
907                          GL_COLOR_ATTACHMENT3};
908 
909     constexpr GLuint kMaxBuffers = 4;
910 
911     // Enable all draw buffers.
912     for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
913     {
914         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
915         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
916                                textures[texIndex], 0);
917         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
918                                textures[texIndex], 0);
919     }
920     glDrawBuffers(kMaxBuffers, allBufs);
921 
922     // Draw with simple program.
923     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
924     ASSERT_GL_NO_ERROR();
925 
926     verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
927     verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
928     verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
929     verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
930 }
931 
932 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)933 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
934 {
935     constexpr char kFS[] = R"(#version 300 es
936 precision highp float;
937 
938 // Make color0 inactive but specify color1 first.  The Vulkan backend assigns bogus locations when
939 // compiling and fixes it up in SPIR-V.  If color0's location is not fixed, it will return location
940 // 1 (aliasing color1).  This will lead to a Vulkan validation warning about attachment 0 not being
941 // written to, which shouldn't be fatal.
942 layout(location = 1) out vec4 color1;
943 layout(location = 0) out vec4 color0;
944 
945 void main()
946 {
947     color1 = vec4(0.0, 1.0, 0.0, 1.0);
948 }
949 )";
950 
951     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
952 
953     constexpr GLint kDrawBufferCount = 2;
954 
955     GLint maxDrawBuffers;
956     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
957     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
958 
959     GLTexture textures[kDrawBufferCount];
960 
961     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
962     {
963         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
964         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
965                      GL_UNSIGNED_BYTE, nullptr);
966     }
967 
968     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
969 
970     GLFramebuffer fbo;
971     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
972 
973     // Enable all draw buffers.
974     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
975     {
976         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
977         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
978                                textures[texIndex], 0);
979     }
980     glDrawBuffers(kDrawBufferCount, allBufs);
981 
982     // Draw with simple program.
983     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
984     ASSERT_GL_NO_ERROR();
985 }
986 
TEST_P(GLSLTest,ScopedStructsOrderBug)987 TEST_P(GLSLTest, ScopedStructsOrderBug)
988 {
989     constexpr char kFS[] = R"(precision mediump float;
990 
991 struct T
992 {
993     float f;
994 };
995 
996 void main()
997 {
998     T a;
999 
1000     struct T
1001     {
1002         float q;
1003     };
1004 
1005     T b;
1006 
1007     gl_FragColor = vec4(1, 0, 0, 1);
1008     gl_FragColor.a += a.f;
1009     gl_FragColor.a += b.q;
1010 })";
1011 
1012     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1013 }
1014 
1015 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
1016 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)1017 TEST_P(GLSLTest, ScopedStructsOrderBug2)
1018 {
1019     constexpr char kFS[] = R"(precision mediump float;
1020 
1021 uniform struct T
1022 {
1023     float f;
1024 } x;
1025 
1026 void main()
1027 {
1028     T a;
1029 
1030     struct T
1031     {
1032         float q;
1033     };
1034 
1035     T b;
1036 
1037     gl_FragColor = vec4(1, 0, 0, 1);
1038     gl_FragColor.a += a.f;
1039     gl_FragColor.a += b.q;
1040 })";
1041 
1042     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1043 }
1044 
1045 // Test that inactive uniforms of struct type don't cause any errors.
TEST_P(GLSLTest,InactiveStructUniform)1046 TEST_P(GLSLTest, InactiveStructUniform)
1047 {
1048     constexpr char kVS[] = R"(
1049 uniform struct
1050 {
1051     vec4 c;
1052 } s;
1053 void main()
1054 {
1055 })";
1056 
1057     ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
1058 }
1059 
1060 // Test that struct with same name can be declared in inner scope.
TEST_P(GLSLTest,SameNameStructInInnerScope)1061 TEST_P(GLSLTest, SameNameStructInInnerScope)
1062 {
1063     constexpr char kVS[] = R"(
1064 void main() {
1065     gl_Position = vec4(0);
1066 })";
1067 
1068     constexpr char kFS[] = R"(
1069 struct S
1070 {
1071     mediump float f;
1072 };
1073 void main()
1074 {
1075     struct S
1076     {
1077         S n;
1078     };
1079 })";
1080 
1081     ANGLE_GL_PROGRAM(program, kVS, kFS);
1082 }
1083 
1084 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)1085 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
1086 {
1087     constexpr char kVS[] = R"(
1088 struct S {
1089     float member;
1090 }, a;
1091 void main() {
1092     a.member = 0.0;
1093     gl_Position = vec4(a.member);
1094 })";
1095 
1096     constexpr char kFS[] = R"(precision mediump float;
1097 void main()
1098 {
1099     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1100 })";
1101 
1102     ANGLE_GL_PROGRAM(program, kVS, kFS);
1103 }
1104 
1105 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1106 TEST_P(GLSLTest, StructConstantFoldingBug)
1107 {
1108     constexpr char kVS[] = R"(
1109 void main()
1110 {
1111 
1112    const struct s2 {
1113        int i;
1114        vec3 v3;
1115        bvec4 bv4;
1116    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1117 
1118    struct s4 {
1119        int ii;
1120        vec4 v4;
1121       };
1122 
1123    const struct s1 {
1124       s2 ss;
1125       int i;
1126       float f;
1127       mat4 m;
1128       s4 s44;
1129    } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1130 
1131   const int field3 = s11.i * s11.ss.i;  // constant folding (int * int)
1132   const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1133  // 49, 64, 81, 100
1134   const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]);  // 10.0, 5.0, 16.0, 81.0
1135   gl_Position = v4;
1136 })";
1137 
1138     constexpr char kFS[] = R"(precision mediump float;
1139 precision mediump float;
1140 void main()
1141 {
1142     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1143 })";
1144 
1145     ANGLE_GL_PROGRAM(program, kVS, kFS);
1146 }
1147 
1148 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1149 TEST_P(GLSLTest, StructConstantFoldingBug2)
1150 {
1151     constexpr char kVS[] = R"(
1152 uniform vec4 u;
1153 
1154 void main()
1155 {
1156 
1157    const struct s2 {
1158        int i;
1159        vec3 v3;
1160        bvec4 bv4;
1161    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1162 
1163    s2 x;
1164    x.v3 = u.xyz;
1165 
1166    gl_Position = vec4(x.v3, float(s22.i));
1167 })";
1168 
1169     constexpr char kFS[] = R"(precision mediump float;
1170 precision mediump float;
1171 void main()
1172 {
1173     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1174 })";
1175 
1176     ANGLE_GL_PROGRAM(program, kVS, kFS);
1177 }
1178 
TEST_P(GLSLTest,ScopedStructsBug)1179 TEST_P(GLSLTest, ScopedStructsBug)
1180 {
1181     constexpr char kFS[] = R"(precision mediump float;
1182 
1183 struct T_0
1184 {
1185     float f;
1186 };
1187 
1188 void main()
1189 {
1190     gl_FragColor = vec4(1, 0, 0, 1);
1191 
1192     struct T
1193     {
1194         vec2 v;
1195     };
1196 
1197     T_0 a;
1198     T b;
1199 
1200     gl_FragColor.a += a.f;
1201     gl_FragColor.a += b.v.x;
1202 })";
1203 
1204     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1205 }
1206 
TEST_P(GLSLTest,DxPositionBug)1207 TEST_P(GLSLTest, DxPositionBug)
1208 {
1209     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1210 varying float dx_Position;
1211 void main()
1212 {
1213     gl_Position = vec4(inputAttribute);
1214     dx_Position = 0.0;
1215 })";
1216 
1217     constexpr char kFS[] = R"(precision mediump float;
1218 
1219 varying float dx_Position;
1220 
1221 void main()
1222 {
1223     gl_FragColor = vec4(dx_Position, 0, 0, 1);
1224 })";
1225 
1226     ANGLE_GL_PROGRAM(program, kVS, kFS);
1227 }
1228 
1229 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1230 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1231 {
1232     constexpr int kStartIndex  = 0;
1233     constexpr int kArrayLength = 5;
1234     constexpr char kVS[]       = R"(#version 300 es
1235 precision highp float;
1236 void main() {
1237     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1238     gl_PointSize = 3.0;
1239 })";
1240 
1241     constexpr char kFS[] = R"(#version 300 es
1242 precision highp float;
1243 out vec4 outColor;
1244 void main() {
1245     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1246 })";
1247 
1248     ANGLE_GL_PROGRAM(program, kVS, kFS);
1249 
1250     glUseProgram(program);
1251     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1252 
1253     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1254     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1255     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1256     {
1257         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1258         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1259                               static_cast<int>(pointCenterY), GLColor::red);
1260     }
1261 }
1262 
GetFirstIntPixelRedValue()1263 GLint GetFirstIntPixelRedValue()
1264 {
1265     GLint pixel[4];
1266     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1267     return pixel[0];
1268 }
1269 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1270 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1271 {
1272     constexpr char kVS[] = R"(#version 300 es
1273     flat out highp int vVertexID;
1274 
1275     void main() {
1276         vVertexID = gl_VertexID;
1277         gl_PointSize = 1.0;
1278         gl_Position = vec4(0,0,0,1);
1279     })";
1280 
1281     constexpr char kFS[] = R"(#version 300 es
1282     flat in highp int vVertexID;
1283     out highp int oVertexID;
1284     void main() {
1285         oVertexID = vVertexID;
1286     })";
1287 
1288     ANGLE_GL_PROGRAM(program, kVS, kFS);
1289     glUseProgram(program);
1290     glViewport(0, 0, 1, 1);
1291 
1292     GLTexture tex;
1293     glBindTexture(GL_TEXTURE_2D, tex);
1294     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1295     GLFramebuffer fb;
1296     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1297     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1298 
1299     EXPECT_GL_NO_ERROR();
1300 
1301     GLint clearData[4] = {42};
1302     glClearBufferiv(GL_COLOR, 0, clearData);
1303     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1304 
1305     const int kIndexDataSize = 5;
1306     GLushort indexData[]     = {1, 2, 5, 3, 10000};
1307     GLBuffer indexBuffer;
1308     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1309     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1310 
1311     for (size_t first = 0; first < kIndexDataSize; ++first)
1312     {
1313         for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1314         {
1315             glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1316                            reinterpret_cast<const void *>(first * 2u));
1317             GLint expected = indexData[first + count - 1];
1318             GLint actual   = GetFirstIntPixelRedValue();
1319             EXPECT_EQ(expected, actual);
1320         }
1321     }
1322     EXPECT_GL_NO_ERROR();
1323 }
1324 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1325 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1326 {
1327     constexpr char kVS[] = R"(#version 300 es
1328     flat out highp int vVertexID;
1329 
1330     void main() {
1331         vVertexID = gl_VertexID;
1332         gl_PointSize = 1.0;
1333         gl_Position = vec4(0,0,0,1);
1334     })";
1335 
1336     constexpr char kFS[] = R"(#version 300 es
1337     flat in highp int vVertexID;
1338     out highp int oVertexID;
1339     void main() {
1340         oVertexID = vVertexID;
1341     })";
1342 
1343     ANGLE_GL_PROGRAM(program, kVS, kFS);
1344     glUseProgram(program);
1345     glViewport(0, 0, 1, 1);
1346 
1347     GLTexture tex;
1348     glBindTexture(GL_TEXTURE_2D, tex);
1349     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1350     GLFramebuffer fb;
1351     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1352     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1353 
1354     EXPECT_GL_NO_ERROR();
1355 
1356     GLint clearData[4] = {42};
1357     glClearBufferiv(GL_COLOR, 0, clearData);
1358     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1359 
1360     const int kIndexDataSize = 5;
1361     GLubyte indexData[]      = {1, 2, 5, 3, 100};
1362     GLBuffer indexBuffer;
1363     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1364     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1365 
1366     for (size_t first = 0; first < kIndexDataSize; ++first)
1367     {
1368         for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1369         {
1370             glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1371                            reinterpret_cast<const void *>(first));
1372             GLint expected = indexData[first + count - 1];
1373             GLint actual   = GetFirstIntPixelRedValue();
1374             EXPECT_EQ(expected, actual);
1375         }
1376     }
1377     EXPECT_GL_NO_ERROR();
1378 }
1379 
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1380 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1381 {
1382     glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1383 
1384     GLint pixels[8];
1385     glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1386 
1387     GLint expected = indices[first + 1];
1388     EXPECT_EQ(expected, pixels[0]);
1389     EXPECT_EQ(expected, pixels[4]);
1390 }
1391 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1392 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1393 {
1394     constexpr char kVS[] = R"(#version 300 es
1395     flat out highp int vVertexID;
1396     layout(location = 0) in vec4 position;
1397 
1398     void main() {
1399         vVertexID = gl_VertexID;
1400         gl_Position = position;
1401     })";
1402 
1403     constexpr char kFS[] = R"(#version 300 es
1404     flat in highp int vVertexID;
1405     out highp int oVertexID;
1406     void main() {
1407         oVertexID = vVertexID;
1408     })";
1409 
1410     ANGLE_GL_PROGRAM(program, kVS, kFS);
1411     glUseProgram(program);
1412     glViewport(0, 0, 2, 1);
1413 
1414     GLTexture tex;
1415     glBindTexture(GL_TEXTURE_2D, tex);
1416     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1417     GLFramebuffer fb;
1418     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1419     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1420 
1421     EXPECT_GL_NO_ERROR();
1422 
1423     struct LR
1424     {
1425         LR() : X0(-1.0f), X1(1.0f) {}
1426         float X0;
1427         float X1;
1428     };
1429     constexpr int kNumVertices = 100;
1430     LR vertData[kNumVertices];
1431     GLBuffer buf;
1432     glBindBuffer(GL_ARRAY_BUFFER, buf);
1433     glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1434     glEnableVertexAttribArray(0);
1435     glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1436 
1437     GLint clearData[4] = {42};
1438     glClearBufferiv(GL_COLOR, 0, clearData);
1439     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1440 
1441     GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1442     GLBuffer indexBuffer;
1443     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1444     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1445 
1446     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1447     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1448     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1449     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1450 
1451     EXPECT_GL_NO_ERROR();
1452 }
1453 
1454 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1455 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1456 {
1457     // Draws lines via indices (glDrawElements). Each pair of indices
1458     // draws the next consecutive pixel. For 2 points, because we're
1459     // using int attributes, they must be "flat" and so the spec
1460     // says for a given line the value should come from the second
1461     // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1462     // Each line is only 1 pixel long so every other pixel should
1463     // be the default value.
1464     constexpr char kVS[] = R"(#version 300 es
1465     flat out highp int vVertexID;
1466     layout(location = 0) in float position;
1467     uniform float width;
1468 
1469     void main() {
1470         vVertexID = gl_VertexID;
1471         gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1472     })";
1473 
1474     constexpr char kFS[] = R"(#version 300 es
1475     flat in highp int vVertexID;
1476     out highp int oVertexID;
1477     void main() {
1478         oVertexID = vVertexID;
1479     })";
1480 
1481     GLubyte indexData[]          = {1, 4, 5, 2, 50, 61, 32, 33};
1482     constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1483     GLBuffer indexBuffer;
1484     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1485     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1486 
1487     ANGLE_GL_PROGRAM(program, kVS, kFS);
1488     glUseProgram(program);
1489     glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1490     glViewport(0, 0, kNumIndices, 1);
1491 
1492     GLTexture tex;
1493     glBindTexture(GL_TEXTURE_2D, tex);
1494     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1495     GLFramebuffer fb;
1496     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1497     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1498 
1499     constexpr int kNumVertices = 100;
1500     std::vector<float> vertData(kNumVertices, -1.0f);
1501     {
1502         int i = 0;
1503         for (GLubyte ndx : indexData)
1504         {
1505             vertData[ndx] = i++;
1506         }
1507     }
1508     GLBuffer buf;
1509     glBindBuffer(GL_ARRAY_BUFFER, buf);
1510     glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1511     glEnableVertexAttribArray(0);
1512     glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1513 
1514     GLint kDefaultValue = 42;
1515     GLint clearData[4]  = {kDefaultValue};
1516     glClearBufferiv(GL_COLOR, 0, clearData);
1517     EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1518 
1519     EXPECT_GL_NO_ERROR();
1520 
1521     glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1522 
1523     GLint pixels[kNumIndices * 4];
1524     glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1525 
1526     for (size_t i = 0; i < kNumIndices; ++i)
1527     {
1528         const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1529         const int actual   = pixels[i * 4];
1530         EXPECT_EQ(expected, actual);
1531     }
1532 
1533     EXPECT_GL_NO_ERROR();
1534 }
1535 
1536 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1537 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1538 {
1539     glDrawArrays(GL_POINTS, first, count);
1540 
1541     int pixel[4];
1542     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1543     // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1544     // pixels.
1545     if (err == static_cast<GLenum>(GL_NO_ERROR))
1546     {
1547         EXPECT_GL_NO_ERROR();
1548         EXPECT_EQ(pixel[0], first + count - 1);
1549     }
1550     else
1551     {
1552         // If we call this function with err set, we will allow the error, but check the pixels if
1553         // the error hasn't occurred.
1554         GLenum glError = glGetError();
1555         if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1556         {
1557             EXPECT_EQ(pixel[0], first + count - 1);
1558         }
1559     }
1560 }
1561 
1562 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1563 // is based off the WebGL test:
1564 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1565 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1566 {
1567     constexpr char kVS[] = R"(#version 300 es
1568 flat out highp int vVertexID;
1569 void main() {
1570     vVertexID = gl_VertexID;
1571     gl_Position = vec4(0,0,0,1);
1572     gl_PointSize = 1.0;
1573 })";
1574 
1575     constexpr char kFS[] = R"(#version 300 es
1576 flat in highp int vVertexID;
1577 out highp int oVertexID;
1578 void main() {
1579     oVertexID = vVertexID;
1580 })";
1581 
1582     ANGLE_GL_PROGRAM(program, kVS, kFS);
1583     glUseProgram(program);
1584     glViewport(0, 0, 1, 1);
1585 
1586     GLTexture texture;
1587     glBindTexture(GL_TEXTURE_2D, texture);
1588     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1589     GLFramebuffer fbo;
1590     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1591     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1592     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1593     EXPECT_GL_NO_ERROR();
1594 
1595     // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1596     GLint val[4] = {42};
1597     glClearBufferiv(GL_COLOR, 0, val);
1598     int pixel[4];
1599     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1600     EXPECT_EQ(pixel[0], val[0]);
1601 
1602     GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1603     GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1604     GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1605     GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1606     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1607     GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1608     GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1609     GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1610     GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1611     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1612 
1613     int32_t int32Max = 0x7FFFFFFF;
1614     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1615     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1616 }
1617 
1618 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1619 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1620 {
1621     // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
1622     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1623 
1624     constexpr int kStartIndex  = 5;
1625     constexpr int kArrayLength = 5;
1626     constexpr char kVS[]       = R"(#version 300 es
1627 precision highp float;
1628 void main() {
1629     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1630     gl_PointSize = 3.0;
1631 })";
1632 
1633     constexpr char kFS[] = R"(#version 300 es
1634 precision highp float;
1635 out vec4 outColor;
1636 void main() {
1637     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1638 })";
1639 
1640     ANGLE_GL_PROGRAM(program, kVS, kFS);
1641 
1642     glUseProgram(program);
1643     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1644 
1645     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1646     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1647     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1648     {
1649         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1650         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1651                               static_cast<int>(pointCenterY), GLColor::red);
1652     }
1653 }
1654 
TEST_P(GLSLTest,ElseIfRewriting)1655 TEST_P(GLSLTest, ElseIfRewriting)
1656 {
1657     constexpr char kVS[] =
1658         "attribute vec4 a_position;\n"
1659         "varying float v;\n"
1660         "void main() {\n"
1661         "  gl_Position = a_position;\n"
1662         "  v = 1.0;\n"
1663         "  if (a_position.x <= 0.5) {\n"
1664         "    v = 0.0;\n"
1665         "  } else if (a_position.x >= 0.5) {\n"
1666         "    v = 2.0;\n"
1667         "  }\n"
1668         "}\n";
1669 
1670     constexpr char kFS[] =
1671         "precision highp float;\n"
1672         "varying float v;\n"
1673         "void main() {\n"
1674         "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1675         "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1676         "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1677         "  gl_FragColor = color;\n"
1678         "}\n";
1679 
1680     ANGLE_GL_PROGRAM(program, kVS, kFS);
1681 
1682     drawQuad(program, "a_position", 0.5f);
1683 
1684     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1685     EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1686 }
1687 
TEST_P(GLSLTest,TwoElseIfRewriting)1688 TEST_P(GLSLTest, TwoElseIfRewriting)
1689 {
1690     constexpr char kVS[] =
1691         "attribute vec4 a_position;\n"
1692         "varying float v;\n"
1693         "void main() {\n"
1694         "  gl_Position = a_position;\n"
1695         "  if (a_position.x == 0.0) {\n"
1696         "    v = 1.0;\n"
1697         "  } else if (a_position.x > 0.5) {\n"
1698         "    v = 0.0;\n"
1699         "  } else if (a_position.x > 0.75) {\n"
1700         "    v = 0.5;\n"
1701         "  }\n"
1702         "}\n";
1703 
1704     constexpr char kFS[] =
1705         "precision highp float;\n"
1706         "varying float v;\n"
1707         "void main() {\n"
1708         "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1709         "}\n";
1710 
1711     ANGLE_GL_PROGRAM(program, kVS, kFS);
1712 }
1713 
TEST_P(GLSLTest,FrontFacingAndVarying)1714 TEST_P(GLSLTest, FrontFacingAndVarying)
1715 {
1716     EGLPlatformParameters platform = GetParam().eglParameters;
1717 
1718     constexpr char kVS[] = R"(attribute vec4 a_position;
1719 varying float v_varying;
1720 void main()
1721 {
1722     v_varying = a_position.x;
1723     gl_Position = a_position;
1724 })";
1725 
1726     constexpr char kFS[] = R"(precision mediump float;
1727 varying float v_varying;
1728 void main()
1729 {
1730     vec4 c;
1731 
1732     if (gl_FrontFacing)
1733     {
1734         c = vec4(v_varying, 0, 0, 1.0);
1735     }
1736     else
1737     {
1738         c = vec4(0, v_varying, 0, 1.0);
1739     }
1740     gl_FragColor = c;
1741 })";
1742 
1743     GLuint program = CompileProgram(kVS, kFS);
1744 
1745     // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1746     if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1747     {
1748         if (platform.majorVersion == 9 && platform.minorVersion == 3)
1749         {
1750             EXPECT_EQ(0u, program);
1751             return;
1752         }
1753     }
1754 
1755     // Otherwise, compilation should succeed
1756     EXPECT_NE(0u, program);
1757 }
1758 
1759 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1760 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1761 {
1762     // Draw with the first program.
1763     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1764     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1765     ASSERT_GL_NO_ERROR();
1766     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1767 
1768     // Clear and release shader compiler.
1769     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1770     glClear(GL_COLOR_BUFFER_BIT);
1771     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1772     glReleaseShaderCompiler();
1773     ASSERT_GL_NO_ERROR();
1774 
1775     // Draw with a second program.
1776     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1777     drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1778     ASSERT_GL_NO_ERROR();
1779     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1780 }
1781 
1782 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1783 TEST_P(GLSLTest_ES3, VersionMismatch)
1784 {
1785     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1786     EXPECT_EQ(0u, program);
1787 
1788     program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1789     EXPECT_EQ(0u, program);
1790 }
1791 
1792 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1793 TEST_P(GLSLTest, InvariantVaryingOut)
1794 {
1795     constexpr char kFS[] =
1796         "precision mediump float;\n"
1797         "varying float v_varying;\n"
1798         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1799 
1800     constexpr char kVS[] =
1801         "attribute vec4 a_position;\n"
1802         "invariant varying float v_varying;\n"
1803         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1804 
1805     GLuint program = CompileProgram(kVS, kFS);
1806     EXPECT_EQ(0u, program);
1807 }
1808 
1809 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1810 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1811 {
1812     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1813     // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1814     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1815 
1816     constexpr char kFS[] =
1817         "#version 300 es\n"
1818         "precision mediump float;\n"
1819         "in float v_varying;\n"
1820         "out vec4 my_FragColor;\n"
1821         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1822 
1823     constexpr char kVS[] =
1824         "#version 300 es\n"
1825         "in vec4 a_position;\n"
1826         "invariant out float v_varying;\n"
1827         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1828 
1829     GLuint program = CompileProgram(kVS, kFS);
1830     EXPECT_NE(0u, program);
1831 }
1832 
1833 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1834 TEST_P(GLSLTest, InvariantVaryingIn)
1835 {
1836     constexpr char kFS[] =
1837         "precision mediump float;\n"
1838         "invariant varying float v_varying;\n"
1839         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1840 
1841     constexpr char kVS[] =
1842         "attribute vec4 a_position;\n"
1843         "varying float v_varying;\n"
1844         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1845 
1846     GLuint program = CompileProgram(kVS, kFS);
1847     EXPECT_EQ(0u, program);
1848 }
1849 
1850 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1851 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1852 {
1853     constexpr char kFS[] =
1854         "#version 300 es\n"
1855         "precision mediump float;\n"
1856         "invariant in float v_varying;\n"
1857         "out vec4 my_FragColor;\n"
1858         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1859 
1860     constexpr char kVS[] =
1861         "#version 300 es\n"
1862         "in vec4 a_position;\n"
1863         "out float v_varying;\n"
1864         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1865 
1866     GLuint program = CompileProgram(kVS, kFS);
1867     EXPECT_EQ(0u, program);
1868 }
1869 
1870 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1871 TEST_P(GLSLTest, InvariantVaryingBoth)
1872 {
1873     constexpr char kFS[] =
1874         "precision mediump float;\n"
1875         "invariant varying float v_varying;\n"
1876         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1877 
1878     constexpr char kVS[] =
1879         "attribute vec4 a_position;\n"
1880         "invariant varying float v_varying;\n"
1881         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1882 
1883     GLuint program = CompileProgram(kVS, kFS);
1884     EXPECT_NE(0u, program);
1885 }
1886 
1887 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1888 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1889 {
1890     constexpr char kFS[] =
1891         "#version 300 es\n"
1892         "precision mediump float;\n"
1893         "invariant in float v_varying;\n"
1894         "out vec4 my_FragColor;\n"
1895         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1896 
1897     constexpr char kVS[] =
1898         "#version 300 es\n"
1899         "in vec4 a_position;\n"
1900         "invariant out float v_varying;\n"
1901         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1902 
1903     GLuint program = CompileProgram(kVS, kFS);
1904     EXPECT_EQ(0u, program);
1905 }
1906 
1907 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1908 TEST_P(GLSLTest, InvariantGLPosition)
1909 {
1910     constexpr char kFS[] =
1911         "precision mediump float;\n"
1912         "varying float v_varying;\n"
1913         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1914 
1915     constexpr char kVS[] =
1916         "attribute vec4 a_position;\n"
1917         "invariant gl_Position;\n"
1918         "varying float v_varying;\n"
1919         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1920 
1921     GLuint program = CompileProgram(kVS, kFS);
1922     EXPECT_NE(0u, program);
1923 }
1924 
1925 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1926 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1927 {
1928     constexpr char kFS[] =
1929         "#version 300 es\n"
1930         "precision mediump float;\n"
1931         "in float v_varying;\n"
1932         "out vec4 my_FragColor;\n"
1933         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1934 
1935     constexpr char kVS[] =
1936         "#version 300 es\n"
1937         "in vec4 a_position;\n"
1938         "invariant gl_Position;\n"
1939         "out float v_varying;\n"
1940         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1941 
1942     GLuint program = CompileProgram(kVS, kFS);
1943     EXPECT_NE(0u, program);
1944 }
1945 
1946 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1947 TEST_P(GLSLTest, InvariantAllBoth)
1948 {
1949     constexpr char kFS[] =
1950         "#pragma STDGL invariant(all)\n"
1951         "precision mediump float;\n"
1952         "varying float v_varying;\n"
1953         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1954 
1955     constexpr char kVS[] =
1956         "#pragma STDGL invariant(all)\n"
1957         "attribute vec4 a_position;\n"
1958         "varying float v_varying;\n"
1959         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1960 
1961     GLuint program = CompileProgram(kVS, kFS);
1962     EXPECT_EQ(0u, program);
1963 }
1964 
1965 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1966 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1967 {
1968     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1969 
1970     constexpr char kVS[] = R"(#version 310 es
1971 #extension GL_EXT_shader_io_blocks : require
1972 
1973 struct S
1974 {
1975     vec4 s;
1976 };
1977 
1978 out Output
1979 {
1980     vec4 x;
1981     invariant S s;
1982 };
1983 
1984 out S s2;
1985 
1986 void main(){
1987     x = vec4(0);
1988     s.s = vec4(1);
1989     s2.s = vec4(2);
1990     S s3 = s;
1991     s.s = s3.s;
1992 })";
1993 
1994     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1995     EXPECT_NE(0u, shader);
1996     glDeleteShader(shader);
1997 }
1998 
1999 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)2000 TEST_P(GLSLTest, MissingReturnFloat)
2001 {
2002     constexpr char kVS[] =
2003         "varying float v_varying;\n"
2004         "float f() { if (v_varying > 0.0) return 1.0; }\n"
2005         "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
2006 
2007     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2008     EXPECT_NE(0u, program);
2009 }
2010 
2011 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)2012 TEST_P(GLSLTest, MissingReturnVec2)
2013 {
2014     constexpr char kVS[] =
2015         "varying float v_varying;\n"
2016         "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
2017         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2018 
2019     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2020     EXPECT_NE(0u, program);
2021 }
2022 
2023 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)2024 TEST_P(GLSLTest, MissingReturnVec3)
2025 {
2026     constexpr char kVS[] =
2027         "varying float v_varying;\n"
2028         "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
2029         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2030 
2031     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2032     EXPECT_NE(0u, program);
2033 }
2034 
2035 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)2036 TEST_P(GLSLTest, MissingReturnVec4)
2037 {
2038     constexpr char kVS[] =
2039         "varying float v_varying;\n"
2040         "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
2041         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2042 
2043     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2044     EXPECT_NE(0u, program);
2045 }
2046 
2047 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)2048 TEST_P(GLSLTest, MissingReturnIVec4)
2049 {
2050     constexpr char kVS[] =
2051         "varying float v_varying;\n"
2052         "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
2053         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2054 
2055     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2056     EXPECT_NE(0u, program);
2057 }
2058 
2059 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)2060 TEST_P(GLSLTest, MissingReturnMat4)
2061 {
2062     constexpr char kVS[] =
2063         "varying float v_varying;\n"
2064         "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
2065         "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
2066 
2067     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2068     EXPECT_NE(0u, program);
2069 }
2070 
2071 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)2072 TEST_P(GLSLTest, MissingReturnStruct)
2073 {
2074     constexpr char kVS[] =
2075         "varying float v_varying;\n"
2076         "struct s { float a; int b; vec2 c; };\n"
2077         "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
2078         "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
2079 
2080     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2081     EXPECT_NE(0u, program);
2082 }
2083 
2084 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)2085 TEST_P(GLSLTest_ES3, MissingReturnArray)
2086 {
2087     constexpr char kVS[] =
2088         "#version 300 es\n"
2089         "in float v_varying;\n"
2090         "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2091         "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2092 
2093     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2094     EXPECT_NE(0u, program);
2095 }
2096 
2097 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2098 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2099 {
2100     constexpr char kVS[] =
2101         "#version 300 es\n"
2102         "in float v_varying;\n"
2103         "struct s { float a; int b; vec2 c; };\n"
2104         "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2105         "vec2(1.0, 1.0))); } }\n"
2106         "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2107 
2108     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2109     EXPECT_NE(0u, program);
2110 }
2111 
2112 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2113 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2114 {
2115     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2116     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2117 
2118     constexpr char kVS[] =
2119         "#version 300 es\n"
2120         "in float v_varying;\n"
2121         "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2122         "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2123         "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2124         "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2125 
2126     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2127     EXPECT_NE(0u, program);
2128 }
2129 
2130 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2131 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2132 {
2133     constexpr char kVS[] = R"(#version 300 es
2134 in float v_varying;
2135 struct s { float a; int b; vec2 c; };
2136 s[2] f()
2137 {
2138     return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2139 }
2140 void main()
2141 {
2142     gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2143 })";
2144 
2145     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2146     EXPECT_NE(0u, program);
2147 }
2148 
2149 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2150 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2151 {
2152     constexpr char kFS[] =
2153         "#version 300 es\n"
2154         "#pragma STDGL invariant(all)\n"
2155         "precision mediump float;\n"
2156         "in float v_varying;\n"
2157         "out vec4 my_FragColor;\n"
2158         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2159 
2160     constexpr char kVS[] =
2161         "#version 300 es\n"
2162         "#pragma STDGL invariant(all)\n"
2163         "in vec4 a_position;\n"
2164         "out float v_varying;\n"
2165         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2166 
2167     GLuint program = CompileProgram(kVS, kFS);
2168     EXPECT_EQ(0u, program);
2169 }
2170 
2171 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2172 TEST_P(GLSLTest, InvariantAllIn)
2173 {
2174     constexpr char kFS[] =
2175         "#pragma STDGL invariant(all)\n"
2176         "precision mediump float;\n"
2177         "varying float v_varying;\n"
2178         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2179 
2180     constexpr char kVS[] =
2181         "attribute vec4 a_position;\n"
2182         "varying float v_varying;\n"
2183         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2184 
2185     GLuint program = CompileProgram(kVS, kFS);
2186     EXPECT_NE(0u, program);
2187 }
2188 
2189 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2190 TEST_P(GLSLTest_ES3, InvariantAllIn)
2191 {
2192     constexpr char kFS[] =
2193         "#version 300 es\n"
2194         "#pragma STDGL invariant(all)\n"
2195         "precision mediump float;\n"
2196         "in float v_varying;\n"
2197         "out vec4 my_FragColor;\n"
2198         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2199 
2200     constexpr char kVS[] =
2201         "#version 300 es\n"
2202         "in vec4 a_position;\n"
2203         "out float v_varying;\n"
2204         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2205 
2206     GLuint program = CompileProgram(kVS, kFS);
2207     EXPECT_EQ(0u, program);
2208 }
2209 
2210 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2211 TEST_P(GLSLTest, InvariantAllOut)
2212 {
2213     constexpr char kFS[] =
2214         "precision mediump float;\n"
2215         "varying float v_varying;\n"
2216         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2217 
2218     constexpr char kVS[] =
2219         "#pragma STDGL invariant(all)\n"
2220         "attribute vec4 a_position;\n"
2221         "varying float v_varying;\n"
2222         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2223 
2224     GLuint program = CompileProgram(kVS, kFS);
2225     EXPECT_EQ(0u, program);
2226 }
2227 
2228 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2229 TEST_P(GLSLTest_ES3, InvariantAllOut)
2230 {
2231     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2232     // for varyings which are invariant in vertex shader,
2233     // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
2234     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2235 
2236     constexpr char kFS[] =
2237         "#version 300 es\n"
2238         "precision mediump float;\n"
2239         "in float v_varying;\n"
2240         "out vec4 my_FragColor;\n"
2241         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2242 
2243     constexpr char kVS[] =
2244         "#version 300 es\n"
2245         "#pragma STDGL invariant(all)\n"
2246         "in vec4 a_position;\n"
2247         "out float v_varying;\n"
2248         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2249 
2250     GLuint program = CompileProgram(kVS, kFS);
2251     EXPECT_NE(0u, program);
2252 }
2253 
TEST_P(GLSLTest,MaxVaryingVec4)2254 TEST_P(GLSLTest, MaxVaryingVec4)
2255 {
2256     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2257     // (http://anglebug.com/1291)
2258     ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2259 
2260     GLint maxVaryings = 0;
2261     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2262 
2263     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2264 }
2265 
2266 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2267 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2268 {
2269     GLint maxVaryings = 0;
2270     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2271 
2272     // Generate shader code that uses gl_FragCoord.
2273     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2274 }
2275 
2276 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2277 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2278 {
2279     GLint maxVaryings = 0;
2280     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2281 
2282     // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2283     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2284 }
2285 
2286 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2287 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2288 {
2289     GLint maxVaryings = 0;
2290     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2291 
2292     // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2293     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2294 }
2295 
2296 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2297 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2298 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2299 {
2300     ANGLE_SKIP_TEST_IF(!IsD3D9());
2301 
2302     GLint maxVaryings = 0;
2303     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2304 
2305     VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2306     VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2307     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2308 
2309     // Special case for gl_PointSize: we get it for free on D3D9.
2310     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2311 }
2312 
2313 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2314 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2315 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2316 {
2317     GLint maxVaryings = 0;
2318     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2319 
2320     // Generate shader code that uses gl_FragCoord.
2321     VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2322 }
2323 
TEST_P(GLSLTest,MaxVaryingVec3)2324 TEST_P(GLSLTest, MaxVaryingVec3)
2325 {
2326     GLint maxVaryings = 0;
2327     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2328 
2329     VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2330 }
2331 
TEST_P(GLSLTest,MaxVaryingVec3Array)2332 TEST_P(GLSLTest, MaxVaryingVec3Array)
2333 {
2334     GLint maxVaryings = 0;
2335     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2336 
2337     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2338 }
2339 
2340 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2341 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2342 {
2343     GLint maxVaryings = 0;
2344     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2345 
2346     VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2347 }
2348 
2349 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2350 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2351 {
2352     GLint maxVaryings = 0;
2353     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2354 
2355     VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2356 }
2357 
2358 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2359 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2360 {
2361     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2362     // (http://anglebug.com/3849)
2363     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2364 
2365     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2366     // (http://anglebug.com/1291)
2367     ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2368 
2369     GLint maxVaryings = 0;
2370     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2371 
2372     VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2373 }
2374 
2375 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2376 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2377 {
2378     ANGLE_SKIP_TEST_IF(IsD3D9());
2379 
2380     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2381     ANGLE_SKIP_TEST_IF(IsOpenGLES());
2382 
2383     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2384     // (http://anglebug.com/1291)
2385     ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2386 
2387     GLint maxVaryings = 0;
2388     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2389 
2390     // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2391     // we should be aware that when we're packing into an odd number of varying registers the
2392     // last row will be empty and can not fit the final vec2 arrary.
2393     GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2394 
2395     VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2396 }
2397 
2398 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2399 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2400 {
2401     // (http://anglebug.com/4439)
2402     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2403 
2404     // http://anglebug.com/4446
2405     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
2406 
2407     GLint maxVaryings = 0;
2408     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2409 
2410     std::stringstream vertexShaderSource;
2411     std::stringstream fragmentShaderSource;
2412 
2413     // substract 1 here for gl_PointSize
2414     const GLint vec4Count     = maxVaryings - 1;
2415     unsigned int varyingCount = 0;
2416     std::string varyingDeclaration;
2417     for (GLint i = 0; i < vec4Count; i++)
2418     {
2419         varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2420         varyingCount += 1;
2421     }
2422     // Generate the vertex shader
2423     vertexShaderSource.clear();
2424     vertexShaderSource << varyingDeclaration;
2425     vertexShaderSource << "\nattribute vec4 a_position;\n";
2426     vertexShaderSource << "\nvoid main()\n{\n";
2427     unsigned int currentVSVarying = 0;
2428     for (GLint i = 0; i < vec4Count; i++)
2429     {
2430         vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2431         currentVSVarying += 1;
2432     }
2433     vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2434     vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2435     vertexShaderSource << "}\n";
2436 
2437     // Generate the fragment shader
2438     fragmentShaderSource.clear();
2439     fragmentShaderSource << "precision highp float;\n";
2440     fragmentShaderSource << varyingDeclaration;
2441     fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2442     unsigned int currentFSVarying = 0;
2443     // Make use of the vec4 varyings
2444     fragmentShaderSource << "\tretColor += ";
2445     for (GLint i = 0; i < vec4Count; i++)
2446     {
2447         fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2448         currentFSVarying += 1;
2449     }
2450     fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2451     constexpr GLuint testValue = 234;
2452     fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2453                          << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2454     fragmentShaderSource << "}\n";
2455 
2456     std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2457     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2458                                         fragmentShaderSource.str().c_str(), tfVaryings,
2459                                         GL_INTERLEAVED_ATTRIBS);
2460 
2461     GLBuffer xfbBuffer;
2462     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2463     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2464                  GL_STATIC_DRAW);
2465 
2466     GLTransformFeedback xfb;
2467     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2468     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2469 
2470     glUseProgram(program1);
2471 
2472     const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2473     GLBuffer vertexBuffer;
2474     // need to shift half pixel to make sure the line covers the center of the pixel
2475     const Vector3 vertices[2] = {
2476         {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2477         {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2478     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2479     glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2480     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2481     glEnableVertexAttribArray(positionLocation);
2482 
2483     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2484     glClear(GL_COLOR_BUFFER_BIT);
2485 
2486     glBeginTransformFeedback(GL_LINES);
2487     glDrawArrays(GL_LINES, 0, 2);
2488     glEndTransformFeedback();
2489 
2490     ASSERT_GL_NO_ERROR();
2491 
2492     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2493 }
2494 
2495 // Verify shader source with a fixed length that is less than the null-terminated length will
2496 // compile.
TEST_P(GLSLTest,FixedShaderLength)2497 TEST_P(GLSLTest, FixedShaderLength)
2498 {
2499     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2500 
2501     const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2502     const std::string source   = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2503     const char *sourceArray[1] = {source.c_str()};
2504     GLint lengths[1]           = {static_cast<GLint>(source.length() - appendGarbage.length())};
2505     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2506     glCompileShader(shader);
2507 
2508     GLint compileResult;
2509     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2510     EXPECT_NE(compileResult, 0);
2511 }
2512 
2513 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2514 TEST_P(GLSLTest, NegativeShaderLength)
2515 {
2516     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2517 
2518     const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2519     GLint lengths[1]           = {-10};
2520     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2521     glCompileShader(shader);
2522 
2523     GLint compileResult;
2524     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2525     EXPECT_NE(compileResult, 0);
2526 }
2527 
2528 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2529 TEST_P(GLSLTest, InvalidFieldFirstChar)
2530 {
2531     GLuint shader      = glCreateShader(GL_VERTEX_SHADER);
2532     const char *source = "void main() {vec4 x; x.}";
2533     glShaderSource(shader, 1, &source, 0);
2534     glCompileShader(shader);
2535 
2536     GLint compileResult;
2537     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2538     EXPECT_EQ(0, compileResult);
2539 }
2540 
2541 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2542 TEST_P(GLSLTest, MixedShaderLengths)
2543 {
2544     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2545 
2546     const char *sourceArray[] = {
2547         "void main()",
2548         "{",
2549         "    gl_FragColor = vec4(0, 0, 0, 0);",
2550         "}",
2551     };
2552     GLint lengths[] = {
2553         -10,
2554         1,
2555         static_cast<GLint>(strlen(sourceArray[2])),
2556         -1,
2557     };
2558     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2559 
2560     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2561     glCompileShader(shader);
2562 
2563     GLint compileResult;
2564     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2565     EXPECT_NE(compileResult, 0);
2566 }
2567 
2568 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2569 TEST_P(GLSLTest, ZeroShaderLength)
2570 {
2571     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2572 
2573     const char *sourceArray[] = {
2574         "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2575     };
2576     GLint lengths[] = {
2577         0, 0, -1, 0, 0,
2578     };
2579     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2580 
2581     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2582     glCompileShader(shader);
2583 
2584     GLint compileResult;
2585     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2586     EXPECT_NE(compileResult, 0);
2587 }
2588 
2589 // Tests that bad index expressions don't crash ANGLE's translator.
2590 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2591 TEST_P(GLSLTest, BadIndexBug)
2592 {
2593     constexpr char kFSSourceVec[] =
2594         "precision mediump float;\n"
2595         "uniform vec4 uniformVec;\n"
2596         "void main()\n"
2597         "{\n"
2598         "    gl_FragColor = vec4(uniformVec[int()]);\n"
2599         "}";
2600 
2601     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2602     EXPECT_EQ(0u, shader);
2603 
2604     if (shader != 0)
2605     {
2606         glDeleteShader(shader);
2607     }
2608 
2609     constexpr char kFSSourceMat[] =
2610         "precision mediump float;\n"
2611         "uniform mat4 uniformMat;\n"
2612         "void main()\n"
2613         "{\n"
2614         "    gl_FragColor = vec4(uniformMat[int()]);\n"
2615         "}";
2616 
2617     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2618     EXPECT_EQ(0u, shader);
2619 
2620     if (shader != 0)
2621     {
2622         glDeleteShader(shader);
2623     }
2624 
2625     constexpr char kFSSourceArray[] =
2626         "precision mediump float;\n"
2627         "uniform vec4 uniformArray;\n"
2628         "void main()\n"
2629         "{\n"
2630         "    gl_FragColor = vec4(uniformArray[int()]);\n"
2631         "}";
2632 
2633     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2634     EXPECT_EQ(0u, shader);
2635 
2636     if (shader != 0)
2637     {
2638         glDeleteShader(shader);
2639     }
2640 }
2641 
2642 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2643 TEST_P(GLSLTest, StructSpecifiersUniforms)
2644 {
2645     constexpr char kFS[] = R"(precision mediump float;
2646 
2647 uniform struct S { float field; } s;
2648 
2649 void main()
2650 {
2651     gl_FragColor = vec4(1, 0, 0, 1);
2652     gl_FragColor.a += s.field;
2653 })";
2654 
2655     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2656     EXPECT_NE(0u, program);
2657 }
2658 
2659 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2660 TEST_P(GLSLTest, StructWithInitializer)
2661 {
2662     constexpr char kFS[] = R"(precision mediump float;
2663 
2664 struct S { float a; } s = S(1.0);
2665 
2666 void main()
2667 {
2668     gl_FragColor = vec4(0, 0, 0, 1);
2669     gl_FragColor.r += s.a;
2670 })";
2671 
2672     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2673     glUseProgram(program);
2674 
2675     // Test drawing, should be red.
2676     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2677 
2678     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2679     EXPECT_GL_NO_ERROR();
2680 }
2681 
2682 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2683 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2684 {
2685     constexpr char kFS[] = R"(precision mediump float;
2686 
2687 struct S { float a; };
2688 uniform S u_s;
2689 
2690 void main()
2691 {
2692     gl_FragColor = vec4(u_s.a);
2693 })";
2694 
2695     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2696     glUseProgram(program);
2697 
2698     // Test drawing, should be red.
2699     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2700 
2701     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2702     EXPECT_GL_NO_ERROR();
2703 }
2704 
2705 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2706 TEST_P(GLSLTest, StructWithUniformInitializer)
2707 {
2708     constexpr char kFS[] = R"(precision mediump float;
2709 
2710 struct S { float a; } s = S(1.0);
2711 uniform S us;
2712 
2713 void main()
2714 {
2715     gl_FragColor = vec4(0, 0, 0, 1);
2716     gl_FragColor.r += s.a;
2717     gl_FragColor.g += us.a;
2718 })";
2719 
2720     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2721     glUseProgram(program);
2722 
2723     // Test drawing, should be red.
2724     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2725 
2726     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2727     EXPECT_GL_NO_ERROR();
2728 }
2729 
2730 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2731 // beginning with "gl_" are filtered out by our validation logic, we must
2732 // bypass the validation to test the behaviour of the implementation.
2733 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2734 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2735 {
2736     constexpr char kFS[] = R"(precision mediump float;
2737 
2738 void main()
2739 {
2740     gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2741 })";
2742 
2743     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2744 
2745     // We need to bypass validation for this call.
2746     GLint nearIndex = glGetUniformLocation(program, "gl_DepthRange.near");
2747     EXPECT_EQ(-1, nearIndex);
2748 
2749     // Test drawing does not throw an exception.
2750     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2751 
2752     EXPECT_GL_NO_ERROR();
2753 }
2754 
GenerateSmallPowShader(double base,double exponent)2755 std::string GenerateSmallPowShader(double base, double exponent)
2756 {
2757     std::stringstream stream;
2758 
2759     stream.precision(8);
2760 
2761     double result = pow(base, exponent);
2762 
2763     stream << "precision highp float;\n"
2764            << "float fun(float arg)\n"
2765            << "{\n"
2766            << "    return pow(arg, " << std::fixed << exponent << ");\n"
2767            << "}\n"
2768            << "\n"
2769            << "void main()\n"
2770            << "{\n"
2771            << "    const float a = " << std::scientific << base << ";\n"
2772            << "    float b = fun(a);\n"
2773            << "    if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2774            << "    {\n"
2775            << "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2776            << "    }\n"
2777            << "    else\n"
2778            << "    {\n"
2779            << "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2780            << "    }\n"
2781            << "}\n";
2782 
2783     return stream.str();
2784 }
2785 
2786 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2787 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)2788 TEST_P(GLSLTest, PowOfSmallConstant)
2789 {
2790     // Test with problematic exponents that are close to an integer.
2791     std::vector<double> testExponents;
2792     std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2793     for (double epsilonMultiplier : epsilonMultipliers)
2794     {
2795         for (int i = -4; i <= 5; ++i)
2796         {
2797             if (i >= -1 && i <= 1)
2798                 continue;
2799             const double epsilon = 1.0e-8;
2800             double bad           = static_cast<double>(i) + epsilonMultiplier * epsilon;
2801             testExponents.push_back(bad);
2802         }
2803     }
2804 
2805     // Also test with a few exponents that are not close to an integer.
2806     testExponents.push_back(3.6);
2807     testExponents.push_back(3.4);
2808 
2809     for (double testExponent : testExponents)
2810     {
2811         const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2812 
2813         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2814 
2815         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2816 
2817         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2818         EXPECT_GL_NO_ERROR();
2819     }
2820 }
2821 
2822 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2823 TEST_P(GLSLTest, LoopIndexingValidation)
2824 {
2825     constexpr char kFS[] = R"(precision mediump float;
2826 
2827 uniform float loopMax;
2828 
2829 void main()
2830 {
2831     gl_FragColor = vec4(1, 0, 0, 1);
2832     for (float l = 0.0; l < loopMax; l++)
2833     {
2834         if (loopMax > 3.0)
2835         {
2836             gl_FragColor.a += 0.1;
2837         }
2838     }
2839 })";
2840 
2841     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2842 
2843     const char *sourceArray[1] = {kFS};
2844     glShaderSource(shader, 1, sourceArray, nullptr);
2845     glCompileShader(shader);
2846 
2847     GLint compileResult;
2848     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2849 
2850     // If the test is configured to run limited to Feature Level 9_3, then it is
2851     // assumed that shader compilation will fail with an expected error message containing
2852     // "Loop index cannot be compared with non-constant expression"
2853     if (GetParam() == ES2_D3D9())
2854     {
2855         if (compileResult != 0)
2856         {
2857             FAIL() << "Shader compilation succeeded, expected failure";
2858         }
2859         else
2860         {
2861             GLint infoLogLength;
2862             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2863 
2864             std::string infoLog;
2865             infoLog.resize(infoLogLength);
2866             glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2867 
2868             if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2869                 std::string::npos)
2870             {
2871                 FAIL() << "Shader compilation failed with unexpected error message";
2872             }
2873         }
2874     }
2875     else
2876     {
2877         EXPECT_NE(0, compileResult);
2878     }
2879 
2880     if (shader != 0)
2881     {
2882         glDeleteShader(shader);
2883     }
2884 }
2885 
2886 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2887 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2888 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2889 {
2890     // crbug.com/680631
2891     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2892 
2893     int maxUniforms = 10000;
2894     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2895     EXPECT_GL_NO_ERROR();
2896     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2897 
2898     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2899 }
2900 
2901 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2902 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2903 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2904 {
2905     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2906 
2907     // Times out on D3D11 on test infra. http://anglebug.com/5076
2908     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2909 
2910     int maxUniforms = 10000;
2911     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2912     EXPECT_GL_NO_ERROR();
2913     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2914 
2915     int maxTextureImageUnits = 0;
2916     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2917 
2918     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2919 }
2920 
2921 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2922 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2923 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2924 {
2925     int maxUniforms = 10000;
2926     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2927     EXPECT_GL_NO_ERROR();
2928     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2929 
2930     CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2931 }
2932 
2933 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2934 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2935 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2936 {
2937     // crbug.com/680631
2938     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2939 
2940     int maxUniforms = 10000;
2941     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2942     EXPECT_GL_NO_ERROR();
2943     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2944 
2945     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2946 }
2947 
2948 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2949 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2950 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2951 {
2952     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2953 
2954     int maxUniforms = 10000;
2955     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2956     EXPECT_GL_NO_ERROR();
2957 
2958     int maxTextureImageUnits = 0;
2959     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2960 
2961     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2962 }
2963 
2964 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2965 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2966 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2967 {
2968     int maxUniforms = 10000;
2969     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2970     EXPECT_GL_NO_ERROR();
2971     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2972               << std::endl;
2973 
2974     CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2975 }
2976 
2977 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2978 TEST_P(GLSLTest, TextureLOD)
2979 {
2980     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2981 
2982     constexpr char kFS[] =
2983         "#extension GL_EXT_shader_texture_lod : require\n"
2984         "uniform sampler2D u_texture;\n"
2985         "void main() {\n"
2986         "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2987         "0.0));\n"
2988         "}\n";
2989 
2990     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2991     ASSERT_NE(0u, shader);
2992     glDeleteShader(shader);
2993 }
2994 
2995 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2996 // function calls to use them in vertex shaders.  http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2997 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2998 {
2999     constexpr char kVS[] = R"(
3000   precision highp float;
3001   uniform int uni;
3002   uniform sampler2D texture;
3003 
3004   vec4 A();
3005 
3006   vec4 B() {
3007     vec4 a;
3008     for(int r=0; r<14; r++){
3009       if (r < uni) return vec4(0.0);
3010       a = A();
3011     }
3012     return a;
3013   }
3014 
3015   vec4 A() {
3016     return texture2D(texture, vec2(0.0, 0.0));
3017   }
3018 
3019   void main() {
3020     gl_Position = B();
3021   })";
3022 
3023     constexpr char kFS[] = R"(
3024 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
3025 )";
3026 
3027     ANGLE_GL_PROGRAM(program, kVS, kFS);
3028 }
3029 
3030 // Test to verify the a shader can have a sampler unused in a vertex shader
3031 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)3032 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
3033 {
3034     constexpr char kVS[] = R"(
3035 attribute vec2 position;
3036 varying mediump vec2 texCoord;
3037 uniform sampler2D tex;
3038 void main()
3039 {
3040     gl_Position = vec4(position, 0, 1);
3041     texCoord = position * 0.5 + vec2(0.5);
3042 })";
3043 
3044     constexpr char kFS[] = R"(
3045 varying mediump vec2 texCoord;
3046 uniform sampler2D tex;
3047 void main()
3048 {
3049     gl_FragColor = texture2D(tex, texCoord);
3050 })";
3051 
3052     ANGLE_GL_PROGRAM(program, kVS, kFS);
3053 
3054     // Initialize basic red texture.
3055     const std::vector<GLColor> redColors(4, GLColor::red);
3056     GLTexture texture;
3057     glBindTexture(GL_TEXTURE_2D, texture);
3058     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
3059     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3060     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3061     ASSERT_GL_NO_ERROR();
3062 
3063     drawQuad(program, "position", 0.0f);
3064 
3065     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
3066 }
3067 
3068 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)3069 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
3070 {
3071     constexpr char kFS[] =
3072         "precision mediump float;\n"
3073         "struct Data { mediump sampler2D data[2]; };\n"
3074         "uniform Data test[2];\n"
3075         "void main() {\n"
3076         "    gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
3077         "                        texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
3078         "                        texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
3079         "                        texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
3080         "}\n";
3081 
3082     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3083     glUseProgram(program);
3084     GLTexture textures[4];
3085     GLColor expected = MakeGLColor(32, 64, 96, 255);
3086     GLubyte data[8]  = {};  // 4 bytes of padding, so that texture can be initialized with 4 bytes
3087     memcpy(data, expected.data(), sizeof(expected));
3088     for (int i = 0; i < 4; i++)
3089     {
3090         int outerIdx = i % 2;
3091         int innerIdx = i / 2;
3092         glActiveTexture(GL_TEXTURE0 + i);
3093         glBindTexture(GL_TEXTURE_2D, textures[i]);
3094         // Each element provides two components.
3095         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3096         std::stringstream uniformName;
3097         uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3098         // Then send it as a uniform
3099         GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
3100         // The uniform should be active.
3101         EXPECT_NE(uniformLocation, -1);
3102 
3103         glUniform1i(uniformLocation, 3 - i);
3104     }
3105     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3106     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3107 }
3108 
3109 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3110 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3111 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3112 {
3113     constexpr const char *kFS = R"(
3114 #if __VERSION__ >= 300
3115     inout mediump vec4 fragData;
3116 #else
3117     #extension GL_EXT_shader_texture_lod :enable
3118 #endif
3119 
3120 void main()
3121 {
3122 }
3123     )";
3124 
3125     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3126     EXPECT_NE(0u, shader);
3127 }
3128 
3129 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3130 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3131 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3132 {
3133     constexpr char kVS[] =
3134         "#version 300 es\n"
3135         "precision highp float;\n"
3136         "in vec4 a_vec;\n"
3137         "in mat2 a_mat;\n"
3138         "void main()\n"
3139         "{\n"
3140         "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3141         "}";
3142 
3143     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3144     EXPECT_NE(0u, program);
3145 }
3146 
3147 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3148 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3149 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3150 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3151 {
3152     constexpr char kVS[] =
3153         "#version 300 es\n"
3154         "precision highp float;\n"
3155         "in mat3x2 a_matA;\n"
3156         "in mat2x3 a_matB;\n"
3157         "void main()\n"
3158         "{\n"
3159         "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3160         "}";
3161 
3162     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3163     EXPECT_NE(0u, program);
3164 }
3165 
3166 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3167 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3168 {
3169     constexpr char kVS[] =
3170         "#version 300 es\n"
3171         "precision highp float;\n"
3172         "in vec4 a_vec;\n"
3173         "in mat2 a_mat;\n"
3174         "vec4 foo(vec4 a)\n"
3175         "{\n"
3176         "    return a;\n"
3177         "}\n"
3178         "vec4 foo(mat2 a)\n"
3179         "{\n"
3180         "    return vec4(a[0][0]);\n"
3181         "}\n"
3182         "void main()\n"
3183         "{\n"
3184         "    gl_Position = foo(a_vec) + foo(a_mat);\n"
3185         "}";
3186 
3187     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3188     EXPECT_NE(0u, program);
3189 }
3190 
3191 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3192 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3193 {
3194     constexpr char kFS[] = R"(#version 300 es
3195 precision highp float;
3196 out vec4 color;
3197 
3198 uniform int i;
3199 uniform uint u;
3200 uniform bool b;
3201 
3202 void main()
3203 {
3204     mat3x2 mi = mat3x2(i);
3205     mat4 mu = mat4(u);
3206     mat2x4 mb = mat2x4(b);
3207 
3208     mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3209 
3210     color = vec4(mi[0][0] == -123.0 ? 1 : 0,
3211                  mu[2][2] == 456.0 ? 1 : 0,
3212                  mb[1][1] == 1.0 ? 1 : 0,
3213                  m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0);
3214 })";
3215 
3216     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3217     glUseProgram(program);
3218 
3219     GLint iloc = glGetUniformLocation(program, "i");
3220     GLint uloc = glGetUniformLocation(program, "u");
3221     GLint bloc = glGetUniformLocation(program, "b");
3222     ASSERT_NE(iloc, -1);
3223     ASSERT_NE(uloc, -1);
3224     ASSERT_NE(bloc, -1);
3225     glUniform1i(iloc, -123);
3226     glUniform1ui(uloc, 456);
3227     glUniform1ui(bloc, 1);
3228 
3229     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3230     EXPECT_GL_NO_ERROR();
3231 
3232     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3233 }
3234 
3235 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3236 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3237 {
3238     constexpr char kFS[] = R"(#version 300 es
3239 precision highp float;
3240 out vec4 color;
3241 
3242 uniform ivec2 i;
3243 uniform uvec2 u;
3244 uniform bvec2 b;
3245 
3246 void main()
3247 {
3248     vec2 v2 = vec2(i.x, b);
3249     vec3 v3 = vec3(b, u);
3250     vec4 v4 = vec4(i, u);
3251 
3252     color = vec4(v2.x == -123.0 && v2.y == 1.0 ? 1 : 0,
3253                  v3.x == 1.0 && v3.y == 0.0 && v3.z == 456.0 ? 1 : 0,
3254                  v4.x == -123.0 && v4.y == -23.0 && v4.z == 456.0 && v4.w == 76.0 ? 1 : 0,
3255                  1);
3256 })";
3257 
3258     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3259     glUseProgram(program);
3260 
3261     GLint iloc = glGetUniformLocation(program, "i");
3262     GLint uloc = glGetUniformLocation(program, "u");
3263     GLint bloc = glGetUniformLocation(program, "b");
3264     ASSERT_NE(iloc, -1);
3265     ASSERT_NE(uloc, -1);
3266     ASSERT_NE(bloc, -1);
3267     glUniform2i(iloc, -123, -23);
3268     glUniform2ui(uloc, 456, 76);
3269     glUniform2ui(bloc, 1, 0);
3270 
3271     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3272     EXPECT_GL_NO_ERROR();
3273 
3274     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3275 }
3276 
3277 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3278 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3279 {
3280     constexpr char kFS[] = R"(#version 300 es
3281 precision highp float;
3282 out vec4 color;
3283 
3284 uniform float f;
3285 
3286 void main()
3287 {
3288     mat4 m = mat4(f);
3289     ivec3 vi = ivec3(m);
3290     uvec2 vu = uvec2(m);
3291     bvec4 vb = bvec4(m);
3292     bvec2 vb2 = bvec2(vi.x, m);
3293 
3294     color = vec4(vi.x == int(f) ? 1 : 0,
3295                  vu.x == uint(f) ? 1 : 0,
3296                  vb.x == bool(f) ? 1 : 0,
3297                  vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3298 })";
3299 
3300     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3301     glUseProgram(program);
3302 
3303     GLint floc = glGetUniformLocation(program, "f");
3304     ASSERT_NE(floc, -1);
3305     glUniform1f(floc, 123);
3306 
3307     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3308     EXPECT_GL_NO_ERROR();
3309 
3310     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3311 }
3312 
3313 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3314 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3315 {
3316     constexpr char kFS[] = R"(#version 300 es
3317 precision highp float;
3318 out vec4 color;
3319 
3320 uniform float f;
3321 uniform int i;
3322 uniform uint u;
3323 
3324 void main()
3325 {
3326     mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3327     mat3x2 m32_2 = mat3x2(m32_1);
3328     mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3329     mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3330     mat2x3 m23_2 = mat2x3(m23_1);
3331     mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3332     vec2 v2_1 = m32_1[0];
3333     vec2 v2_2 = m32_2[0];
3334     ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3335     ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3336     uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3337     uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3338 
3339     color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3340                  v2_1 == v2_2 ? 1 : 0,
3341                  (v3_1 == v3_2 ? 0.5 : 0.0) +
3342                     (v4_1 == v4_2 ? 0.5 : 0.0),
3343                  (m32_1 != m32_3 ? 0.125 : 0.0) +
3344                     (m23_1 != m23_3 ? 0.125 : 0.0) +
3345                     (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3346                     (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3347                     (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3348 })";
3349 
3350     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3351     glUseProgram(program);
3352 
3353     GLint floc = glGetUniformLocation(program, "f");
3354     GLint iloc = glGetUniformLocation(program, "i");
3355     GLint uloc = glGetUniformLocation(program, "u");
3356     ASSERT_NE(floc, -1);
3357     ASSERT_NE(iloc, -1);
3358     ASSERT_NE(uloc, -1);
3359     glUniform1f(floc, 1.5);
3360     glUniform1i(iloc, -123);
3361     glUniform1ui(uloc, 456);
3362 
3363     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3364     EXPECT_GL_NO_ERROR();
3365 
3366     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3367 }
3368 
3369 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3370 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3371 {
3372     constexpr char kFS[] = R"(#version 310 es
3373 precision highp float;
3374 out vec4 color;
3375 
3376 uniform float f;
3377 uniform int i;
3378 uniform uint u;
3379 
3380 struct S
3381 {
3382     float f;
3383     int i;
3384     uint u;
3385     vec4 v;
3386     ivec3 iv;
3387     uvec2 uv;
3388     mat3x2 m32;
3389     mat2x3 m23;
3390     float fa[3][4][5];
3391     int ia[4];
3392     uint ua[6][2];
3393 };
3394 
3395 struct T
3396 {
3397     S s1;
3398     S s2[3][2];
3399 };
3400 
3401 void main()
3402 {
3403     float fa[5] = float[5](f, f, f, f, f);
3404     int ia[4] = int[4](i, i, i, i);
3405     uint ua[2] = uint[2](u, u);
3406 
3407     S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3408              mat3x2(vec2(f), vec2(i), vec2(u)),
3409              mat2x3(vec3(f), vec3(i)),
3410              float[3][4][5](
3411                             float[4][5](fa, fa, fa, fa),
3412                             float[4][5](fa, fa, fa, fa),
3413                             float[4][5](fa, fa, fa, fa)),
3414              ia,
3415              uint[6][2](ua, ua, ua, ua, ua, ua));
3416 
3417     S s2[2] = S[2](s1, s1);
3418     s2[1].fa[0][1][2] = float(i);
3419 
3420     T t1 = T(s1, S[3][2](s2, s2, s2));
3421     T t2 = T(s2[1], S[3][2](s2, s2, s2));
3422 
3423     T ta1[2] = T[2](t1, t2);
3424     T ta2[2] = T[2](t1, t2);
3425     T ta3[2] = T[2](t2, t1);
3426 
3427     color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3428                  (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3429                  (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3430                  (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3431 })";
3432 
3433     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3434     glUseProgram(program);
3435 
3436     GLint floc = glGetUniformLocation(program, "f");
3437     GLint iloc = glGetUniformLocation(program, "i");
3438     GLint uloc = glGetUniformLocation(program, "u");
3439     ASSERT_NE(floc, -1);
3440     ASSERT_NE(iloc, -1);
3441     ASSERT_NE(uloc, -1);
3442     glUniform1f(floc, 1.5);
3443     glUniform1i(iloc, -123);
3444     glUniform1ui(uloc, 456);
3445 
3446     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3447     EXPECT_GL_NO_ERROR();
3448 
3449     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3450 }
3451 
3452 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3453 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3454 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3455 {
3456     std::stringstream vertexShaderStream;
3457     // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3458     const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3459 
3460     vertexShaderStream << "#version 300 es\n"
3461                           "precision highp float;\n"
3462                           "in vec4 a_vec;\n"
3463                           "vec4 lotsOfVec4Parameters(";
3464     for (unsigned int i = 0; i < paramCount - 1; ++i)
3465     {
3466         vertexShaderStream << "vec4 a" << i << ", ";
3467     }
3468     vertexShaderStream << "vec4 aLast)\n"
3469                           "{\n"
3470                           "    vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3471     for (unsigned int i = 0; i < paramCount - 1; ++i)
3472     {
3473         vertexShaderStream << "    sum += a" << i << ";\n";
3474     }
3475     vertexShaderStream << "    sum += aLast;\n"
3476                           "    return sum;\n "
3477                           "}\n"
3478                           "void main()\n"
3479                           "{\n"
3480                           "    gl_Position = lotsOfVec4Parameters(";
3481     for (unsigned int i = 0; i < paramCount - 1; ++i)
3482     {
3483         vertexShaderStream << "a_vec, ";
3484     }
3485     vertexShaderStream << "a_vec);\n"
3486                           "}";
3487 
3488     GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3489     EXPECT_NE(0u, program);
3490 }
3491 
3492 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3493 // Test a shader where a global constant array is initialized with an expression containing array
3494 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3495 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3496 // Also includes multiple array initializers in one declaration, where only the second one has
3497 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3498 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3499 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3500 {
3501     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
3502     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3503 
3504     constexpr char kFS[] =
3505         "#version 300 es\n"
3506         "precision highp float;\n"
3507         "out vec4 my_FragColor;\n"
3508         "const highp float f[2] = float[2](0.1, 0.2);\n"
3509         "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3510         "void main()\n"
3511         "{\n"
3512         "    my_FragColor = vec4(h[1]);\n"
3513         "}";
3514 
3515     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3516     EXPECT_NE(0u, program);
3517 }
3518 
3519 // Test that constant global matrix array with an initializer compiles.
TEST_P(GLSLTest_ES3,InitConstantMatrixArray)3520 TEST_P(GLSLTest_ES3, InitConstantMatrixArray)
3521 {
3522     constexpr char kFS[] = R"(#version 300 es
3523         precision highp float;
3524         uniform int index;
3525 
3526         const mat4 matrix = mat4(1.0);
3527         const mat4 array[1] = mat4[1](matrix);
3528         out vec4 my_FragColor;
3529         void main() {
3530             my_FragColor = vec4(array[index][1].rgb, 1.0);
3531         })";
3532 
3533     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3534 
3535     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3536     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3537 }
3538 
3539 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3540 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3541 {
3542     constexpr char kFS[] =
3543         "precision mediump float;\n"
3544         "uniform sampler2D uni[2];\n"
3545         "\n"
3546         "float zero(int x)\n"
3547         "{\n"
3548         "    return float(x) - float(x);\n"
3549         "}\n"
3550         "\n"
3551         "void main()\n"
3552         "{\n"
3553         "    vec4 c = vec4(0,0,0,0);\n"
3554         "    for (int ii = 1; ii < 3; ++ii) {\n"
3555         "        if (c.x > 255.0) {\n"
3556         "            c.x = 255.0 + zero(ii);\n"
3557         "            break;\n"
3558         "        }\n"
3559         // Index the sampler array with a predictable loop index (index-constant) as opposed to
3560         // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3561         // without an extension.
3562         "        c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3563         "    }\n"
3564         "    gl_FragColor = c;\n"
3565         "}";
3566 
3567     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3568     EXPECT_NE(0u, program);
3569 }
3570 
3571 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3572 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3573 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3574 TEST_P(GLSLTest, PragmaDirective)
3575 {
3576     constexpr char kVS[] =
3577         "#pragma STDGL invariant(all)\n"
3578         "void main()\n"
3579         "{\n"
3580         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3581         "}\n";
3582 
3583     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3584     EXPECT_NE(0u, program);
3585 }
3586 
3587 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3588 // The function call that returns the array needs to be evaluated after ++j for the expression to
3589 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3590 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3591 {
3592     constexpr char kFS[] =
3593         "#version 300 es\n"
3594         "precision mediump float;\n"
3595         "out vec4 my_FragColor; \n"
3596         "int[2] func(int param) {\n"
3597         "    return int[2](param, param);\n"
3598         "}\n"
3599         "void main() {\n"
3600         "    int a[2]; \n"
3601         "    for (int i = 0; i < 2; ++i) {\n"
3602         "        a[i] = 1;\n"
3603         "    }\n"
3604         "    int j = 0; \n"
3605         "    bool result = ((++j), (a == func(j)));\n"
3606         "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3607         "}\n";
3608 
3609     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3610     ASSERT_NE(0u, program);
3611 
3612     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3613 
3614     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3615 }
3616 
3617 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3618 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3619 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3620 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3621 {
3622     constexpr char kFS[] =
3623         "#version 300 es\n"
3624         "precision mediump float;\n"
3625         "out vec4 my_FragColor; \n"
3626         "void main() {\n"
3627         "    int j = 0; \n"
3628         "    bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3629         "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3630         "}\n";
3631 
3632     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3633     ASSERT_NE(0u, program);
3634 
3635     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3636 
3637     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3638 }
3639 
3640 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3641 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3642 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3643 {
3644     constexpr char kFS[] =
3645         "#version 300 es\n"
3646         "precision mediump float;\n"
3647         "out vec4 my_FragColor;\n"
3648         "uniform int u_zero;\n"
3649         "int sideEffectCount = 0;\n"
3650         "float func() {\n"
3651         "    ++sideEffectCount;\n"
3652         "    return -1.0;\n"
3653         "}\n"
3654         "void main() {\n"
3655         "    vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3656         "    float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3657         "    bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3658         "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3659         "}\n";
3660 
3661     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3662     ASSERT_NE(0u, program);
3663 
3664     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3665 
3666     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3667 }
3668 
3669 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3670 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3671 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)3672 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3673 {
3674     constexpr char kVS[] =
3675         "attribute vec2 aPosition;\n"
3676         "void main()\n"
3677         "{\n"
3678         "    gl_Position = vec4(aPosition, 0, 1);\n"
3679         "    gl_PointSize = 1.0;\n"
3680         "}";
3681     constexpr char kFS[] =
3682         "void main()\n"
3683         "{\n"
3684         "    gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3685         "    gl_FragColor = vec4(0, 1, 0, 1);\n"
3686         "}";
3687 
3688     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3689     drawQuad(prog, "aPosition", 0.5f);
3690     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3691 }
3692 
3693 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3694 TEST_P(GLSLTest, NestedPowStatements)
3695 {
3696     // https://crbug.com/1127866 - possible NVIDIA driver issue
3697     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3698 
3699     constexpr char kFS[] =
3700         "precision mediump float;\n"
3701         "float func(float v)\n"
3702         "{\n"
3703         "   float f1 = pow(v, 2.0);\n"
3704         "   return pow(f1 + v, 2.0);\n"
3705         "}\n"
3706         "void main()\n"
3707         "{\n"
3708         "    float v = func(2.0);\n"
3709         "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3710         "}";
3711 
3712     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3713     drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3714     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3715 }
3716 
3717 // This test covers a crash seen in an application during SPIR-V compilation
TEST_P(GLSLTest_ES3,NestedPowFromUniform)3718 TEST_P(GLSLTest_ES3, NestedPowFromUniform)
3719 {
3720     constexpr char kVS[] = R"(#version 300 es
3721 in vec2 position;
3722 void main()
3723 {
3724     gl_Position = vec4(position, 0, 1);
3725 })";
3726 
3727     constexpr char kFS[] = R"(#version 300 es
3728 precision mediump float;
3729 precision mediump int;
3730 
3731 uniform highp vec4 scale;
3732 out mediump vec4 out_FragColor;
3733 void main()
3734 {
3735     highp vec4 v0;
3736     v0 = scale;
3737     highp vec3 v1;
3738     v1.xyz = v0.xyz;
3739     if ((v0.y!=1.0))
3740     {
3741         vec3 v3;
3742         v3.xyz = pow(v0.xyz,v0.xxx);
3743         float h0;
3744         if ((v3.x < 3.13))
3745         {
3746             h0 = (v3.x * 1.29);
3747         }
3748         else
3749         {
3750             h0 = ((pow(v3.x,4.16)*1.055)+-5.5);
3751         }
3752         float h1;
3753         if ((v3.y<3.13))
3754         {
3755             h1 = (v3.y*1.29);
3756         }
3757         else
3758         {
3759             h1 = ((pow(v3.y,4.16)*1.055)+-5.5);
3760         }
3761         float h2;
3762         if ((v3.z<3.13))
3763         {
3764             h2 = (v3.z*1.29);
3765         }
3766         else
3767         {
3768             h2 = ((pow(v3.z,4.16)*1.055)+-5.5);
3769         }
3770         v1.xyz = vec3(h0, h1, h2);
3771     }
3772     out_FragColor = vec4(v1, v0.w);
3773 }
3774 )";
3775 
3776     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3777 
3778     GLint scaleIndex = glGetUniformLocation(prog, "scale");
3779     ASSERT_NE(-1, scaleIndex);
3780 
3781     glUseProgram(prog);
3782     glUniform4f(scaleIndex, 0.5, 0.5, 0.5, 0.5);
3783 
3784     // Don't crash
3785     drawQuad(prog, "position", 0.5f);
3786 }
3787 
3788 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3789 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3790 {
3791     constexpr char kFS[] =
3792         "#version 300 es\n"
3793         "out highp vec4 o_color;\n"
3794         "void main() {\n"
3795         "    highp float f = -1.0;\n"
3796         "    // atan(tan(0.5), -f) should be 0.5.\n"
3797         "    highp float v = atan(tan(0.5), -f);\n"
3798         "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3799         "}\n";
3800 
3801     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3802     drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3804 }
3805 
3806 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3807 TEST_P(GLSLTest_ES3, AtanVec2)
3808 {
3809     constexpr char kFS[] =
3810         "#version 300 es\n"
3811         "out highp vec4 o_color;\n"
3812         "void main() {\n"
3813         "    highp float f = 1.0;\n"
3814         "    // atan(tan(0.5), f) should be 0.5.\n"
3815         "    highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3816         "    o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3817         "vec4(1, 0, 0, 1);\n"
3818         "}\n";
3819 
3820     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3821     drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3822     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3823 }
3824 
3825 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3826 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3827 {
3828     constexpr char kVS[] =
3829         "#version 300 es\n"
3830         "in highp vec4 position;\n"
3831         "out mediump vec4 v_color;\n"
3832         "uniform int ui_one;\n"
3833         "uniform int ui_two;\n"
3834         "uniform int ui_three;\n"
3835         "void main() {\n"
3836         "    int s[3];\n"
3837         "    s[0] = ui_one;\n"
3838         "    s[1] = -(-(-ui_two + 1) + 1);\n"  // s[1] = -ui_two
3839         "    s[2] = ui_three;\n"
3840         "    int result = 0;\n"
3841         "    for (int i = 0; i < ui_three; i++) {\n"
3842         "        result += s[i];\n"
3843         "    }\n"
3844         "    v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3845         "    gl_Position = position;\n"
3846         "}\n";
3847     constexpr char kFS[] =
3848         "#version 300 es\n"
3849         "in mediump vec4 v_color;\n"
3850         "layout(location=0) out mediump vec4 o_color;\n"
3851         "void main() {\n"
3852         "    o_color = v_color;\n"
3853         "}\n";
3854 
3855     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3856 
3857     GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3858     ASSERT_NE(-1, oneIndex);
3859     GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3860     ASSERT_NE(-1, twoIndex);
3861     GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3862     ASSERT_NE(-1, threeIndex);
3863     glUseProgram(prog);
3864     glUniform1i(oneIndex, 1);
3865     glUniform1i(twoIndex, 2);
3866     glUniform1i(threeIndex, 3);
3867 
3868     drawQuad(prog, "position", 0.5f);
3869     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3870 }
3871 
3872 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3873 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3874 {
3875     constexpr char kVS[] =
3876         "#version 300 es\n"
3877         "in highp vec4 position;\n"
3878         "out mediump vec4 v_color;\n"
3879         "uniform uint ui_one;\n"
3880         "uniform uint ui_two;\n"
3881         "uniform uint ui_three;\n"
3882         "void main() {\n"
3883         "    uint s[3];\n"
3884         "    s[0] = ui_one;\n"
3885         "    s[1] = -(-(-ui_two + 1u) + 1u);\n"  // s[1] = -ui_two
3886         "    s[2] = ui_three;\n"
3887         "    uint result = 0u;\n"
3888         "    for (uint i = 0u; i < ui_three; i++) {\n"
3889         "        result += s[i];\n"
3890         "    }\n"
3891         "    v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3892         "    gl_Position = position;\n"
3893         "}\n";
3894     constexpr char kFS[] =
3895         "#version 300 es\n"
3896         "in mediump vec4 v_color;\n"
3897         "layout(location=0) out mediump vec4 o_color;\n"
3898         "void main() {\n"
3899         "    o_color = v_color;\n"
3900         "}\n";
3901 
3902     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3903 
3904     GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3905     ASSERT_NE(-1, oneIndex);
3906     GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3907     ASSERT_NE(-1, twoIndex);
3908     GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3909     ASSERT_NE(-1, threeIndex);
3910     glUseProgram(prog);
3911     glUniform1ui(oneIndex, 1u);
3912     glUniform1ui(twoIndex, 2u);
3913     glUniform1ui(threeIndex, 3u);
3914 
3915     drawQuad(prog, "position", 0.5f);
3916     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3917 }
3918 
3919 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3920 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3921 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3922 {
3923     // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3924     // its default value false.
3925     constexpr char kFS[] =
3926         "precision mediump float;\n"
3927         "uniform bool keep_flop_positive;\n"
3928         "float flop;\n"
3929         "void main() {\n"
3930         "    flop = -1.0,\n"
3931         "    (flop *= -1.0,\n"
3932         "    keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3933         "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
3934         "}";
3935 
3936     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3937     drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3938     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3939 }
3940 
3941 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3942 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3943 {
3944     // Note that the uniform doesn't need to be set, and will contain the default value of false.
3945     constexpr char kFS[] = R"(
3946 precision mediump float;
3947 uniform bool u;
3948 void main()
3949 {
3950     int a = u ? 12345 : 2;      // will be 2
3951     int b = u ? 12345 : 4;      // will be 4
3952     int c = u ? 12345 : 0;      // will be 0
3953 
3954     if (a == 2                  // true path is taken
3955         ? (b == 3               // false path is taken
3956             ? (a=0) != 0
3957             : b != 0            // true
3958           ) && (                // short-circuit evaluates RHS
3959             (a=7) == 7          // true, modifies a
3960             ||                  // short-circuit doesn't evaluate RHS
3961             (b=8) == 8
3962           )
3963         : (a == 0 && b == 0
3964             ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3965             : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3966     {
3967         c += 15;                // will execute
3968     }
3969 
3970     // Verify that a is 7, b is 4 and c is 15.
3971     gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3972 })";
3973 
3974     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3975     drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3976     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3977 }
3978 
3979 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)3980 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
3981 {
3982     constexpr char kFS[] = R"(#version 300 es
3983 precision mediump float;
3984 uniform bvec4 u;
3985 out vec4 color;
3986 
3987 bool f(bvec4 bv)
3988 {
3989     return all(bv.xz) && !any(bv.yw);
3990 }
3991 
3992 void main() {
3993     color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3994 })";
3995 
3996     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3997     glUseProgram(prog);
3998 
3999     GLint uloc = glGetUniformLocation(prog, "u");
4000     ASSERT_NE(uloc, -1);
4001     glUniform4ui(uloc, true, false, true, false);
4002 
4003     drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
4004     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4005 }
4006 
4007 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)4008 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
4009 {
4010     constexpr char kCS[] = R"(#version 310 es
4011 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4012 layout(binding = 0, std430) buffer Output {
4013     bvec4 b;
4014     bool valid;
4015 } outbuf;
4016 
4017 bool f_in(bvec4 bv)
4018 {
4019     return all(bv.xz) && !any(bv.yw);
4020 }
4021 
4022 bool f_inout(inout bvec4 bv)
4023 {
4024     bool ok = all(bv.xz) && !any(bv.yw);
4025     bv.xw = bvec2(false, true);
4026     return ok;
4027 }
4028 
4029 void f_out(out bvec4 bv)
4030 {
4031     bv = bvec4(false, true, false, true);
4032 }
4033 
4034 void main() {
4035     bool valid = f_in(outbuf.b);
4036     valid = f_inout(outbuf.b) && valid;
4037     f_out(outbuf.b);
4038     outbuf.valid = valid;
4039 })";
4040 
4041     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4042     glUseProgram(program);
4043 
4044     constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
4045     GLBuffer outputBuffer;
4046     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4047     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4048                  GL_STATIC_DRAW);
4049     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4050     EXPECT_GL_NO_ERROR();
4051 
4052     glDispatchCompute(1, 1, 1);
4053     EXPECT_GL_NO_ERROR();
4054 
4055     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4056 
4057     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4058         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4059     fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
4060     EXPECT_FALSE(ptr[0]);
4061     EXPECT_TRUE(ptr[1]);
4062     EXPECT_FALSE(ptr[2]);
4063     EXPECT_TRUE(ptr[3]);
4064     EXPECT_TRUE(ptr[4]);
4065     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4066 }
4067 
4068 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)4069 TEST_P(GLSLTest, ExternalAnd2DSampler)
4070 {
4071     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
4072 
4073     constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
4074 precision mediump float;
4075 uniform samplerExternalOES tex0;
4076 uniform sampler2D tex1;
4077 void main(void)
4078 {
4079     vec2 uv = vec2(0.0, 0.0);
4080     gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
4081 })";
4082 
4083     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4084 }
4085 
4086 // Tests that monomorphizing functions does not crash if there is a main prototype.
TEST_P(GLSLTest,MonomorphizeMainPrototypeNoCrash)4087 TEST_P(GLSLTest, MonomorphizeMainPrototypeNoCrash)
4088 {
4089     constexpr char kFS[] = R"(precision mediump float;
4090 struct S { sampler2D source; };
4091 vec4 f(S s)
4092 {
4093     return texture2D(s.source, vec2(5));
4094 }
4095 uniform S green;
4096 void main();
4097 void main() {
4098     f(green);
4099 })";
4100     CompileShader(GL_FRAGMENT_SHADER, kFS);
4101     ASSERT_GL_NO_ERROR();
4102 }
4103 
4104 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)4105 TEST_P(GLSLTest, VaryingMatrixArray)
4106 {
4107     constexpr char kVS[] =
4108         "uniform vec2 u_a1;\n"
4109         "uniform vec2 u_a2;\n"
4110         "attribute vec4 a_position;\n"
4111         "varying mat2 v_mat[2];\n"
4112         "void main() {\n"
4113         "    v_mat[0] = mat2(u_a1, u_a2);\n"
4114         "    v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
4115         "    gl_Position = a_position;\n"
4116         "}";
4117 
4118     constexpr char kFS[] =
4119         "precision mediump float;\n"
4120         "varying mat2 v_mat[2];\n"
4121         "void main(void)\n"
4122         "{\n"
4123         "    gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4124         "}";
4125 
4126     ANGLE_GL_PROGRAM(program, kVS, kFS);
4127 
4128     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4129     ASSERT_NE(-1, oneIndex);
4130     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4131     ASSERT_NE(-1, twoIndex);
4132     glUseProgram(program);
4133     glUniform2f(oneIndex, 1, 0.5f);
4134     glUniform2f(twoIndex, 0.25f, 0.125f);
4135 
4136     drawQuad(program, "a_position", 0.5f);
4137     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4138 }
4139 
4140 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)4141 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
4142 {
4143     // TODO(anglebug.com/5491): Skipping initial failures so we can set up a passing iOS test bot.
4144     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
4145 
4146     constexpr char kVS[] =
4147         "#version 300 es\n"
4148         "uniform vec2 u_a1;\n"
4149         "uniform vec2 u_a2;\n"
4150         "in vec4 a_position;\n"
4151         "centroid out mat3x2 v_mat[2];\n"
4152         "void main() {\n"
4153         "    v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
4154         "    v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
4155         "    gl_Position = a_position;\n"
4156         "}";
4157 
4158     constexpr char kFS[] =
4159         "#version 300 es\n"
4160         "precision mediump float;\n"
4161         "centroid in mat3x2 v_mat[2];\n"
4162         "layout(location = 0) out vec4 out_color;\n"
4163         "void main(void)\n"
4164         "{\n"
4165         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
4166         "}";
4167 
4168     ANGLE_GL_PROGRAM(program, kVS, kFS);
4169 
4170     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4171     ASSERT_NE(-1, oneIndex);
4172     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4173     ASSERT_NE(-1, twoIndex);
4174     glUseProgram(program);
4175     glUniform2f(oneIndex, 1, 0.5f);
4176     glUniform2f(twoIndex, 0.25f, 0.125f);
4177 
4178     drawQuad(program, "a_position", 0.5f);
4179     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4180 }
4181 
4182 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)4183 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
4184 {
4185     constexpr char kVS[] =
4186         "#version 300 es\n"
4187         "uniform vec2 u_a1;\n"
4188         "uniform vec2 u_a2;\n"
4189         "in vec4 a_position;\n"
4190         "flat out mat2 v_mat[2];\n"
4191         "void main() {\n"
4192         "    v_mat[0] = mat2(u_a1, u_a2);\n"
4193         "    v_mat[1] = mat2(u_a2, u_a1);\n"
4194         "    gl_Position = a_position;\n"
4195         "}";
4196 
4197     constexpr char kFS[] =
4198         "#version 300 es\n"
4199         "precision mediump float;\n"
4200         "flat in mat2 v_mat[2];\n"
4201         "layout(location = 0) out vec4 out_color;\n"
4202         "void main(void)\n"
4203         "{\n"
4204         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4205         "}";
4206 
4207     ANGLE_GL_PROGRAM(program, kVS, kFS);
4208 
4209     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4210     ASSERT_NE(-1, oneIndex);
4211     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4212     ASSERT_NE(-1, twoIndex);
4213     glUseProgram(program);
4214     glUniform2f(oneIndex, 1, 0.5f);
4215     glUniform2f(twoIndex, 0.25f, 0.125f);
4216 
4217     drawQuad(program, "a_position", 0.5f);
4218     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4219 }
4220 
4221 // Test that literal infinity can be written out from the shader translator.
4222 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralInfinityOutput)4223 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4224 {
4225     constexpr char kFS[] =
4226         "#version 300 es\n"
4227         "precision highp float;\n"
4228         "out vec4 out_color;\n"
4229         "uniform float u;\n"
4230         "void main()\n"
4231         "{\n"
4232         "   float infVar = 1.0e40 - u;\n"
4233         "   bool correct = isinf(infVar) && infVar > 0.0;\n"
4234         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4235         "}\n";
4236 
4237     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4238     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4239     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4240 }
4241 
4242 // Test that literal negative infinity can be written out from the shader translator.
4243 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralNegativeInfinityOutput)4244 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4245 {
4246     constexpr char kFS[] =
4247         "#version 300 es\n"
4248         "precision highp float;\n"
4249         "out vec4 out_color;\n"
4250         "uniform float u;\n"
4251         "void main()\n"
4252         "{\n"
4253         "   float infVar = -1.0e40 + u;\n"
4254         "   bool correct = isinf(infVar) && infVar < 0.0;\n"
4255         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4256         "}\n";
4257 
4258     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4259     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4260     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4261 }
4262 
4263 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4264 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4265 // a unittest for them. Instead we add the tests as end2end so will in particular test
4266 // TranslatorHLSL when run on Windows.
4267 
4268 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4269 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4270 {
4271     constexpr char kFS[] = R"(#version 300 es
4272 precision mediump float;
4273 out vec4 color;
4274 
4275 uniform float u;
4276 float c = 0.0;
4277 float sideEffect()
4278 {
4279     c = u;
4280     return c;
4281 }
4282 
4283 void main(void)
4284 {
4285     float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4286     color = vec4(b + c);
4287 })";
4288 
4289     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4290 }
4291 
4292 // Test that passes splitting multiple declarations and comma operators and for loops are
4293 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4294 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4295 {
4296     constexpr char kFS[] = R"(#version 300 es
4297 precision mediump float;
4298 out vec4 color;
4299 
4300 uniform float u;
4301 float c = 0.0;
4302 float sideEffect()
4303 {
4304     c = u;
4305     return c;
4306 }
4307 
4308 void main(void)
4309 {
4310     for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4311     {
4312         b += 1.0;
4313         color = vec4(b);
4314     }
4315 })";
4316 
4317     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4318 }
4319 
4320 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4321 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4322 {
4323     constexpr char kFS[] =
4324         "#version 300 es\n"
4325         "precision mediump float;\n"
4326         "out vec4 color;\n"
4327         "void main(void)\n"
4328         "{\n"
4329         " for(float a = 0.0, b = 1.0;; a++)\n"
4330         " {\n"
4331         "  b += 1.0;\n"
4332         "  if (a > 10.0) {break;}\n"
4333         "  color = vec4(b);\n"
4334         " }\n"
4335         "}\n";
4336 
4337     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4338 }
4339 
4340 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4341 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4342 {
4343     constexpr char kFS[] =
4344         "#version 300 es\n"
4345         "precision mediump float;\n"
4346         "out vec4 color;\n"
4347         "void main(void)\n"
4348         "{\n"
4349         " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4350         " {\n"
4351         "  b += 1.0;\n"
4352         "  a += 1.0;\n"
4353         "  color = vec4(b);\n"
4354         " }\n"
4355         "}\n";
4356 
4357     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4358 }
4359 
4360 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4361 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4362 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4363 {
4364     constexpr char kFS[] =
4365         "#version 300 es\n"
4366         "precision mediump float;\n"
4367         "out vec4 my_FragColor;\n"
4368         "uniform int u_zero;\n"
4369         "void main() {\n"
4370         "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4371         "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4372         "    float f = m[1][1];\n"
4373         "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4374         "}\n";
4375 
4376     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4377     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4378     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4379 }
4380 
4381 class WebGLGLSLTest : public GLSLTest
4382 {
4383   protected:
WebGLGLSLTest()4384     WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4385 };
4386 
4387 class WebGL2GLSLTest : public GLSLTest
4388 {
4389   protected:
WebGL2GLSLTest()4390     WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4391 };
4392 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4393 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4394 {
4395     GLint maxVaryings = 0;
4396     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4397 
4398     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4399     // This test should fail, since we are really using (maxVaryings + 1) varyings.
4400     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4401 }
4402 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4403 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4404 {
4405     GLint maxVaryings = 0;
4406     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4407 
4408     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4409     // This test should fail, since we are really using (maxVaryings + 1) varyings.
4410     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4411 }
4412 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4413 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4414 {
4415     GLint maxVaryings = 0;
4416     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4417 
4418     VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4419 }
4420 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4421 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4422 {
4423     GLint maxVaryings = 0;
4424     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4425 
4426     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4427 }
4428 
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4429 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4430 {
4431     GLint maxVaryings = 0;
4432     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4433 
4434     VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4435 }
4436 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4437 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4438 {
4439     GLint maxVaryings = 0;
4440     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4441 
4442     VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4443 }
4444 
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4445 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4446 {
4447     GLint maxVaryings = 0;
4448     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4449 
4450     VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4451                     false);
4452 }
4453 
4454 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4455 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4456 {
4457     // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4458     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4459 
4460     // Failing on N5X Oreo http://anglebug.com/2304
4461     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4462 
4463     constexpr char kFS[] =
4464         "#version 310 es\n"
4465         "precision mediump float;\n"
4466         "out vec4 my_FragColor;\n"
4467         "uniform int u_zero;\n"
4468         "void main() {\n"
4469         "    if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4470         "    {\n"
4471         "        my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4472         "    }\n"
4473         "    else\n"
4474         "    {\n"
4475         "        my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4476         "    }\n"
4477         "}\n";
4478 
4479     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4480     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4481     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4482 }
4483 
4484 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4485 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4486 {
4487     // http://anglebug.com/1924
4488     ANGLE_SKIP_TEST_IF(IsOpenGL());
4489 
4490     // The shader first assigns v.x to v.z (1.0)
4491     // Then v.y to v.y (2.0)
4492     // Then v.z to v.x (1.0)
4493     constexpr char kFS[] =
4494         "#version 300 es\n"
4495         "precision highp float;\n"
4496         "out vec4 my_FragColor;\n"
4497         "void main() {\n"
4498         "    vec3 v = vec3(1.0, 2.0, 3.0);\n"
4499         "    for (int i = 0; i < 3; i++) {\n"
4500         "        v.zyx[i] = v[i];\n"
4501         "    }\n"
4502         "    my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4503         "0, 0, 1);\n"
4504         "}\n";
4505 
4506     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4507     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4508     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4509 }
4510 
4511 // Test including Ternary using a uniform block is correctly
4512 // expanded.
TEST_P(GLSLTest_ES3,NamelessUniformBlockTernary)4513 TEST_P(GLSLTest_ES3, NamelessUniformBlockTernary)
4514 {
4515     const char kVS[] = R"(#version 300 es
4516     precision highp float;
4517     out vec4 color_interp;
4518     void  main()
4519     {
4520         color_interp = vec4(0.0);
4521     }
4522 )";
4523     const char kFS[] = R"(#version 300 es
4524     precision highp float;
4525     out vec4 fragColor;
4526     in vec4 color_interp;
4527 layout(std140) uniform TestData {
4528     int a;
4529     int b;
4530 };
4531 void main()
4532 {
4533     int c, a1;
4534     a1 += c > 0 ? a : b;
4535     fragColor = vec4(a1,a1,a1,1.0);
4536 }
4537 )";
4538     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4539 }
4540 
4541 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4542 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4543 {
4544     // Crashes on an assertion.  The driver reports no atomic counter buffers when queried from the
4545     // program, but ANGLE believes there to be one.
4546     //
4547     // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4548     // the code on which .length() is being called:
4549     //
4550     //     _uac1[(_uvalue = _utestSideEffectValue)];
4551     //
4552     // The driver is optimizing the subscription out, and calling the atomic counter inactive.  This
4553     // was observed on nvidia, mesa and amd/windows.
4554     //
4555     // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4556     // driver says don't.
4557     //
4558     // http://anglebug.com/3782
4559     ANGLE_SKIP_TEST_IF(IsOpenGL());
4560 
4561     constexpr char kCS[] = R"(#version 310 es
4562 precision mediump float;
4563 layout(local_size_x=1) in;
4564 
4565 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4566 uniform uint testSideEffectValue;
4567 
4568 layout(binding = 1, std140) buffer Result
4569 {
4570     uint value;
4571 } result;
4572 
4573 void main() {
4574     bool passed = true;
4575     if (ac1.length() != 2)
4576     {
4577         passed = false;
4578     }
4579     uint value = 0u;
4580     if (ac1[value = testSideEffectValue].length() != 3)
4581     {
4582         passed = false;
4583     }
4584     if (value != testSideEffectValue)
4585     {
4586         passed = false;
4587     }
4588     if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4589     {
4590         passed = false;
4591     }
4592     if (value != testSideEffectValue + 1u)
4593     {
4594         passed = false;
4595     }
4596     result.value = passed ? 255u : 127u;
4597 })";
4598 
4599     constexpr unsigned int kUniformTestValue     = 17;
4600     constexpr unsigned int kExpectedSuccessValue = 255;
4601     constexpr unsigned int kAtomicCounterRows    = 2;
4602     constexpr unsigned int kAtomicCounterCols    = 3;
4603 
4604     GLint maxAtomicCounters = 0;
4605     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4606     EXPECT_GL_NO_ERROR();
4607 
4608     // Required minimum is 8 by the spec
4609     EXPECT_GE(maxAtomicCounters, 8);
4610     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4611                        kAtomicCounterRows * kAtomicCounterCols);
4612 
4613     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4614     glUseProgram(program);
4615 
4616     constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4617     GLBuffer atomicCounterBuffer;
4618     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4619     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4620     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4621 
4622     constexpr unsigned int kOutputInitValue = 0;
4623     GLBuffer shaderStorageBuffer;
4624     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4625     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4626                  GL_STATIC_DRAW);
4627     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4628 
4629     GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4630     EXPECT_NE(uniformLocation, -1);
4631     glUniform1ui(uniformLocation, kUniformTestValue);
4632     EXPECT_GL_NO_ERROR();
4633 
4634     glDispatchCompute(1, 1, 1);
4635 
4636     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4637 
4638     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4639         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4640     EXPECT_EQ(*ptr, kExpectedSuccessValue);
4641     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4642 }
4643 
4644 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4645 TEST_P(GLSLTest_ES31, InactiveImages)
4646 {
4647     ANGLE_SKIP_TEST_IF(IsD3D11());
4648 
4649     constexpr char kCS[] = R"(#version 310 es
4650 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4651 layout(rgba32ui) uniform highp readonly uimage2D image1;
4652 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4653 void main()
4654 {
4655 })";
4656 
4657     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4658 
4659     glUseProgram(program);
4660     glDispatchCompute(1, 1, 1);
4661     EXPECT_GL_NO_ERROR();
4662 
4663     // Verify that the images are indeed inactive.
4664     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4665     EXPECT_GL_NO_ERROR();
4666     EXPECT_EQ(GL_INVALID_INDEX, index);
4667 
4668     index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4669     EXPECT_GL_NO_ERROR();
4670     EXPECT_EQ(GL_INVALID_INDEX, index);
4671 }
4672 
4673 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4674 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4675 {
4676     constexpr char kCS[] = R"(#version 310 es
4677 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4678 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4679 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4680 void main()
4681 {
4682 })";
4683 
4684     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4685 
4686     glUseProgram(program);
4687     glDispatchCompute(1, 1, 1);
4688     EXPECT_GL_NO_ERROR();
4689 
4690     // Verify that the atomic counters are indeed inactive.
4691     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4692     EXPECT_GL_NO_ERROR();
4693     EXPECT_EQ(GL_INVALID_INDEX, index);
4694 
4695     index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4696     EXPECT_GL_NO_ERROR();
4697     EXPECT_EQ(GL_INVALID_INDEX, index);
4698 }
4699 
4700 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4701 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4702 {
4703     constexpr char kCS[] = R"(#version 310 es
4704 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4705 struct S
4706 {
4707     vec4 v;
4708     sampler2D t[10];
4709 };
4710 uniform S s;
4711 void main()
4712 {
4713 })";
4714 
4715     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4716 
4717     glUseProgram(program);
4718     glDispatchCompute(1, 1, 1);
4719     EXPECT_GL_NO_ERROR();
4720 }
4721 
4722 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4723 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4724 {
4725     constexpr char kFS[] =
4726         "#version 310 es\n"
4727         "precision mediump float;\n"
4728         "out vec4 my_FragColor;\n"
4729         "uniform ivec2 test[2][2];\n"
4730         "void main() {\n"
4731         "    bool passed = true;\n"
4732         "    for (int i = 0; i < 2; i++) {\n"
4733         "        for (int j = 0; j < 2; j++) {\n"
4734         "            if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4735         "                passed = false;\n"
4736         "            }\n"
4737         "        }\n"
4738         "    }\n"
4739         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4740         "}\n";
4741 
4742     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4743     glUseProgram(program);
4744     for (int i = 0; i < 2; i++)
4745     {
4746         for (int j = 0; j < 2; j++)
4747         {
4748             std::stringstream uniformName;
4749             uniformName << "test[" << i << "][" << j << "]";
4750             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4751             // All array indices should be used.
4752             EXPECT_NE(uniformLocation, -1);
4753             glUniform2i(uniformLocation, i + 1, j + 1);
4754         }
4755     }
4756     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4757     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4758 }
4759 
4760 // Test that array indices for arrays of arrays of basic types work as expected
4761 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4762 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4763 {
4764     // anglebug.com/3821 - fails on AMD Windows
4765     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4766     constexpr char kFS[] =
4767         "#version 310 es\n"
4768         "precision mediump float;\n"
4769         "out vec4 my_FragColor;\n"
4770         "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4771         "void main() {\n"
4772         "    bool passed = true;\n"
4773         "    for (int i = 0; i < 2; i++) {\n"
4774         "        for (int j = 0; j < 2; j++) {\n"
4775         "            if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4776         "                passed = false;\n"
4777         "            }\n"
4778         "        }\n"
4779         "    }\n"
4780         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4781         "}\n";
4782 
4783     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4784     glUseProgram(program);
4785     // Use interface queries to determine buffer size and offset
4786     GLuint uboBlockIndex   = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "UBO");
4787     GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4788     GLint uboDataSize;
4789     glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4790                            nullptr, &uboDataSize);
4791     std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4792     for (int i = 0; i < 2; i++)
4793     {
4794         std::stringstream resourceName;
4795         resourceName << "UBO.test[" << i << "][0]";
4796         GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4797         struct
4798         {
4799             GLint stride;
4800             GLint offset;
4801         } values;
4802         GLuint resourceIndex =
4803             glGetProgramResourceIndex(program, GL_UNIFORM, resourceName.str().c_str());
4804         ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4805         glGetProgramResourceiv(program, GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2, nullptr,
4806                                &values.stride);
4807         for (int j = 0; j < 2; j++)
4808         {
4809             GLint(&dataPtr)[2] =
4810                 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4811             dataPtr[0] = i + 1;
4812             dataPtr[1] = j + 1;
4813         }
4814     }
4815     GLBuffer ubo;
4816     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
4817     glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4818     GLuint ubo_index = glGetUniformBlockIndex(program, "UBO");
4819     ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4820     glUniformBlockBinding(program, ubo_index, 5);
4821     glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo);
4822     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4823     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4824 }
4825 
4826 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4827 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4828 {
4829     constexpr char kFS[] =
4830         "#version 310 es\n"
4831         "precision mediump float;\n"
4832         "out vec4 my_FragColor;\n"
4833         "uniform mediump isampler2D test[2][2];\n"
4834         "void main() {\n"
4835         "    bool passed = true;\n"
4836         "#define DO_CHECK(i,j) \\\n"
4837         "    if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4838         "        passed = false; \\\n"
4839         "    }\n"
4840         "    DO_CHECK(0, 0)\n"
4841         "    DO_CHECK(0, 1)\n"
4842         "    DO_CHECK(1, 0)\n"
4843         "    DO_CHECK(1, 1)\n"
4844         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4845         "}\n";
4846 
4847     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4848     glUseProgram(program);
4849     GLTexture textures[2][2];
4850     for (int i = 0; i < 2; i++)
4851     {
4852         for (int j = 0; j < 2; j++)
4853         {
4854             // First generate the texture
4855             int textureUnit = i * 2 + j;
4856             glActiveTexture(GL_TEXTURE0 + textureUnit);
4857             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4858             GLint texData[2] = {i + 1, j + 1};
4859             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4860             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4861             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4862             // Then send it as a uniform
4863             std::stringstream uniformName;
4864             uniformName << "test[" << i << "][" << j << "]";
4865             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4866             // All array indices should be used.
4867             EXPECT_NE(uniformLocation, -1);
4868             glUniform1i(uniformLocation, textureUnit);
4869         }
4870     }
4871     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4872     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4873 }
4874 
4875 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4876 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4877 {
4878     // http://anglebug.com/5072
4879     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4880 
4881     // Fails on D3D due to mistranslation.
4882     ANGLE_SKIP_TEST_IF(IsD3D());
4883 
4884     // Fails on Android on GLES.
4885     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4886 
4887     GLint maxTextures, maxComputeImageUniforms;
4888     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4889     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4890     ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
4891     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
4892 
4893     constexpr char kComputeShader[] = R"(#version 310 es
4894         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4895         layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
4896         layout(binding = 1, std430) buffer Output {
4897             uint image_value;
4898         } outbuf;
4899 
4900         void main(void)
4901         {
4902             outbuf.image_value = uint(0.0);
4903             outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
4904             outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
4905             outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
4906             outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
4907             outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
4908             outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
4909         })";
4910     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4911     EXPECT_GL_NO_ERROR();
4912 
4913     glUseProgram(program);
4914 
4915     GLuint outputInitData[1] = {10};
4916     GLBuffer outputBuffer;
4917     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4918     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
4919     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
4920     EXPECT_GL_NO_ERROR();
4921 
4922     GLuint imageData = 200u;
4923     GLTexture images[1][2][3];
4924     for (int i = 0; i < 1; i++)
4925     {
4926         for (int j = 0; j < 2; j++)
4927         {
4928             for (int k = 0; k < 3; k++)
4929             {
4930                 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
4931                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4932                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4933                                 &imageData);
4934                 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
4935                                    GL_R32UI);
4936                 EXPECT_GL_NO_ERROR();
4937             }
4938         }
4939     }
4940 
4941     glDispatchCompute(1, 1, 1);
4942     EXPECT_GL_NO_ERROR();
4943 
4944     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4945 
4946     // read back
4947     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4948         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
4949     memcpy(outputInitData, ptr, sizeof(outputInitData));
4950     EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
4951     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4952 }
4953 
4954 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)4955 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
4956 {
4957     // http://anglebug.com/5072
4958     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4959 
4960     // Fails on D3D due to mistranslation.
4961     ANGLE_SKIP_TEST_IF(IsD3D());
4962 
4963     constexpr GLsizei kImage1Layers = 3;
4964     constexpr GLsizei kImage1Rows   = 2;
4965     constexpr GLsizei kImage1Cols   = 1;
4966     constexpr GLsizei kImage2Rows   = 2;
4967     constexpr GLsizei kImage2Cols   = 4;
4968 
4969     constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
4970     constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
4971     constexpr GLsizei kImage3Units = 1;
4972 
4973     constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
4974 
4975     GLint maxTextures, maxComputeImageUniforms;
4976     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4977     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4978     ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
4979     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
4980 
4981     constexpr char kComputeShader[] = R"(#version 310 es
4982         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4983         layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
4984         layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
4985         layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
4986         layout(binding = 0, std430) buffer Output {
4987             uint image_value;
4988         } outbuf;
4989 
4990         void main(void)
4991         {
4992             outbuf.image_value = uint(0.0);
4993 
4994             outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
4995             outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
4996             outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
4997             outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
4998             outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
4999             outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
5000 
5001             outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
5002             outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
5003             outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
5004             outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
5005             outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
5006             outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
5007             outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
5008             outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
5009 
5010             outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
5011         })";
5012     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5013     EXPECT_GL_NO_ERROR();
5014 
5015     glUseProgram(program);
5016 
5017     constexpr GLuint kOutputInitData = 10;
5018     GLBuffer outputBuffer;
5019     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5020     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
5021                  GL_STATIC_DRAW);
5022     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5023     EXPECT_GL_NO_ERROR();
5024 
5025     constexpr GLsizei kImage1Binding = 0;
5026     constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
5027     constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
5028 
5029     constexpr GLuint kImage1Data = 13;
5030     GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
5031     for (int layer = 0; layer < kImage1Layers; layer++)
5032     {
5033         for (int row = 0; row < kImage1Rows; row++)
5034         {
5035             for (int col = 0; col < kImage1Cols; col++)
5036             {
5037                 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
5038                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5039                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5040                                 &kImage1Data);
5041                 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
5042                                    images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
5043                                    GL_R32UI);
5044                 EXPECT_GL_NO_ERROR();
5045             }
5046         }
5047     }
5048 
5049     constexpr GLuint kImage2Data = 17;
5050     GLTexture images2[kImage2Rows][kImage2Cols];
5051     for (int row = 0; row < kImage2Rows; row++)
5052     {
5053         for (int col = 0; col < kImage2Cols; col++)
5054         {
5055             glBindTexture(GL_TEXTURE_2D, images2[row][col]);
5056             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5057             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5058                             &kImage2Data);
5059             glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
5060                                GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5061             EXPECT_GL_NO_ERROR();
5062         }
5063     }
5064 
5065     constexpr GLuint kImage3Data = 19;
5066     GLTexture image3;
5067     glBindTexture(GL_TEXTURE_2D, image3);
5068     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5069     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
5070     glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5071     EXPECT_GL_NO_ERROR();
5072 
5073     glDispatchCompute(1, 1, 1);
5074     EXPECT_GL_NO_ERROR();
5075 
5076     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5077 
5078     // read back
5079     const GLuint *ptr = reinterpret_cast<const GLuint *>(
5080         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5081     EXPECT_EQ(*ptr,
5082               kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
5083     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5084 }
5085 
5086 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)5087 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
5088 {
5089     // Skip if GL_OES_shader_image_atomic is not enabled.
5090     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
5091 
5092     // http://anglebug.com/5072
5093     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5094 
5095     // Fails on D3D due to mistranslation.
5096     ANGLE_SKIP_TEST_IF(IsD3D());
5097 
5098     // Fails on Android on GLES.
5099     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5100 
5101     // http://anglebug.com/5353
5102     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
5103 
5104     GLint maxComputeImageUniforms;
5105     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5106     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
5107 
5108     constexpr char kComputeShader[] = R"(#version 310 es
5109 #extension GL_OES_shader_image_atomic : require
5110 
5111 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5112 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
5113 layout(binding = 6, r32f) uniform highp image2D image2;
5114 
5115 void testFunction(highp image2D imageOut[2][3])
5116 {
5117     // image1 is an array of 1x1 images.
5118     // image2 is a 1x4 image with the following data:
5119     //
5120     // (0, 0): 234.5
5121     // (0, 1): 4.0
5122     // (0, 2): 456.0
5123     // (0, 3): 987.0
5124 
5125 
5126     // Write to [0][0]
5127     imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
5128 
5129     // Write to [0][1]
5130     imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
5131 
5132     // Write to [0][2]
5133     imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
5134 
5135     // Write to [1][0]
5136     imageStore(imageOut[1][0], ivec2(0,
5137                  imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
5138                 ), vec4(678.0));
5139 
5140     // Write to [1][1]
5141     imageStore(imageOut[1][1], ivec2(0, 0),
5142                 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
5143 
5144     // Write to [1][2]
5145     imageStore(imageOut[1][2], ivec2(0, 0),
5146                     imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
5147 }
5148 
5149 void main(void)
5150 {
5151     testFunction(image1);
5152 })";
5153     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5154     EXPECT_GL_NO_ERROR();
5155 
5156     glUseProgram(program);
5157 
5158     constexpr GLsizei kImageRows = 2;
5159     constexpr GLsizei kImageCols = 3;
5160     constexpr GLfloat kImageData = 0;
5161     GLTexture images[kImageRows][kImageCols];
5162     for (size_t row = 0; row < kImageRows; row++)
5163     {
5164         for (size_t col = 0; col < kImageCols; col++)
5165         {
5166             glBindTexture(GL_TEXTURE_2D, images[row][col]);
5167             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
5168             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
5169             glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
5170                                GL_READ_WRITE, GL_R32F);
5171             EXPECT_GL_NO_ERROR();
5172         }
5173     }
5174 
5175     constexpr GLsizei kImage2Size                          = 4;
5176     constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
5177         234.5f,
5178         4.0f,
5179         456.0f,
5180         987.0f,
5181     };
5182     GLTexture image2;
5183     glBindTexture(GL_TEXTURE_2D, image2);
5184     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
5185     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
5186     glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
5187     EXPECT_GL_NO_ERROR();
5188 
5189     glDispatchCompute(1, 1, 1);
5190     EXPECT_GL_NO_ERROR();
5191 
5192     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5193 
5194     // Verify the previous dispatch with another dispatch
5195     constexpr char kVerifyShader[] = R"(#version 310 es
5196 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5197 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
5198 layout(binding = 6, r32f) uniform highp readonly image2D image2;
5199 layout(binding = 0, std430) buffer Output {
5200     float image2Data[4];
5201     float image1Data[6];
5202 } outbuf;
5203 
5204 void main(void)
5205 {
5206     for (int i = 0; i < 4; ++i)
5207     {
5208         outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
5209     }
5210     outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
5211     outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
5212     outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
5213     outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
5214     outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
5215     outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
5216 })";
5217     ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
5218     EXPECT_GL_NO_ERROR();
5219 
5220     glUseProgram(verifyProgram);
5221 
5222     constexpr std::array<GLfloat, kImage2Size + kImageRows * kImageCols> kOutputInitData = {};
5223     GLBuffer outputBuffer;
5224     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5225     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
5226                  GL_STATIC_DRAW);
5227     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5228     EXPECT_GL_NO_ERROR();
5229 
5230     glDispatchCompute(1, 1, 1);
5231     EXPECT_GL_NO_ERROR();
5232 
5233     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5234 
5235     // Verify
5236     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5237         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5238 
5239     EXPECT_EQ(ptr[0], kImage2Data[0]);
5240     EXPECT_EQ(ptr[1], kImage2Data[1]);
5241     EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5242     EXPECT_EQ(ptr[3], kImage2Data[3]);
5243 
5244     EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5245     EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5246     EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5247     EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5248     EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5249     EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5250 
5251     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5252 }
5253 
5254 // Check that imageLoad gives the correct color after clearing the texture -- anglebug.com/7355
TEST_P(GLSLTest_ES31,ImageLoadAfterClear)5255 TEST_P(GLSLTest_ES31, ImageLoadAfterClear)
5256 {
5257     ANGLE_GL_PROGRAM(program,
5258                      R"(#version 310 es
5259 precision highp float;
5260 void main()
5261 {
5262     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5263     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5264     gl_Position.zw = vec2(0, 1);
5265 })",
5266 
5267                      R"(#version 310 es
5268 precision highp float;
5269 layout(binding=0, rgba8) readonly highp uniform image2D img;
5270 out vec4 fragColor;
5271 void main()
5272 {
5273     ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5274     fragColor = vec4(1, 0, 0, 0) + imageLoad(img, imgcoord);
5275 })");
5276     ASSERT_TRUE(program.valid());
5277     glUseProgram(program);
5278 
5279     GLTexture tex;
5280     glBindTexture(GL_TEXTURE_2D, tex);
5281     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5282     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5283 
5284     // Clear the texture to green.
5285     GLFramebuffer fbo;
5286     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5287     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5288     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5289     glClearColor(0, 1, 0, 1);
5290     glClear(GL_COLOR_BUFFER_BIT);
5291     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
5292 
5293     // Draw the texture via imageLoad, plus red, into the main framebuffer. Make sure the texture
5294     // was still green. (green + red == yellow.)
5295     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5296     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5297     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5298 
5299     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5300     ASSERT_GL_NO_ERROR();
5301 }
5302 
5303 // Check that writeonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,WriteOnlyImage2DAsFunctionArg)5304 TEST_P(GLSLTest_ES31, WriteOnlyImage2DAsFunctionArg)
5305 {
5306     // Create an image.
5307     GLTexture tex;
5308     glBindTexture(GL_TEXTURE_2D, tex);
5309     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5310 
5311     // Clear the image to red.
5312     GLFramebuffer fbo;
5313     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5314     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5315     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5316 
5317     glClearColor(1, 0, 0, 1);
5318     glClear(GL_COLOR_BUFFER_BIT);
5319     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5320 
5321     const char kVS[] = R"(#version 310 es
5322 precision highp float;
5323 void main()
5324 {
5325     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5326     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5327     gl_Position.zw = vec2(0, 1);
5328 })";
5329 
5330     const char kFS[] = R"(#version 310 es
5331 precision highp float;
5332 layout(binding=0, rgba8) writeonly highp uniform image2D uniformImage;
5333 void store(writeonly highp image2D img, vec4 color)
5334 {
5335     ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5336     imageStore(img, imgcoord, color);
5337 }
5338 void main()
5339 {
5340     store(uniformImage, vec4(1, 1, 0, 1));
5341 })";
5342 
5343     // Store yellow to the image.
5344     ANGLE_GL_PROGRAM(program, kVS, kFS);
5345     glUseProgram(program);
5346 
5347     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5348     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5349     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5350     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5351 
5352     // Check that the image is yellow.
5353     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5354     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5355     ASSERT_GL_NO_ERROR();
5356 }
5357 
5358 // Check that readonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,ReadOnlyImage2DAsFunctionArg)5359 TEST_P(GLSLTest_ES31, ReadOnlyImage2DAsFunctionArg)
5360 {
5361     const int w = getWindowWidth();
5362     const int h = getWindowHeight();
5363 
5364     // Create an image.
5365     GLTexture tex;
5366     glBindTexture(GL_TEXTURE_2D, tex);
5367     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5368 
5369     const std::vector<GLColor> kInitData(w * h, GLColor::red);
5370     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, kInitData.data());
5371 
5372     // Create a framebuffer.
5373     GLTexture color;
5374     glBindTexture(GL_TEXTURE_2D, color);
5375     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5376 
5377     GLFramebuffer fbo;
5378     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5379     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5380     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5381 
5382     // Initialize the framebuffer with the contents of the texture.
5383     glClearColor(0, 0, 0, 0);
5384     glClear(GL_COLOR_BUFFER_BIT);
5385 
5386     const char kVS[] = R"(#version 310 es
5387 precision highp float;
5388 void main()
5389 {
5390     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5391     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5392     gl_Position.zw = vec2(0, 1);
5393 })";
5394 
5395     const char kFS[] = R"(#version 310 es
5396 precision highp float;
5397 layout(binding=0, rgba8) readonly highp uniform image2D uniformImage;
5398 out vec4 color;
5399 vec4 load(readonly highp image2D img)
5400 {
5401     ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5402     return imageLoad(img, imgcoord);
5403 }
5404 void main()
5405 {
5406     color = load(uniformImage);
5407 })";
5408 
5409     ANGLE_GL_PROGRAM(program, kVS, kFS);
5410     glUseProgram(program);
5411 
5412     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5413     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5414 
5415     // Check that the framebuffer is red.
5416     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
5417     ASSERT_GL_NO_ERROR();
5418 }
5419 
5420 // Check that the volatile keyword combined with memoryBarrierImage() allow load/store from
5421 // different aliases of the same image -- anglebug.com/7343
5422 //
5423 // ES 3.1 requires most image formats to be either readonly or writeonly. (It appears that this
5424 // limitation exists due to atomics, since we still have the volatile keyword and the built-in
5425 // memoryBarrierImage(), which ought to allow us to load and store different aliases of the same
5426 // image.) To test this, we create two aliases of the same image -- one for reading and one for
5427 // writing.
TEST_P(GLSLTest_ES31,AliasedLoadStore)5428 TEST_P(GLSLTest_ES31, AliasedLoadStore)
5429 {
5430 
5431     GLTexture tex;
5432     glBindTexture(GL_TEXTURE_2D, tex);
5433     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5434 
5435     GLFramebuffer fbo;
5436     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5437     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5438     glClearColor(1, 0, 0, 1);
5439     glClear(GL_COLOR_BUFFER_BIT);
5440     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5441 
5442     ANGLE_GL_PROGRAM(program,
5443 
5444                      R"(#version 310 es
5445 precision highp float;
5446 void main()
5447 {
5448     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5449     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5450     gl_Position.zw = vec2(0, 1);
5451 })",
5452 
5453                      R"(#version 310 es
5454 precision highp float;
5455 layout(binding=0, rgba8) volatile readonly highp uniform image2D img_r;
5456 layout(binding=0, rgba8) volatile writeonly highp uniform image2D img_w;
5457 uniform vec4 drawColor;
5458 void main()
5459 {
5460     ivec2 coord = ivec2(floor(gl_FragCoord.xy));
5461     vec4 oldval = imageLoad(img_r, coord);
5462     memoryBarrierImage();
5463     imageStore(img_w, coord, oldval + drawColor);
5464 })");
5465 
5466     ASSERT_TRUE(program.valid());
5467     glUseProgram(program);
5468     GLint drawColorLocation = glGetUniformLocation(program, "drawColor");
5469 
5470     // Tell the driver the binding is GL_READ_WRITE, since it will be referenced by two image2Ds:
5471     // one readeonly and one writeonly.
5472     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
5473 
5474     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5475     glUniform4f(drawColorLocation, 0, 1, 0, 0);
5476     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5477     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5478 
5479     // Ensure the cleared color was loaded before we stored.
5480     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5481     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5482 
5483     ASSERT_GL_NO_ERROR();
5484 
5485     // Now make two draws to ensure the imageStore is coherent.
5486     glClear(GL_COLOR_BUFFER_BIT);
5487     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5488     glUniform4f(drawColorLocation, 0, 1, 0, 0);
5489     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5490     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5491     glUniform4f(drawColorLocation, 0, 0, 1, 0);
5492     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5493     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5494 
5495     // Ensure the first imageStore was loaded by the second imageLoad.
5496     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5497     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
5498 
5499     ASSERT_GL_NO_ERROR();
5500 }
5501 
5502 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5503 TEST_P(GLSLTest_ES31, StructArraySampler)
5504 {
5505     constexpr char kFS[] =
5506         "#version 310 es\n"
5507         "precision mediump float;\n"
5508         "out vec4 my_FragColor;\n"
5509         "struct Data { mediump sampler2D data[2]; };\n"
5510         "uniform Data test;\n"
5511         "void main() {\n"
5512         "    my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5513         "                        texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5514         "}\n";
5515 
5516     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5517     glUseProgram(program);
5518     GLTexture textures[2];
5519     GLColor expected = MakeGLColor(32, 64, 96, 255);
5520     GLubyte data[6]  = {};  // Two bytes of padding, so that texture can be initialized with 4 bytes
5521     memcpy(data, expected.data(), sizeof(expected));
5522     for (int i = 0; i < 2; i++)
5523     {
5524         glActiveTexture(GL_TEXTURE0 + i);
5525         glBindTexture(GL_TEXTURE_2D, textures[i]);
5526         // Each element provides two components.
5527         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5528         std::stringstream uniformName;
5529         uniformName << "test.data[" << i << "]";
5530         // Then send it as a uniform
5531         GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5532         // The uniform should be active.
5533         EXPECT_NE(uniformLocation, -1);
5534         glUniform1i(uniformLocation, i);
5535     }
5536     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5537     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5538 }
5539 
5540 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5541 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5542 {
5543     constexpr char kFS[] =
5544         "#version 310 es\n"
5545         "precision mediump float;\n"
5546         "out vec4 my_FragColor;\n"
5547         "struct Data { mediump isampler2D data[2][2]; };\n"
5548         "uniform Data test;\n"
5549         "void main() {\n"
5550         "    bool passed = true;\n"
5551         "#define DO_CHECK(i,j) \\\n"
5552         "    if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5553         "        passed = false; \\\n"
5554         "    }\n"
5555         "    DO_CHECK(0, 0)\n"
5556         "    DO_CHECK(0, 1)\n"
5557         "    DO_CHECK(1, 0)\n"
5558         "    DO_CHECK(1, 1)\n"
5559         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5560         "}\n";
5561 
5562     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5563     glUseProgram(program);
5564     GLTexture textures[2][2];
5565     for (int i = 0; i < 2; i++)
5566     {
5567         for (int j = 0; j < 2; j++)
5568         {
5569             // First generate the texture
5570             int textureUnit = i * 2 + j;
5571             glActiveTexture(GL_TEXTURE0 + textureUnit);
5572             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5573             GLint texData[2] = {i + 1, j + 1};
5574             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5575             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5576             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5577             // Then send it as a uniform
5578             std::stringstream uniformName;
5579             uniformName << "test.data[" << i << "][" << j << "]";
5580             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5581             // All array indices should be used.
5582             EXPECT_NE(uniformLocation, -1);
5583             glUniform1i(uniformLocation, textureUnit);
5584         }
5585     }
5586     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5587     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5588 }
5589 
5590 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5591 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5592 {
5593     GLint numTextures;
5594     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5595     ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5596     constexpr char kFS[] =
5597         "#version 310 es\n"
5598         "precision mediump float;\n"
5599         "out vec4 my_FragColor;\n"
5600         "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5601         "uniform Data test[2];\n"
5602         "void main() {\n"
5603         "    bool passed = true;\n"
5604         "#define DO_CHECK_ikl(i,k,l) \\\n"
5605         "    if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5606         "        passed = false; \\\n"
5607         "    } \\\n"
5608         "    if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5609         "        passed = false; \\\n"
5610         "    }\n"
5611         "#define DO_CHECK_ik(i,k) \\\n"
5612         "    DO_CHECK_ikl(i, k, 0) \\\n"
5613         "    DO_CHECK_ikl(i, k, 1)\n"
5614         "#define DO_CHECK_i(i) \\\n"
5615         "    DO_CHECK_ik(i, 0) \\\n"
5616         "    DO_CHECK_ik(i, 1)\n"
5617         "    DO_CHECK_i(0)\n"
5618         "    DO_CHECK_i(1)\n"
5619         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5620         "}\n";
5621 
5622     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5623     glUseProgram(program);
5624     GLTexture textures[2][2][2][2];
5625     for (int i = 0; i < 2; i++)
5626     {
5627         for (int j = 0; j < 2; j++)
5628         {
5629             for (int k = 0; k < 2; k++)
5630             {
5631                 for (int l = 0; l < 2; l++)
5632                 {
5633                     // First generate the texture
5634                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5635                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5636                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5637                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5638                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5639                                  &texData[0]);
5640                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5641                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5642                     // Then send it as a uniform
5643                     std::stringstream uniformName;
5644                     uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5645                     GLint uniformLocation =
5646                         glGetUniformLocation(program, uniformName.str().c_str());
5647                     // All array indices should be used.
5648                     EXPECT_NE(uniformLocation, -1);
5649                     glUniform1i(uniformLocation, textureUnit);
5650                 }
5651             }
5652         }
5653     }
5654     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5655     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5656 }
5657 
5658 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5659 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5660 {
5661     GLint numTextures;
5662     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5663     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5664     constexpr char kFS[] =
5665         "#version 310 es\n"
5666         "precision mediump float;\n"
5667         "out vec4 my_FragColor;\n"
5668         "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5669         "uniform Data test[2][3];\n"
5670         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5671         "void main() {\n"
5672         "    bool passed = true;\n"
5673         "#define DO_CHECK_INNER0(i,j,l) \\\n"
5674         "    if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5675         "        passed = false; \\\n"
5676         "    }\n"
5677         "#define DO_CHECK_INNER1(i,j,l) \\\n"
5678         "    if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5679         "        passed = false; \\\n"
5680         "    }\n"
5681         "#define DO_CHECK(i,j) \\\n"
5682         "    DO_CHECK_INNER0(i, j, 0) \\\n"
5683         "    DO_CHECK_INNER0(i, j, 1) \\\n"
5684         "    DO_CHECK_INNER1(i, j, 0) \\\n"
5685         "    DO_CHECK_INNER1(i, j, 1) \\\n"
5686         "    DO_CHECK_INNER1(i, j, 2)\n"
5687         "    DO_CHECK(0, 0)\n"
5688         "    DO_CHECK(0, 1)\n"
5689         "    DO_CHECK(0, 2)\n"
5690         "    DO_CHECK(1, 0)\n"
5691         "    DO_CHECK(1, 1)\n"
5692         "    DO_CHECK(1, 2)\n"
5693         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5694         "}\n";
5695 
5696     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5697     glUseProgram(program);
5698     struct Data
5699     {
5700         GLTexture data1[2];
5701         GLTexture data2[3];
5702     };
5703     Data textures[2][3];
5704     for (int i = 0; i < 2; i++)
5705     {
5706         for (int j = 0; j < 3; j++)
5707         {
5708             GLTexture *arrays[]     = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5709             size_t arrayLengths[]   = {2, 3};
5710             size_t arrayOffsets[]   = {0, 2};
5711             size_t totalArrayLength = 5;
5712             for (int k = 0; k < 2; k++)
5713             {
5714                 GLTexture *array   = arrays[k];
5715                 size_t arrayLength = arrayLengths[k];
5716                 size_t arrayOffset = arrayOffsets[k];
5717                 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5718                 {
5719                     // First generate the texture
5720                     int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5721                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5722                     glBindTexture(GL_TEXTURE_2D, array[l]);
5723                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5724                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5725                                  &texData[0]);
5726                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5727                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5728                     // Then send it as a uniform
5729                     std::stringstream uniformName;
5730                     uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5731                     GLint uniformLocation =
5732                         glGetUniformLocation(program, uniformName.str().c_str());
5733                     // All array indices should be used.
5734                     EXPECT_NE(uniformLocation, -1);
5735                     glUniform1i(uniformLocation, textureUnit);
5736                 }
5737             }
5738         }
5739     }
5740     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5741     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5742 }
5743 
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5744 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5745 {
5746     GLint numTextures;
5747     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5748     ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5749     constexpr char kFS[] =
5750         "#version 310 es\n"
5751         "precision mediump float;\n"
5752         "out vec4 my_FragColor;\n"
5753         "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5754         "uniform Data test[3];\n"
5755         "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5756         "void main() {\n"
5757         "    bool passed = true;\n"
5758         "#define DO_CHECK_ik(i,k) \\\n"
5759         "    if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5760         "        passed = false; \\\n"
5761         "    } \\\n"
5762         "    if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5763         "        passed = false; \\\n"
5764         "    }\n"
5765         "#define DO_CHECK_i(i) \\\n"
5766         "    DO_CHECK_ik(i, 0) \\\n"
5767         "    DO_CHECK_ik(i, 1)\n"
5768         "    DO_CHECK_i(0)\n"
5769         "    DO_CHECK_i(1)\n"
5770         "    DO_CHECK_i(2)\n"
5771         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5772         "}\n";
5773 
5774     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5775     glUseProgram(program);
5776     GLTexture textures[3][2][2];
5777     for (int i = 0; i < 3; i++)
5778     {
5779         for (int j = 0; j < 2; j++)
5780         {
5781             for (int k = 0; k < 2; k++)
5782             {
5783                 // First generate the texture
5784                 int textureUnit = k + 2 * (j + 2 * i);
5785                 glActiveTexture(GL_TEXTURE0 + textureUnit);
5786                 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5787                 GLint texData[4]        = {i + 1, j + 1, k + 1, 1};
5788                 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5789                                            static_cast<GLubyte>((j + 1) * 64 - 1),
5790                                            static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5791                 if (j == 0)
5792                 {
5793                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5794                                  &texData[0]);
5795                 }
5796                 else
5797                 {
5798                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5799                                  &texDataFloat[0]);
5800                 }
5801                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5802                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5803                 // Then send it as a uniform
5804                 std::stringstream uniformName;
5805                 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5806                 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5807                 // All array indices should be used.
5808                 EXPECT_NE(uniformLocation, -1);
5809                 glUniform1i(uniformLocation, textureUnit);
5810             }
5811         }
5812     }
5813     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5814     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5815 }
5816 
5817 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5818 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5819 {
5820     // anglebug.com/3832 - no sampler array params on Android
5821     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5822 
5823     constexpr char kFS[] =
5824         "#version 310 es\n"
5825         "precision mediump float;\n"
5826         "out vec4 my_FragColor;\n"
5827         "uniform mediump isampler2D test[2][3];\n"
5828         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5829         "\n"
5830         "bool check(mediump isampler2D data[2][3]);\n"
5831         "bool check(mediump isampler2D data[2][3]) {\n"
5832         "#define DO_CHECK(i,j) \\\n"
5833         "    if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5834         "        return false; \\\n"
5835         "    }\n"
5836         "    DO_CHECK(0, 0)\n"
5837         "    DO_CHECK(0, 1)\n"
5838         "    DO_CHECK(0, 2)\n"
5839         "    DO_CHECK(1, 0)\n"
5840         "    DO_CHECK(1, 1)\n"
5841         "    DO_CHECK(1, 2)\n"
5842         "    return true;\n"
5843         "}\n"
5844         "void main() {\n"
5845         "    bool passed = check(test);\n"
5846         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5847         "}\n";
5848 
5849     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5850     glUseProgram(program);
5851     GLTexture textures[2][3];
5852     for (int i = 0; i < 2; i++)
5853     {
5854         for (int j = 0; j < 3; j++)
5855         {
5856             // First generate the texture
5857             int textureUnit = i * 3 + j;
5858             glActiveTexture(GL_TEXTURE0 + textureUnit);
5859             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5860             GLint texData[2] = {i + 1, j + 1};
5861             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5862             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5863             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5864             // Then send it as a uniform
5865             std::stringstream uniformName;
5866             uniformName << "test[" << i << "][" << j << "]";
5867             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5868             // All array indices should be used.
5869             EXPECT_NE(uniformLocation, -1);
5870             glUniform1i(uniformLocation, textureUnit);
5871         }
5872     }
5873     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5874     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5875 }
5876 
5877 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)5878 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
5879 {
5880     // anglebug.com/3832 - no sampler array params on Android
5881     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5882 
5883     constexpr char kFS[] =
5884         "#version 310 es\n"
5885         "precision mediump float;\n"
5886         "out vec4 my_FragColor;\n"
5887         "struct Data { mediump isampler2D data[2][3]; };\n"
5888         "uniform Data test;\n"
5889         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5890         "\n"
5891         "bool check(Data data) {\n"
5892         "#define DO_CHECK(i,j) \\\n"
5893         "    if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5894         "        return false; \\\n"
5895         "    }\n"
5896         "    DO_CHECK(0, 0)\n"
5897         "    DO_CHECK(0, 1)\n"
5898         "    DO_CHECK(0, 2)\n"
5899         "    DO_CHECK(1, 0)\n"
5900         "    DO_CHECK(1, 1)\n"
5901         "    DO_CHECK(1, 2)\n"
5902         "    return true;\n"
5903         "}\n"
5904         "void main() {\n"
5905         "    bool passed = check(test);\n"
5906         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5907         "}\n";
5908 
5909     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5910     glUseProgram(program);
5911     GLTexture textures[2][3];
5912     for (int i = 0; i < 2; i++)
5913     {
5914         for (int j = 0; j < 3; j++)
5915         {
5916             // First generate the texture
5917             int textureUnit = i * 3 + j;
5918             glActiveTexture(GL_TEXTURE0 + textureUnit);
5919             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5920             GLint texData[2] = {i + 1, j + 1};
5921             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5922             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5923             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5924             // Then send it as a uniform
5925             std::stringstream uniformName;
5926             uniformName << "test.data[" << i << "][" << j << "]";
5927             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5928             // All array indices should be used.
5929             EXPECT_NE(uniformLocation, -1);
5930             glUniform1i(uniformLocation, textureUnit);
5931         }
5932     }
5933     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5934     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5935 }
5936 
5937 // Test that arrays of arrays of structs with arrays of arrays of samplers
5938 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)5939 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
5940 {
5941     // anglebug.com/3832 - no sampler array params on Android
5942     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5943 
5944     GLint numTextures;
5945     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5946     ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
5947     constexpr char kFS[] =
5948         "#version 310 es\n"
5949         "precision mediump float;\n"
5950         "out vec4 my_FragColor;\n"
5951         "struct Data { mediump isampler2D data[2][2]; };\n"
5952         "uniform Data test[3][2];\n"
5953         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5954         "\n"
5955         "bool check(Data data[3][2]) {\n"
5956         "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
5957         "    if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
5958         "        return false; \\\n"
5959         "    }\n"
5960         "#define DO_CHECK_ij(i,j) \\\n"
5961         "    DO_CHECK_ijkl(i, j, 0, 0) \\\n"
5962         "    DO_CHECK_ijkl(i, j, 0, 1) \\\n"
5963         "    DO_CHECK_ijkl(i, j, 1, 0) \\\n"
5964         "    DO_CHECK_ijkl(i, j, 1, 1)\n"
5965         "    DO_CHECK_ij(0, 0)\n"
5966         "    DO_CHECK_ij(1, 0)\n"
5967         "    DO_CHECK_ij(2, 0)\n"
5968         "    DO_CHECK_ij(0, 1)\n"
5969         "    DO_CHECK_ij(1, 1)\n"
5970         "    DO_CHECK_ij(2, 1)\n"
5971         "    return true;\n"
5972         "}\n"
5973         "void main() {\n"
5974         "    bool passed = check(test);\n"
5975         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5976         "}\n";
5977 
5978     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5979     glUseProgram(program);
5980     GLTexture textures[3][2][2][2];
5981     for (int i = 0; i < 3; i++)
5982     {
5983         for (int j = 0; j < 2; j++)
5984         {
5985             for (int k = 0; k < 2; k++)
5986             {
5987                 for (int l = 0; l < 2; l++)
5988                 {
5989                     // First generate the texture
5990                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5991                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5992                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5993                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5994                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5995                                  &texData[0]);
5996                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5997                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5998                     // Then send it as a uniform
5999                     std::stringstream uniformName;
6000                     uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
6001                     GLint uniformLocation =
6002                         glGetUniformLocation(program, uniformName.str().c_str());
6003                     // All array indices should be used.
6004                     EXPECT_NE(uniformLocation, -1);
6005                     glUniform1i(uniformLocation, textureUnit);
6006                 }
6007             }
6008         }
6009     }
6010     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6011     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6012 }
6013 
6014 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)6015 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
6016 {
6017     GLint numTextures;
6018     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6019     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
6020 
6021     // anglebug.com/3832 - no sampler array params on Android
6022     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6023 
6024     // http://anglebug.com/5546
6025     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
6026 
6027     constexpr char kFS[] =
6028         "#version 310 es\n"
6029         "precision mediump float;\n"
6030         "out vec4 my_FragColor;\n"
6031         "uniform mediump isampler2D test[2][3][4];\n"
6032         "uniform mediump isampler2D test2[4];\n"
6033         "const vec2 ZERO = vec2(0.0, 0.0);\n"
6034         "\n"
6035         "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
6036         "    if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
6037         "    if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
6038         "    if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
6039         "    if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
6040         "    return true;\n"
6041         "}\n"
6042         "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
6043         "    if (!check1D(arr[0], x, 0)) return false;\n"
6044         "    if (!check1D(arr[1], x, 1)) return false;\n"
6045         "    if (!check1D(arr[2], x, 2)) return false;\n"
6046         "    return true;\n"
6047         "}\n"
6048         "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
6049         "    if (!check2D(arr[0], 0)) return false;\n"
6050         "    if (!check2D(arr[1], 1)) return false;\n"
6051         "    return true;\n"
6052         "}\n"
6053         "void main() {\n"
6054         "    bool passed = check3D(test) && check1D(test2, 7, 8);\n"
6055         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6056         "}\n";
6057 
6058     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6059     glUseProgram(program);
6060     GLTexture textures1[2][3][4];
6061     GLTexture textures2[4];
6062     for (int i = 0; i < 2; i++)
6063     {
6064         for (int j = 0; j < 3; j++)
6065         {
6066             for (int k = 0; k < 4; k++)
6067             {
6068                 // First generate the texture
6069                 int textureUnit = k + 4 * (j + 3 * i);
6070                 glActiveTexture(GL_TEXTURE0 + textureUnit);
6071                 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
6072                 GLint texData[3] = {i + 1, j + 1, k + 1};
6073                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
6074                              &texData[0]);
6075                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6076                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6077                 // Then send it as a uniform
6078                 std::stringstream uniformName;
6079                 uniformName << "test[" << i << "][" << j << "][" << k << "]";
6080                 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6081                 // All array indices should be used.
6082                 EXPECT_NE(uniformLocation, -1);
6083                 glUniform1i(uniformLocation, textureUnit);
6084             }
6085         }
6086     }
6087     for (int k = 0; k < 4; k++)
6088     {
6089         // First generate the texture
6090         int textureUnit = 2 * 3 * 4 + k;
6091         glActiveTexture(GL_TEXTURE0 + textureUnit);
6092         glBindTexture(GL_TEXTURE_2D, textures2[k]);
6093         GLint texData[3] = {7 + 1, 8 + 1, k + 1};
6094         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
6095         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6096         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6097         // Then send it as a uniform
6098         std::stringstream uniformName;
6099         uniformName << "test2[" << k << "]";
6100         GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6101         // All array indices should be used.
6102         EXPECT_NE(uniformLocation, -1);
6103         glUniform1i(uniformLocation, textureUnit);
6104     }
6105     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6106     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6107 }
6108 
6109 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)6110 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
6111 {
6112     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/3604 - rewriter can create name collisions
6113     GLint numTextures;
6114     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6115     ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
6116     // anglebug.com/3832 - no sampler array params on Android
6117     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6118     constexpr char kFS[] =
6119         "#version 310 es\n"
6120         "precision mediump sampler2D;\n"
6121         "precision mediump float;\n"
6122         "uniform sampler2D test_field1_field2[2][2];\n"
6123         "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
6124         "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
6125         "vec4 func1(sampler2D param_field1_field2[2][2],\n"
6126         "           int param_field1_field2_offset,\n"
6127         "           S1 param_field1,\n"
6128         "           S2 param) {\n"
6129         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
6130         "}\n"
6131         "out vec4 my_FragColor;\n"
6132         "void main() {\n"
6133         "    my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
6134         "    my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
6135         "    vec2 uv = vec2(0.0);\n"
6136         "    my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
6137         "                    texture(test_field1.field2[0][0], uv) +\n"
6138         "                    texture(test.field1_field2[0][0], uv);\n"
6139         "}\n";
6140     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6141     glActiveTexture(GL_TEXTURE0);
6142     GLTexture tex;
6143     glBindTexture(GL_TEXTURE_2D, tex);
6144     GLint zero = 0;
6145     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6146     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6147     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6148 }
6149 
6150 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)6151 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
6152 {
6153     constexpr char kFS[] =
6154         "#version 310 es\n"
6155         "precision mediump sampler2D;\n"
6156         "precision mediump float;\n"
6157         "uniform sampler2D sampler_array[2][2];\n"
6158         "uniform int array[3][2];\n"
6159         "vec4 func1(int param[2],\n"
6160         "           int param2[3]) {\n"
6161         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
6162         "}\n"
6163         "out vec4 my_FragColor;\n"
6164         "void main() {\n"
6165         "    my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
6166         "    my_FragColor += func1(array[1], int[](1, 2, 3));\n"
6167         "}\n";
6168     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6169     glActiveTexture(GL_TEXTURE0);
6170     GLTexture tex;
6171     glBindTexture(GL_TEXTURE_2D, tex);
6172     GLint zero = 0;
6173     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6174     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6175     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6176 }
6177 
6178 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
6179 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)6180 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
6181 {
6182     // This seems to be bugged on some version of Android. Might not affect the newest versions.
6183     // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
6184     // Test skipped on Android because of bug with Nexus 5X.
6185     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6186 
6187     constexpr char kVS[] =
6188         "#version 300 es\n"
6189         "out vec2 texCoord;\n"
6190         "in vec2 position;\n"
6191         "void main()\n"
6192         "{\n"
6193         "    gl_Position = vec4(position, 0, 1);\n"
6194         "    texCoord = position * 0.5 + vec2(0.5);\n"
6195         "}\n";
6196 
6197     constexpr char kSimpleFS[] =
6198         "#version 300 es\n"
6199         "in mediump vec2 texCoord;\n"
6200         "out mediump vec4 fragColor;\n"
6201         "void main()\n"
6202         "{\n"
6203         "    fragColor = vec4(texCoord, 0, 1);\n"
6204         "}\n";
6205 
6206     constexpr char kNestedFS[] =
6207         "#version 300 es\n"
6208         "uniform mediump sampler2D samplerA;\n"
6209         "uniform mediump sampler2D samplerB;\n"
6210         "in mediump vec2 texCoord;\n"
6211         "out mediump vec4 fragColor;\n"
6212         "void main ()\n"
6213         "{\n"
6214         "    fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
6215         "}\n";
6216 
6217     ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
6218     ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
6219 
6220     // Initialize a first texture with default texCoord data.
6221     GLTexture texA;
6222     glActiveTexture(GL_TEXTURE0);
6223     glBindTexture(GL_TEXTURE_2D, texA);
6224     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6225                  GL_UNSIGNED_BYTE, nullptr);
6226     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6227     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6228 
6229     GLFramebuffer fbo;
6230     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6231     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
6232 
6233     drawQuad(initProg, "position", 0.5f);
6234     ASSERT_GL_NO_ERROR();
6235 
6236     // Initialize a second texture with a simple color pattern.
6237     GLTexture texB;
6238     glActiveTexture(GL_TEXTURE1);
6239     glBindTexture(GL_TEXTURE_2D, texB);
6240 
6241     std::array<GLColor, 4> simpleColors = {
6242         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6243     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6244                  simpleColors.data());
6245     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6246     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6247 
6248     // Draw with the nested program, using the first texture to index the second.
6249     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6250     glUseProgram(nestedProg);
6251     GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
6252     ASSERT_NE(-1, samplerALoc);
6253     glUniform1i(samplerALoc, 0);
6254     GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
6255     ASSERT_NE(-1, samplerBLoc);
6256     glUniform1i(samplerBLoc, 1);
6257 
6258     drawQuad(nestedProg, "position", 0.5f);
6259     ASSERT_GL_NO_ERROR();
6260 
6261     // Compute four texel centers.
6262     Vector2 windowSize(getWindowWidth(), getWindowHeight());
6263     Vector2 quarterWindowSize = windowSize / 4;
6264     Vector2 ul                = quarterWindowSize;
6265     Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
6266     Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
6267     Vector2 lr = windowSize - quarterWindowSize;
6268 
6269     EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
6270     EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
6271     EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
6272     EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
6273 }
6274 
6275 // Tests that using a constant declaration as the only statement in a for loop without curly braces
6276 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)6277 TEST_P(GLSLTest, ConstantStatementInForLoop)
6278 {
6279     constexpr char kVS[] =
6280         "void main()\n"
6281         "{\n"
6282         "    for (int i = 0; i < 10; ++i)\n"
6283         "        const int b = 0;\n"
6284         "}\n";
6285 
6286     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6287     EXPECT_NE(0u, shader);
6288     glDeleteShader(shader);
6289 }
6290 
6291 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
6292 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)6293 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
6294 {
6295     constexpr char kVS[] =
6296         "void main()\n"
6297         "{\n"
6298         "    for (const int i = 0; i < 0;) {}\n"
6299         "}\n";
6300 
6301     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6302     EXPECT_NE(0u, shader);
6303     glDeleteShader(shader);
6304 }
6305 
6306 // Tests that using a constant condition guarding a discard works
6307 // Covers a failing case in the Vulkan backend: http://anglebug.com/7033
TEST_P(GLSLTest_ES3,ConstantConditionGuardingDiscard)6308 TEST_P(GLSLTest_ES3, ConstantConditionGuardingDiscard)
6309 {
6310     constexpr char kFS[] = R"(#version 300 es
6311 void main()
6312 {
6313     if (true)
6314     {
6315         discard;
6316     }
6317 })";
6318 
6319     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6320     EXPECT_NE(0u, shader);
6321     glDeleteShader(shader);
6322 }
6323 
6324 // Tests that nesting a discard in unconditional blocks works
6325 // Covers a failing case in the Vulkan backend: http://anglebug.com/7033
TEST_P(GLSLTest_ES3,NestedUnconditionalDiscards)6326 TEST_P(GLSLTest_ES3, NestedUnconditionalDiscards)
6327 {
6328     constexpr char kFS[] = R"(#version 300 es
6329 out mediump vec4 c;
6330 void main()
6331 {
6332     {
6333         c = vec4(0);
6334         {
6335             discard;
6336         }
6337     }
6338 })";
6339 
6340     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6341     EXPECT_NE(0u, shader);
6342     glDeleteShader(shader);
6343 }
6344 
6345 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)6346 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
6347 {
6348     // Test skipped on Android GLES because local variable initialization is disabled.
6349     // http://anglebug.com/2046
6350     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6351 
6352     constexpr char kFS[] =
6353         "#version 300 es\n"
6354         "precision mediump float;\n"
6355         "out vec4 my_FragColor;\n"
6356         "int result = 0;\n"
6357         "void main()\n"
6358         "{\n"
6359         "    int u;\n"
6360         "    result += u;\n"
6361         "    int k = 0;\n"
6362         "    for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
6363         "    {\n"
6364         "        result += j;\n"
6365         "    }\n"
6366         "    if (result == 2)\n"
6367         "    {\n"
6368         "        my_FragColor = vec4(0, 1, 0, 1);\n"
6369         "    }\n"
6370         "    else\n"
6371         "    {\n"
6372         "        my_FragColor = vec4(1, 0, 0, 1);\n"
6373         "    }\n"
6374         "}\n";
6375 
6376     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6377 
6378     // [WebGL 1.0]
6379     // DrawArrays or drawElements will generate an INVALID_OPERATION error
6380     // if a vertex attribute is enabled as an array via enableVertexAttribArray
6381     // but no buffer is bound to that attribute.
6382     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6383     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6384 }
6385 
6386 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
6387 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)6388 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
6389 {
6390     // Test skipped on Android GLES because local variable initialization is disabled.
6391     // http://anglebug.com/2046
6392     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6393 
6394     constexpr char kFS[] =
6395         "precision mediump float;\n"
6396         "struct T\n"
6397         "{\n"
6398         "    int a[2];\n"
6399         "};\n"
6400         "struct S\n"
6401         "{\n"
6402         "    T t[2];\n"
6403         "};\n"
6404         "void main()\n"
6405         "{\n"
6406         "    S s;\n"
6407         "    S s2;\n"
6408         "    if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
6409         "    {\n"
6410         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6411         "    }\n"
6412         "    else\n"
6413         "    {\n"
6414         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
6415         "    }\n"
6416         "}\n";
6417 
6418     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6419     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6420     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6421 }
6422 
6423 // Verify that two shaders with the same uniform name and members but different structure names will
6424 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)6425 TEST_P(GLSLTest, StructureNameMatchingTest)
6426 {
6427     const char *vsSource =
6428         "// Structures must have the same name, sequence of type names, and\n"
6429         "// type definitions, and field names to be considered the same type.\n"
6430         "// GLSL 1.017 4.2.4\n"
6431         "precision mediump float;\n"
6432         "struct info {\n"
6433         "  vec4 pos;\n"
6434         "  vec4 color;\n"
6435         "};\n"
6436         "\n"
6437         "uniform info uni;\n"
6438         "void main()\n"
6439         "{\n"
6440         "    gl_Position = uni.pos;\n"
6441         "}\n";
6442 
6443     GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
6444     ASSERT_NE(0u, vs);
6445     glDeleteShader(vs);
6446 
6447     const char *fsSource =
6448         "// Structures must have the same name, sequence of type names, and\n"
6449         "// type definitions, and field names to be considered the same type.\n"
6450         "// GLSL 1.017 4.2.4\n"
6451         "precision mediump float;\n"
6452         "struct info1 {\n"
6453         "  vec4 pos;\n"
6454         "  vec4 color;\n"
6455         "};\n"
6456         "\n"
6457         "uniform info1 uni;\n"
6458         "void main()\n"
6459         "{\n"
6460         "    gl_FragColor = uni.color;\n"
6461         "}\n";
6462 
6463     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
6464     ASSERT_NE(0u, fs);
6465     glDeleteShader(fs);
6466 
6467     GLuint program = CompileProgram(vsSource, fsSource);
6468     EXPECT_EQ(0u, program);
6469 }
6470 
6471 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)6472 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
6473 {
6474     // Test skipped on Android GLES because local variable initialization is disabled.
6475     // http://anglebug.com/2046
6476     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6477 
6478     constexpr char kFS[] =
6479         "#version 300 es\n"
6480         "precision highp float;\n"
6481         "out vec4 my_FragColor;\n"
6482         "void main()\n"
6483         "{\n"
6484         "    my_FragColor = vec4(1, 0, 0, 1);\n"
6485         "    for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
6486         "        my_FragColor = vec4(0, 1, 0, 1);\n"
6487         "    }\n"
6488         "}\n";
6489 
6490     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6491     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6492     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6493 }
6494 
6495 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)6496 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
6497 {
6498     // http://anglebug.com/2862
6499     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6500 
6501     constexpr char kFS[] =
6502         "precision mediump float;\n"
6503         "int result;\n"
6504         "int i[2], j = i[0] + 1;\n"
6505         "void main()\n"
6506         "{\n"
6507         "    result += j;\n"
6508         "    if (result == 1)\n"
6509         "    {\n"
6510         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6511         "    }\n"
6512         "    else\n"
6513         "    {\n"
6514         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
6515         "    }\n"
6516         "}\n";
6517 
6518     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6519     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6520     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6521 }
6522 
6523 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6524 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6525 {
6526     constexpr char kFS[] =
6527         "precision mediump float;\n"
6528         "struct { float q; } b;\n"
6529         "void main()\n"
6530         "{\n"
6531         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
6532         "    if (b.q == 0.0)\n"
6533         "    {\n"
6534         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6535         "    }\n"
6536         "}\n";
6537 
6538     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6539     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6540     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6541 }
6542 
6543 // Test that uninitialized output arguments are initialized to 0.
TEST_P(WebGL2GLSLTest,InitOutputParams)6544 TEST_P(WebGL2GLSLTest, InitOutputParams)
6545 {
6546     constexpr char kFS[] = R"(#version 300 es
6547 precision mediump float;
6548 
6549 struct S { float a; };
6550 
6551 out vec4 color;
6552 
6553 float f(out vec2 o1, out S o2[2], out float o3[3])
6554 {
6555     float uninitialized_local;
6556 
6557     // leave o1 uninitialized
6558     // leave o2 partially uninitialized
6559     o2[0].a = 1.0;
6560 
6561     // leave o3 partially uninitialized
6562     o3[1] = 0.5;
6563 
6564     return uninitialized_local;
6565 }
6566 
6567 void main()
6568 {
6569     vec2 v1 = vec2(123., 234.);
6570     S v2[2] = S[2](S(-1111.), S(55.));
6571     float v3[3] = float[3](20., 30., 40.);
6572     float v4 = f(v1, v2, v3);
6573 
6574     // Everything should be 0 now except for v2[0].a and v3[1] which should be 1.0 and 0.5
6575     // respectively.
6576     color = vec4(v1.x + v2[0].a + v3[0],  // 1.0
6577                  v1.y + v2[1].a + v3[1],  // 0.5
6578                  v3[2] + v4,              // 0
6579                  1.0);
6580 })";
6581 
6582     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6583     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6584     EXPECT_PIXEL_NEAR(0, 0, 255, 127, 0, 255, 1);
6585 }
6586 
6587 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6588 TEST_P(GLSLTest, EmbeddedStructUniform)
6589 {
6590     const char kFragmentShader[] = R"(precision mediump float;
6591 uniform struct { float q; } b;
6592 void main()
6593 {
6594     gl_FragColor = vec4(1, 0, 0, 1);
6595     if (b.q == 0.5)
6596     {
6597         gl_FragColor = vec4(0, 1, 0, 1);
6598     }
6599 })";
6600 
6601     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6602     glUseProgram(program);
6603     GLint uniLoc = glGetUniformLocation(program, "b.q");
6604     ASSERT_NE(-1, uniLoc);
6605     glUniform1f(uniLoc, 0.5f);
6606 
6607     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6608     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6609 }
6610 
6611 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6612 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6613 {
6614     const char kFragmentShader[] = R"(precision mediump float;
6615 uniform struct { float q; } b[2];
6616 void main()
6617 {
6618     gl_FragColor = vec4(1, 0, 0, 1);
6619     if (b[0].q == 0.5)
6620     {
6621         gl_FragColor = vec4(0, 1, 0, 1);
6622     }
6623 })";
6624 
6625     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6626     glUseProgram(program);
6627     GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6628     ASSERT_NE(-1, uniLoc);
6629     glUniform1f(uniLoc, 0.5f);
6630 
6631     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6632     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6633 }
6634 
6635 // Test that samplers in structs can be extracted if the first reference to the struct does not
6636 // select an attribute.
TEST_P(GLSLTest,SamplerInStructNoMemberIndexing)6637 TEST_P(GLSLTest, SamplerInStructNoMemberIndexing)
6638 {
6639     constexpr char kVS[] = R"(
6640 uniform struct {
6641     sampler2D n;
6642     vec2 c;
6643 } s;
6644 void main()
6645 {
6646     s;
6647 })";
6648 
6649     constexpr char kFS[] = R"(void main()
6650 {
6651     gl_FragColor = vec4(1);
6652 })";
6653 
6654     ANGLE_GL_PROGRAM(program, kVS, kFS);
6655 }
6656 
6657 // Similar test to SamplerInStructNoMemberIndexing, but the struct variable is an array.
TEST_P(GLSLTest,SamplerInStructArrayNoMemberIndexing)6658 TEST_P(GLSLTest, SamplerInStructArrayNoMemberIndexing)
6659 {
6660     constexpr char kVS[] = R"(
6661 uniform struct
6662 {
6663     sampler2D K;
6664     vec4 c;
6665 } s[6];
6666 void main()
6667 {
6668     s[0];
6669 })";
6670 
6671     constexpr char kFS[] = R"(void main()
6672 {
6673     gl_FragColor = vec4(1);
6674 })";
6675 
6676     ANGLE_GL_PROGRAM(program, kVS, kFS);
6677 }
6678 
6679 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6680 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6681 {
6682     const char kVertexShader[] = R"(attribute vec2 position;
6683 varying vec2 texCoord;
6684 void main()
6685 {
6686     gl_Position = vec4(position, 0, 1);
6687     texCoord = position * 0.5 + vec2(0.5);
6688 })";
6689 
6690     const char kFragmentShader[] = R"(precision mediump float;
6691 struct S { sampler2D samp; bool b; };
6692 uniform S uni;
6693 varying vec2 texCoord;
6694 void main()
6695 {
6696     uni;
6697     if (uni.b)
6698     {
6699         gl_FragColor = texture2D(uni.samp, texCoord);
6700     }
6701     else
6702     {
6703         gl_FragColor = vec4(1, 0, 0, 1);
6704     }
6705 })";
6706 
6707     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6708     glUseProgram(program);
6709 
6710     GLint bLoc = glGetUniformLocation(program, "uni.b");
6711     ASSERT_NE(-1, bLoc);
6712     GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6713     ASSERT_NE(-1, sampLoc);
6714 
6715     glUniform1i(bLoc, 1);
6716 
6717     std::array<GLColor, 4> kGreenPixels = {
6718         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6719 
6720     GLTexture tex;
6721     glBindTexture(GL_TEXTURE_2D, tex);
6722     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6723                  kGreenPixels.data());
6724     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6725     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6726     ASSERT_GL_NO_ERROR();
6727 
6728     drawQuad(program, "position", 0.5f);
6729     ASSERT_GL_NO_ERROR();
6730 
6731     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6732 }
6733 
6734 // Tests that rewriting samplers in structs works when passed as function argument.  In this test,
6735 // the function references another struct, which is not being modified.  Regression test for AST
6736 // validation applied to a multipass transformation, where references to declarations were attempted
6737 // to be validated without having the entire shader.  In this case, the reference to S2 was flagged
6738 // as invalid because S2's declaration was not visible.
TEST_P(GLSLTest,SamplerInStructAsFunctionArg)6739 TEST_P(GLSLTest, SamplerInStructAsFunctionArg)
6740 {
6741     const char kFS[] = R"(precision mediump float;
6742 struct S { sampler2D samp; bool b; };
6743 struct S2 { float f; };
6744 
6745 uniform S us;
6746 
6747 float f(S s)
6748 {
6749     S2 s2;
6750     s2.f = float(s.b);
6751     return s2.f;
6752 }
6753 
6754 void main()
6755 {
6756     gl_FragColor = vec4(f(us), 0, 0, 1);
6757 })";
6758 
6759     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6760     EXPECT_NE(fs, 0u);
6761     ASSERT_GL_NO_ERROR();
6762 }
6763 
6764 // Test that structs with samplers are not allowed in interface blocks.  This is forbidden per
6765 // GLES3:
6766 //
6767 // > Types and declarators are the same as for other uniform variable declarations outside blocks,
6768 // > with these exceptions:
6769 // > * opaque types are not allowed
TEST_P(GLSLTest_ES3,StructWithSamplersDisallowedInInterfaceBlock)6770 TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock)
6771 {
6772     const char kFS[] = R"(#version 300 es
6773 precision mediump float;
6774 struct S { sampler2D samp; bool b; };
6775 
6776 layout(std140) uniform Buffer { S s; } buffer;
6777 
6778 out vec4 color;
6779 
6780 void main()
6781 {
6782     color = texture(buffer.s.samp, vec2(0));
6783 })";
6784 
6785     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6786     EXPECT_EQ(fs, 0u);
6787     ASSERT_GL_NO_ERROR();
6788 }
6789 
6790 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6791 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6792 {
6793     const char kFragmentShader[] = R"(precision mediump float;
6794 uniform struct { float q; } b, c;
6795 void main()
6796 {
6797     gl_FragColor = vec4(1, 0, 0, 1);
6798     if (b.q == 0.5 && c.q == 1.0)
6799     {
6800         gl_FragColor = vec4(0, 1, 0, 1);
6801     }
6802 })";
6803 
6804     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6805     glUseProgram(program);
6806 
6807     GLint uniLocB = glGetUniformLocation(program, "b.q");
6808     ASSERT_NE(-1, uniLocB);
6809     glUniform1f(uniLocB, 0.5f);
6810 
6811     GLint uniLocC = glGetUniformLocation(program, "c.q");
6812     ASSERT_NE(-1, uniLocC);
6813     glUniform1f(uniLocC, 1.0f);
6814 
6815     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6816     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6817 }
6818 
6819 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6820 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6821 {
6822     constexpr char kFS[] =
6823         "#version 300 es\n"
6824         "precision highp float;\n"
6825         "out vec4 my_FragColor;\n"
6826         "void main()\n"
6827         "{\n"
6828         "    float i = 0.0;\n"
6829         "    while (bool foo = (i < 1.5))\n"
6830         "    {\n"
6831         "        if (!foo)\n"
6832         "        {\n"
6833         "            ++i;\n"
6834         "        }\n"
6835         "        if (i > 3.5)\n"
6836         "        {\n"
6837         "            break;\n"
6838         "        }\n"
6839         "        ++i;\n"
6840         "    }\n"
6841         "    my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6842         "}\n";
6843 
6844     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6845     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
6846     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6847 }
6848 
6849 // Test that a variable hides a user-defined function with the same name after its initializer.
6850 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6851 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6852 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6853 {
6854     constexpr char kFS[] =
6855         "precision mediump float;\n"
6856         "uniform vec4 u;\n"
6857         "vec4 foo()\n"
6858         "{\n"
6859         "    return u;\n"
6860         "}\n"
6861         "void main()\n"
6862         "{\n"
6863         "    vec4 foo = foo();\n"
6864         "    gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6865         "}\n";
6866 
6867     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6868     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6869     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6870 }
6871 
6872 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6873 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6874 {
6875     constexpr char kFS[] =
6876         "precision mediump float;\n"
6877         "uniform float u_zero;\n"
6878         "struct S { float foo; };\n"
6879         "struct S2 { float foo; };\n"
6880         "float get(S s) { return s.foo + u_zero; }\n"
6881         "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
6882         "void main()\n"
6883         "{\n"
6884         "    S s;\n"
6885         "    s.foo = 0.5;\n"
6886         "    S2 s2;\n"
6887         "    s2.foo = 0.25;\n"
6888         "    gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
6889         "}\n";
6890 
6891     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6892     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6893     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6894 }
6895 
6896 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
6897 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)6898 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
6899 {
6900     // http://anglebug.com/4820
6901     ANGLE_SKIP_TEST_IF((IsMac() && IsOpenGL()) || (IsIOS() && IsOpenGLES()));
6902 
6903     constexpr char kVS[] =
6904         "attribute vec4 inputAttribute;\n"
6905         "varying vec4 varColor;\n"
6906         "void main()\n"
6907         "{\n"
6908         "    gl_Position = inputAttribute;\n"
6909         "}\n";
6910 
6911     constexpr char kFS[] =
6912         "precision mediump float;\n"
6913         "varying vec4 varColor;\n"
6914         "void main()\n"
6915         "{\n"
6916         "    gl_FragColor = varColor;\n"
6917         "}\n";
6918 
6919     ANGLE_GL_PROGRAM(program, kVS, kFS);
6920     drawQuad(program, "inputAttribute", 0.5f);
6921     ASSERT_GL_NO_ERROR();
6922 }
6923 
6924 // Test that a varying struct that's not statically used in the fragment shader works.
6925 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)6926 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
6927 {
6928     constexpr char kVS[] =
6929         "#version 300 es\n"
6930         "struct S {\n"
6931         "    vec4 field;\n"
6932         "};\n"
6933         "out S varStruct;\n"
6934         "void main()\n"
6935         "{\n"
6936         "    gl_Position = vec4(1.0);\n"
6937         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
6938         "}\n";
6939 
6940     constexpr char kFS[] =
6941         "#version 300 es\n"
6942         "precision mediump float;\n"
6943         "struct S {\n"
6944         "    vec4 field;\n"
6945         "};\n"
6946         "in S varStruct;\n"
6947         "out vec4 col;\n"
6948         "void main()\n"
6949         "{\n"
6950         "    col = vec4(1.0);\n"
6951         "}\n";
6952 
6953     ANGLE_GL_PROGRAM(program, kVS, kFS);
6954 }
6955 
6956 // Test that inactive shader IO block varying are ok.
TEST_P(GLSLTest_ES31,InactiveVaryingIOBlock)6957 TEST_P(GLSLTest_ES31, InactiveVaryingIOBlock)
6958 {
6959     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
6960 
6961     constexpr char kVS[] =
6962         R"(#version 310 es
6963         #extension GL_EXT_shader_io_blocks : require
6964 
6965         precision highp float;
6966         in vec4 inputAttribute;
6967         out Block { vec4 v; };
6968         out Inactive1 { vec4 value; };
6969         out Inactive2 { vec4 value; } named;
6970 
6971         void main()
6972         {
6973             gl_Position    = inputAttribute;
6974             v = vec4(0);
6975         })";
6976 
6977     constexpr char kFS[] =
6978         R"(#version 310 es
6979         #extension GL_EXT_shader_io_blocks : require
6980 
6981         precision highp float;
6982 
6983         in Block { vec4 v; };
6984         in Inactive3 { vec4 value; };
6985         in Inactive4 { vec4 value; } named2;
6986 
6987         layout(location = 0) out mediump vec4 color;
6988         void main()
6989         {
6990             color = vec4(1, v.xy, 1);
6991         })";
6992 
6993     ANGLE_GL_PROGRAM(program, kVS, kFS);
6994     drawQuad(program, "inputAttribute", 0.5f);
6995     ASSERT_GL_NO_ERROR();
6996 
6997     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6998 }
6999 
7000 // Test that a shader IO block varying that's not declared in the fragment shader links
7001 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)7002 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
7003 {
7004     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7005 
7006     constexpr char kVS[] =
7007         R"(#version 310 es
7008         #extension GL_EXT_shader_io_blocks : require
7009 
7010         precision highp float;
7011         in vec4 inputAttribute;
7012         out Block_inout { vec4 value; } user_out;
7013 
7014         void main()
7015         {
7016             gl_Position    = inputAttribute;
7017             user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
7018         })";
7019 
7020     constexpr char kFS[] =
7021         R"(#version 310 es
7022         #extension GL_EXT_shader_io_blocks : require
7023 
7024         precision highp float;
7025         layout(location = 0) out mediump vec4 color;
7026         void main()
7027         {
7028             color = vec4(1, 0, 0, 1);
7029         })";
7030 
7031     ANGLE_GL_PROGRAM(program, kVS, kFS);
7032     drawQuad(program, "inputAttribute", 0.5f);
7033     ASSERT_GL_NO_ERROR();
7034 
7035     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7036 }
7037 
7038 // Test that a shader IO block varying that's not declared in the vertex shader links
7039 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)7040 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
7041 {
7042     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7043 
7044     constexpr char kVS[] =
7045         R"(#version 310 es
7046         #extension GL_EXT_shader_io_blocks : require
7047 
7048         precision highp float;
7049         in vec4 inputAttribute;
7050 
7051         void main()
7052         {
7053             gl_Position = inputAttribute;
7054         })";
7055 
7056     constexpr char kFS[] =
7057         R"(#version 310 es
7058         #extension GL_EXT_shader_io_blocks : require
7059 
7060         precision highp float;
7061         in Block_inout { vec4 value; } user_in;
7062         layout(location = 0) out mediump vec4 color;
7063 
7064         void main()
7065         {
7066             color = vec4(1, 0, 0, 1);
7067         })";
7068 
7069     ANGLE_GL_PROGRAM(program, kVS, kFS);
7070     drawQuad(program, "inputAttribute", 0.5f);
7071     ASSERT_GL_NO_ERROR();
7072 
7073     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7074 }
7075 
7076 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)7077 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
7078 {
7079     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7080     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7081 
7082     constexpr char kVS[] =
7083         R"(#version 310 es
7084         #extension GL_OES_shader_multisample_interpolation : require
7085 
7086         precision highp float;
7087         in vec4 inputAttribute;
7088 
7089         sample out mediump float tc_in;
7090         void main()
7091         {
7092             tc_in = inputAttribute[0];
7093             gl_Position = inputAttribute;
7094         })";
7095 
7096     constexpr char kTCS[] =
7097         R"(#version 310 es
7098         #extension GL_EXT_tessellation_shader : require
7099         #extension GL_OES_shader_multisample_interpolation : require
7100         layout (vertices=3) out;
7101 
7102         sample in mediump float tc_in[];
7103         sample out mediump float tc_out[];
7104         void main()
7105         {
7106             tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
7107             gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7108             gl_TessLevelInner[0] = 2.0;
7109             gl_TessLevelInner[1] = 2.0;
7110             gl_TessLevelOuter[0] = 2.0;
7111             gl_TessLevelOuter[1] = 2.0;
7112             gl_TessLevelOuter[2] = 2.0;
7113             gl_TessLevelOuter[3] = 2.0;
7114         })";
7115 
7116     constexpr char kTES[] =
7117         R"(#version 310 es
7118         #extension GL_EXT_tessellation_shader : require
7119         #extension GL_OES_shader_multisample_interpolation : require
7120         layout (triangles) in;
7121 
7122         sample in mediump float tc_out[];
7123         sample out mediump float te_out;
7124         void main()
7125         {
7126             te_out = tc_out[2];
7127             gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
7128         })";
7129 
7130     constexpr char kFS[] =
7131         R"(#version 310 es
7132         #extension GL_OES_shader_multisample_interpolation : require
7133 
7134         precision highp float;
7135         sample in mediump float te_out;
7136         layout(location = 0) out mediump vec4 color;
7137 
7138         void main()
7139         {
7140             float out0 = te_out;
7141             color = vec4(1, 0, 0, 1);
7142         })";
7143 
7144     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7145     drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7146     ASSERT_GL_NO_ERROR();
7147 }
7148 
7149 // Test that `smooth sample` and `flat sample` pass the validation.
TEST_P(GLSLTest_ES3,AliasedSampleQualifiers)7150 TEST_P(GLSLTest_ES3, AliasedSampleQualifiers)
7151 {
7152     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7153 
7154     constexpr char kVS[] =
7155         R"(#version 300 es
7156         #extension GL_OES_shader_multisample_interpolation : require
7157 
7158         smooth sample out mediump float f;
7159         flat sample out mediump int i;
7160         void main()
7161         {
7162             f = 1.0;
7163             i = 1;
7164             gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7165         })";
7166 
7167     constexpr char kFS[] =
7168         R"(#version 300 es
7169         #extension GL_OES_shader_multisample_interpolation : require
7170 
7171         smooth sample in mediump float f;
7172         flat sample in mediump int i;
7173         out mediump vec4 color;
7174         void main()
7175         {
7176             color = vec4(f, float(i), 0, 1);
7177         })";
7178 
7179     ANGLE_GL_PROGRAM(program, kVS, kFS);
7180 }
7181 
7182 // Test that `noperspective centroid` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveCentroid)7183 TEST_P(GLSLTest_ES3, NoPerspectiveCentroid)
7184 {
7185     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7186 
7187     constexpr char kVS[] =
7188         R"(#version 300 es
7189         #extension GL_NV_shader_noperspective_interpolation : require
7190 
7191         noperspective centroid out mediump float f;
7192         void main()
7193         {
7194             f = 1.0;
7195             gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7196         })";
7197 
7198     constexpr char kFS[] =
7199         R"(#version 300 es
7200         #extension GL_NV_shader_noperspective_interpolation : require
7201 
7202         noperspective centroid in mediump float f;
7203         out mediump vec4 color;
7204         void main()
7205         {
7206             color = vec4(f, 0.0, 0.0, 1.0);
7207         })";
7208 
7209     ANGLE_GL_PROGRAM(program, kVS, kFS);
7210 }
7211 
7212 // Test that `noperspective sample` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveSample)7213 TEST_P(GLSLTest_ES3, NoPerspectiveSample)
7214 {
7215     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7216     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7217 
7218     constexpr char kVS[] =
7219         R"(#version 300 es
7220         #extension GL_OES_shader_multisample_interpolation : require
7221         #extension GL_NV_shader_noperspective_interpolation : require
7222 
7223         noperspective sample out mediump float f;
7224         void main()
7225         {
7226             f = 1.0;
7227             gl_Position = vec4(f, 0.0, 0.0, 1.0);
7228         })";
7229 
7230     constexpr char kFS[] =
7231         R"(#version 300 es
7232         #extension GL_OES_shader_multisample_interpolation : require
7233         #extension GL_NV_shader_noperspective_interpolation : require
7234 
7235         noperspective sample in mediump float f;
7236         out mediump vec4 color;
7237         void main()
7238         {
7239             color = vec4(f, 0.0, 0.0, 1.0);
7240         })";
7241 
7242     ANGLE_GL_PROGRAM(program, kVS, kFS);
7243 }
7244 
7245 // Test that a shader with sample in / sample out can be used successfully when the varying
7246 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)7247 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
7248 {
7249     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7250 
7251     constexpr char kVS[] =
7252         R"(#version 310 es
7253         #extension GL_OES_shader_multisample_interpolation : require
7254 
7255         precision highp float;
7256         in vec4 inputAttribute;
7257 
7258         sample out highp float v;
7259         void main()
7260         {
7261             v = inputAttribute[0];
7262             gl_Position = inputAttribute;
7263         })";
7264 
7265     constexpr char kFS[] =
7266         R"(#version 310 es
7267         #extension GL_OES_shader_multisample_interpolation : require
7268 
7269         precision highp float;
7270         sample in mediump float v;
7271         layout(location = 0) out mediump vec4 color;
7272 
7273         void main()
7274         {
7275             color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
7276         })";
7277 
7278     ANGLE_GL_PROGRAM(program, kVS, kFS);
7279     drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7280     ASSERT_GL_NO_ERROR();
7281 
7282     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
7283 }
7284 
7285 // Test that a shader IO block varying whose block name is declared multiple(in/out) time links
7286 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockDeclaredAsInAndOut)7287 TEST_P(GLSLTest_ES31, VaryingIOBlockDeclaredAsInAndOut)
7288 {
7289     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7290     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7291 
7292     constexpr char kVS[] = R"(#version 310 es
7293     #extension GL_EXT_shader_io_blocks : require
7294     precision highp float;
7295     in vec4 inputAttribute;
7296     out Vertex
7297     {
7298         vec4 fv;
7299     } outVertex;
7300     void main()
7301     {
7302         gl_Position = inputAttribute;
7303         outVertex.fv = gl_Position;
7304     })";
7305 
7306     constexpr char kTCS[] = R"(#version 310 es
7307     #extension GL_EXT_tessellation_shader : require
7308     #extension GL_EXT_shader_io_blocks : require
7309     precision mediump float;
7310     in Vertex
7311     {
7312         vec4 fv;
7313     } inVertex[];
7314     layout(vertices = 2) out;
7315     out Vertex
7316     {
7317         vec4 fv;
7318     } outVertex[];
7319 
7320     void main()
7321     {
7322         gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7323         outVertex[gl_InvocationID].fv = inVertex[gl_InvocationID].fv;
7324         gl_TessLevelInner[0] = 1.0;
7325             gl_TessLevelInner[1] = 1.0;
7326             gl_TessLevelOuter[0] = 1.0;
7327             gl_TessLevelOuter[1] = 1.0;
7328             gl_TessLevelOuter[2] = 1.0;
7329             gl_TessLevelOuter[3] = 1.0;
7330     })";
7331 
7332     constexpr char kTES[] = R"(#version 310 es
7333     #extension GL_EXT_tessellation_shader : require
7334     #extension GL_EXT_shader_io_blocks : require
7335     precision mediump float;
7336     layout (isolines, point_mode) in;
7337     in Vertex
7338     {
7339         vec4 fv;
7340     } inVertex[];
7341     out vec4 result_fv;
7342 
7343     void main()
7344     {
7345         gl_Position = gl_in[0].gl_Position;
7346         result_fv = inVertex[0].fv;
7347     })";
7348 
7349     constexpr char kFS[] = R"(#version 310 es
7350     precision mediump float;
7351 
7352     layout(location = 0) out mediump vec4 color;
7353 
7354     void main()
7355     {
7356         // Output solid green
7357         color = vec4(0, 1.0, 0, 1.0);
7358     })";
7359 
7360     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7361     drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7362     ASSERT_GL_NO_ERROR();
7363 }
7364 
testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)7365 void GLSLTest_ES31::testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)
7366 {
7367     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
7368 
7369     // Vertex shader
7370     constexpr char kVS[] = R"(#version 310 es
7371 precision highp float;
7372 in vec4 inputAttribute;
7373 
7374 void main()
7375 {
7376 gl_Position = inputAttribute;
7377 })";
7378 
7379     // Tessellation shaders
7380     constexpr char kGLSLVersion[] = R"(#version 310 es
7381 )";
7382     constexpr char kTessEXT[]     = R"(#extension GL_EXT_tessellation_shader : require
7383 )";
7384     constexpr char kTessOES[]     = R"(#extension GL_OES_tessellation_shader : require
7385 )";
7386     constexpr char kTexBufEXT[]   = R"(#extension GL_EXT_texture_buffer : require
7387 )";
7388     constexpr char kTexBufOES[]   = R"(#extension GL_OES_texture_buffer : require
7389 )";
7390 
7391     std::string tcs;
7392     std::string tes;
7393 
7394     tcs.append(kGLSLVersion);
7395     tes.append(kGLSLVersion);
7396 
7397     if (usedExtension == APIExtensionVersion::EXT)
7398     {
7399         tcs.append(kTessEXT);
7400         tes.append(kTessEXT);
7401         tes.append(kTexBufEXT);
7402     }
7403     else
7404     {
7405         tcs.append(kTessOES);
7406         tes.append(kTessOES);
7407         tes.append(kTexBufOES);
7408     }
7409 
7410     constexpr char kTCSBody[] = R"(precision mediump float;
7411 layout(vertices = 2) out;
7412 
7413 void main()
7414 {
7415 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7416 gl_TessLevelInner[0] = 1.0;
7417 gl_TessLevelInner[1] = 1.0;
7418 gl_TessLevelOuter[0] = 1.0;
7419 gl_TessLevelOuter[1] = 1.0;
7420 gl_TessLevelOuter[2] = 1.0;
7421 gl_TessLevelOuter[3] = 1.0;
7422 })";
7423     tcs.append(kTCSBody);
7424 
7425     constexpr char kTESBody[] = R"(precision mediump float;
7426 layout (isolines, point_mode) in;
7427 
7428 uniform highp samplerBuffer tex;
7429 
7430 out vec4 tex_color;
7431 
7432 void main()
7433 {
7434 tex_color = texelFetch(tex, 0);
7435 gl_Position = gl_in[0].gl_Position;
7436 })";
7437     tes.append(kTESBody);
7438 
7439     // Fragment shader
7440     constexpr char kFS[] = R"(#version 310 es
7441 precision mediump float;
7442 layout(location = 0) out mediump vec4 color;
7443 
7444 in vec4 tex_color;
7445 
7446 void main()
7447 {
7448 color = tex_color;
7449 })";
7450 
7451     constexpr GLint kBufferSize = 32;
7452     GLubyte texData[]           = {0u, 255u, 0u, 255u};
7453 
7454     GLTexture texture;
7455     glBindTexture(GL_TEXTURE_BUFFER, texture);
7456 
7457     GLBuffer buffer;
7458     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
7459     glBufferData(GL_TEXTURE_BUFFER, kBufferSize, texData, GL_STATIC_DRAW);
7460     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
7461     ASSERT_GL_NO_ERROR();
7462 
7463     glClearColor(1.0, 0, 0, 1.0);
7464     glClear(GL_COLOR_BUFFER_BIT);
7465 
7466     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, tcs.c_str(), tes.c_str(), kFS);
7467     drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7468     ASSERT_GL_NO_ERROR();
7469 }
7470 
7471 // Test that texture buffers can be accessed in a tessellation stage (using EXT)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessEXT)7472 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessEXT)
7473 {
7474     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7475     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
7476     testTessellationTextureBufferAccess(APIExtensionVersion::EXT);
7477 }
7478 
7479 // Test that texture buffers can be accessed in a tessellation stage (using OES)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessOES)7480 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessOES)
7481 {
7482     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_tessellation_shader"));
7483     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
7484     testTessellationTextureBufferAccess(APIExtensionVersion::OES);
7485 }
7486 
7487 // Test that a varying struct that's not declared in the fragment shader links successfully.
7488 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)7489 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
7490 {
7491     constexpr char kVS[] =
7492         "#version 300 es\n"
7493         "struct S {\n"
7494         "    vec4 field;\n"
7495         "};\n"
7496         "out S varStruct;\n"
7497         "void main()\n"
7498         "{\n"
7499         "    gl_Position = vec4(1.0);\n"
7500         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7501         "}\n";
7502 
7503     constexpr char kFS[] =
7504         "#version 300 es\n"
7505         "precision mediump float;\n"
7506         "out vec4 col;\n"
7507         "void main()\n"
7508         "{\n"
7509         "    col = vec4(1.0);\n"
7510         "}\n";
7511 
7512     ANGLE_GL_PROGRAM(program, kVS, kFS);
7513 }
7514 
7515 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
7516 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)7517 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
7518 {
7519     // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
7520     // going to use it.  See section 9.1 in
7521     // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
7522     // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7523     //
7524     // However, nvidia OpenGL ES drivers fail to link this program.
7525     //
7526     // http://anglebug.com/3413
7527     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
7528 
7529     constexpr char kVS[] =
7530         "#version 300 es\n"
7531         "void main()\n"
7532         "{\n"
7533         "    gl_Position = vec4(1.0);\n"
7534         "}\n";
7535 
7536     constexpr char kFS[] =
7537         "#version 300 es\n"
7538         "precision mediump float;\n"
7539         "out vec4 col;\n"
7540         "struct S {\n"
7541         "    vec4 field;\n"
7542         "};\n"
7543         "in S varStruct;\n"
7544         "void main()\n"
7545         "{\n"
7546         "    col = vec4(1.0);\n"
7547         "}\n";
7548 
7549     ANGLE_GL_PROGRAM(program, kVS, kFS);
7550 }
7551 
7552 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)7553 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
7554 {
7555     // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
7556     // specification that the varying values are undefined in the fragment stage).  See section 9.1
7557     // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
7558     // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7559     //
7560     // However, windows and mac OpenGL drivers fail to link this program.  With a message like:
7561     //
7562     // > Input of fragment shader 'varStruct' not written by vertex shader
7563     //
7564     // http://anglebug.com/3413
7565     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsMac() || (IsWindows() && !IsNVIDIA())));
7566     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7567     // struct member. Not sure if it's being overly strict.
7568     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7569 
7570     constexpr char kVS[] =
7571         "#version 300 es\n"
7572         "struct S {\n"
7573         "    vec4 field;\n"
7574         "};\n"
7575         "out S varStruct;\n"
7576         "void main()\n"
7577         "{\n"
7578         "    gl_Position = vec4(1.0);\n"
7579         "}\n";
7580 
7581     constexpr char kFS[] =
7582         "#version 300 es\n"
7583         "precision mediump float;\n"
7584         "out vec4 col;\n"
7585         "struct S {\n"
7586         "    vec4 field;\n"
7587         "};\n"
7588         "in S varStruct;\n"
7589         "void main()\n"
7590         "{\n"
7591         "    col = varStruct.field;\n"
7592         "}\n";
7593 
7594     ANGLE_GL_PROGRAM(program, kVS, kFS);
7595 }
7596 
7597 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)7598 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
7599 {
7600     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7601     // struct member. Not sure if it's being overly strict.
7602     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7603     constexpr char kVS[] =
7604         "#version 300 es\n"
7605         "in vec4 inputAttribute;\n"
7606         "struct S {\n"
7607         "    vec4 field;\n"
7608         "};\n"
7609         "out S varStruct;\n"
7610         "out S varStruct2;\n"
7611         "void main()\n"
7612         "{\n"
7613         "    gl_Position = inputAttribute;\n"
7614         "    varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7615         "    varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7616         "}\n";
7617 
7618     constexpr char kFS[] =
7619         "#version 300 es\n"
7620         "precision mediump float;\n"
7621         "out vec4 col;\n"
7622         "struct S {\n"
7623         "    vec4 field;\n"
7624         "};\n"
7625         "in S varStruct;\n"
7626         "in S varStruct2;\n"
7627         "void main()\n"
7628         "{\n"
7629         "    col = varStruct.field + varStruct2.field;\n"
7630         "}\n";
7631 
7632     ANGLE_GL_PROGRAM(program, kVS, kFS);
7633     drawQuad(program, "inputAttribute", 0.5f);
7634     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7635 }
7636 
7637 // This is a regression test to make sure a red quad is rendered without issues
7638 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)7639 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
7640 {
7641     constexpr char kVS[] =
7642         "precision mediump float;\n"
7643         "attribute vec4 inputAttribute;\n"
7644         "varying mediump vec2 texCoord;\n"
7645         "void main() {\n"
7646         "    texCoord = inputAttribute.xy;\n"
7647         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7648         "}\n";
7649 
7650     constexpr char kFS[] =
7651         "precision mediump float;\n"
7652         "varying mediump vec2 texCoord;\n"
7653         "uniform sampler2D testSampler;\n"
7654         "vec3 passthrough(vec3 c) {\n"
7655         "    return c;\n"
7656         "}\n"
7657         "void main() {\n"
7658         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
7659         "}\n";
7660     ANGLE_GL_PROGRAM(program, kVS, kFS);
7661 
7662     // Initialize basic red texture.
7663     GLTexture texture;
7664     glBindTexture(GL_TEXTURE_2D, texture);
7665     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7666                  GLColor::red.data());
7667     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7668     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7669     ASSERT_GL_NO_ERROR();
7670 
7671     drawQuad(program, "inputAttribute", 0.5f);
7672     ASSERT_GL_NO_ERROR();
7673     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7674 }
7675 
7676 // This is a regression test to make sure a red quad is rendered without issues
7677 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)7678 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
7679 {
7680     constexpr char kVS[] =
7681         "precision mediump float;\n"
7682         "attribute vec4 inputAttribute;\n"
7683         "varying mediump vec2 texCoord;\n"
7684         "void main() {\n"
7685         "    texCoord = inputAttribute.xy;\n"
7686         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7687         "}\n";
7688 
7689     constexpr char kFS[] =
7690         "precision mediump float;\n"
7691         "varying mediump vec2 texCoord;\n"
7692         "uniform sampler2D testSampler;\n"
7693         "vec4 passthrough(vec4 c) {\n"
7694         "    return c;\n"
7695         "}\n"
7696         "void main() {\n"
7697         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
7698         "}\n";
7699     ANGLE_GL_PROGRAM(program, kVS, kFS);
7700 
7701     // Initialize basic red texture.
7702     GLTexture texture;
7703     glBindTexture(GL_TEXTURE_2D, texture);
7704     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7705                  GLColor::red.data());
7706     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7707     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7708     ASSERT_GL_NO_ERROR();
7709 
7710     drawQuad(program, "inputAttribute", 0.5f);
7711     ASSERT_GL_NO_ERROR();
7712     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7713 }
7714 
7715 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)7716 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
7717 {
7718     // TODO(syoussefi): fails on android with:
7719     //
7720     // > Internal Vulkan error: A return array was too small for the result
7721     //
7722     // http://anglebug.com/3220
7723     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
7724     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7725     // struct members. Not sure if it's being overly strict.
7726     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7727 
7728     constexpr char kVS[] =
7729         "#version 300 es\n"
7730         "in vec4 inputAttribute;\n"
7731         "struct S {\n"
7732         "    vec4 field1;\n"
7733         "    vec4 field2;\n"
7734         "};\n"
7735         "out S varStruct;\n"
7736         "out S varStruct2;\n"
7737         "void main()\n"
7738         "{\n"
7739         "    gl_Position = inputAttribute;\n"
7740         "    varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7741         "    varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7742         "    varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7743         "    varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7744         "}\n";
7745 
7746     constexpr char kFS[] =
7747         "#version 300 es\n"
7748         "precision mediump float;\n"
7749         "out vec4 col;\n"
7750         "struct S {\n"
7751         "    vec4 field1;\n"
7752         "    vec4 field2;\n"
7753         "};\n"
7754         "in S varStruct;\n"
7755         "in S varStruct2;\n"
7756         "void main()\n"
7757         "{\n"
7758         "    col = varStruct.field1 + varStruct2.field2;\n"
7759         "}\n";
7760 
7761     ANGLE_GL_PROGRAM(program, kVS, kFS);
7762     drawQuad(program, "inputAttribute", 0.5f);
7763     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7764 }
7765 
7766 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)7767 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
7768 {
7769     constexpr char kVS[] =
7770         "#version 300 es\n"
7771         "in vec4 inputAttribute;\n"
7772         "out vec4 varArray[4];\n"
7773         "void main()\n"
7774         "{\n"
7775         "    gl_Position = inputAttribute;\n"
7776         "    varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
7777         "    varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
7778         "    varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
7779         "    varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
7780         "}\n";
7781 
7782     constexpr char kFS[] =
7783         "#version 300 es\n"
7784         "precision mediump float;\n"
7785         "out vec4 col;\n"
7786         "void main()\n"
7787         "{\n"
7788         "    col = vec4(0.0, 0.0, 0.0, 1.0);\n"
7789         "}\n";
7790 
7791     ANGLE_GL_PROGRAM(program, kVS, kFS);
7792     drawQuad(program, "inputAttribute", 0.5f);
7793     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7794 }
7795 
7796 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)7797 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
7798 {
7799     constexpr char kVS[] =
7800         "#version 300 es\n"
7801         "in vec4 inputAttribute;\n"
7802         "struct S {\n"
7803         "    vec4 field;\n"
7804         "};\n"
7805         "out S varStruct;\n"
7806         "out S varStruct2;\n"
7807         "void main()\n"
7808         "{\n"
7809         "    gl_Position = inputAttribute;\n"
7810         "    varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7811         "    varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7812         "}\n";
7813 
7814     constexpr char kFS[] =
7815         "#version 300 es\n"
7816         "precision mediump float;\n"
7817         "out vec4 col;\n"
7818         "struct S {\n"
7819         "    vec4 field;\n"
7820         "};\n"
7821         "in S varStruct;\n"
7822         "in S varStruct2;\n"
7823         "void main()\n"
7824         "{\n"
7825         "    col = varStruct.field;\n"
7826         "}\n";
7827 
7828     ANGLE_GL_PROGRAM(program, kVS, kFS);
7829     drawQuad(program, "inputAttribute", 0.5f);
7830     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7831 }
7832 
7833 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)7834 TEST_P(GLSLTest_ES3, VaryingMatrices)
7835 {
7836     constexpr char kVS[] =
7837         "#version 300 es\n"
7838         "in vec4 inputAttribute;\n"
7839         "out mat2x2 varMat;\n"
7840         "out mat2x2 varMat2;\n"
7841         "out mat4x3 varMat3;\n"
7842         "void main()\n"
7843         "{\n"
7844         "    gl_Position = inputAttribute;\n"
7845         "    varMat[0] = vec2(1, 1);\n"
7846         "    varMat[1] = vec2(1, 1);\n"
7847         "    varMat2[0] = vec2(0.5, 0.5);\n"
7848         "    varMat2[1] = vec2(0.5, 0.5);\n"
7849         "    varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
7850         "    varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
7851         "    varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
7852         "    varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
7853         "}\n";
7854 
7855     constexpr char kFS[] =
7856         "#version 300 es\n"
7857         "precision mediump float;\n"
7858         "out vec4 col;\n"
7859         "in mat2x2 varMat;\n"
7860         "in mat2x2 varMat2;\n"
7861         "in mat4x3 varMat3;\n"
7862         "void main()\n"
7863         "{\n"
7864         "    col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
7865         "}\n";
7866 
7867     ANGLE_GL_PROGRAM(program, kVS, kFS);
7868     drawQuad(program, "inputAttribute", 0.5f);
7869     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
7870 }
7871 
7872 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)7873 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
7874 {
7875     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7876     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7877 
7878     const char kFragmentShader[] = R"(precision mediump float;
7879 struct S { sampler2D samplerMember; };
7880 uniform S uStruct;
7881 uniform vec2 uTexCoord;
7882 vec4 foo(S structVar)
7883 {
7884     return texture2D(structVar.samplerMember, uTexCoord);
7885 }
7886 void main()
7887 {
7888     gl_FragColor = foo(uStruct);
7889 })";
7890 
7891     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7892 
7893     // Initialize the texture with green.
7894     GLTexture tex;
7895     glActiveTexture(GL_TEXTURE0);
7896     glBindTexture(GL_TEXTURE_2D, tex);
7897     GLubyte texData[] = {0u, 255u, 0u, 255u};
7898     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7899     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7900     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7901     ASSERT_GL_NO_ERROR();
7902 
7903     // Draw
7904     glUseProgram(program);
7905     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
7906     ASSERT_NE(-1, samplerMemberLoc);
7907     glUniform1i(samplerMemberLoc, 0);
7908     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7909     ASSERT_NE(-1, texCoordLoc);
7910     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7911 
7912     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7913     ASSERT_GL_NO_ERROR();
7914 
7915     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7916 }
7917 
7918 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)7919 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
7920 {
7921     // Shader failed to compile on Android. http://anglebug.com/2114
7922     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
7923 
7924     const char kFragmentShader[] = R"(precision mediump float;
7925 struct S { sampler2D samplerMember; };
7926 uniform S uStruct;
7927 uniform vec2 uTexCoord;
7928 vec4 foo(S structVar);
7929 vec4 foo(S structVar)
7930 {
7931     return texture2D(structVar.samplerMember, uTexCoord);
7932 }
7933 void main()
7934 {
7935     gl_FragColor = foo(uStruct);
7936 })";
7937 
7938     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7939 
7940     // Initialize the texture with green.
7941     GLTexture tex;
7942     glActiveTexture(GL_TEXTURE0);
7943     glBindTexture(GL_TEXTURE_2D, tex);
7944     GLubyte texData[] = {0u, 255u, 0u, 255u};
7945     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7946     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7947     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7948     ASSERT_GL_NO_ERROR();
7949 
7950     // Draw
7951     glUseProgram(program);
7952     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
7953     ASSERT_NE(-1, samplerMemberLoc);
7954     glUniform1i(samplerMemberLoc, 0);
7955     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7956     ASSERT_NE(-1, texCoordLoc);
7957     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7958 
7959     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7960     ASSERT_GL_NO_ERROR();
7961 
7962     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7963 }
7964 
7965 // This test covers passing a struct containing a sampler as a function argument, where the function
7966 // has non-return branch statements.
TEST_P(GLSLTest_ES3,StructsWithSamplersAsFunctionArgWithBranch)7967 TEST_P(GLSLTest_ES3, StructsWithSamplersAsFunctionArgWithBranch)
7968 {
7969     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7970     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7971 
7972     const char kFragmentShader[] = R"(precision mediump float;
7973 struct S { sampler2D samplerMember; };
7974 uniform S uStruct;
7975 uniform vec2 uTexCoord;
7976 vec4 foo(S structVar)
7977 {
7978     vec4 result;
7979     while (true)
7980     {
7981         result = texture2D(structVar.samplerMember, uTexCoord);
7982         if (result.x == 12345.)
7983         {
7984             continue;
7985         }
7986         break;
7987     }
7988     return result;
7989 }
7990 void main()
7991 {
7992     gl_FragColor = foo(uStruct);
7993 })";
7994 
7995     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7996 
7997     // Initialize the texture with green.
7998     GLTexture tex;
7999     glActiveTexture(GL_TEXTURE0);
8000     glBindTexture(GL_TEXTURE_2D, tex);
8001     GLubyte texData[] = {0u, 255u, 0u, 255u};
8002     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8003     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8004     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8005     ASSERT_GL_NO_ERROR();
8006 
8007     // Draw
8008     glUseProgram(program);
8009     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8010     ASSERT_NE(-1, samplerMemberLoc);
8011     glUniform1i(samplerMemberLoc, 0);
8012     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8013     ASSERT_NE(-1, texCoordLoc);
8014     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8015 
8016     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8017     ASSERT_GL_NO_ERROR();
8018 
8019     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8020 }
8021 
8022 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)8023 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
8024 {
8025     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8026     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8027 
8028     constexpr char kFS[] =
8029         "precision mediump float;\n"
8030         "struct S\n"
8031         "{\n"
8032         "    sampler2D samplerMember; \n"
8033         "};\n"
8034         "uniform S uStructs[2];\n"
8035         "uniform vec2 uTexCoord;\n"
8036         "\n"
8037         "vec4 foo(S[2] structs)\n"
8038         "{\n"
8039         "    return texture2D(structs[0].samplerMember, uTexCoord);\n"
8040         "}\n"
8041         "void main()\n"
8042         "{\n"
8043         "    gl_FragColor = foo(uStructs);\n"
8044         "}\n";
8045 
8046     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8047 
8048     // Initialize the texture with green.
8049     GLTexture tex;
8050     glActiveTexture(GL_TEXTURE0);
8051     glBindTexture(GL_TEXTURE_2D, tex);
8052     GLubyte texData[] = {0u, 255u, 0u, 255u};
8053     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8054     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8055     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8056     ASSERT_GL_NO_ERROR();
8057 
8058     // Draw
8059     glUseProgram(program);
8060     GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
8061     ASSERT_NE(-1, samplerMemberLoc);
8062     glUniform1i(samplerMemberLoc, 0);
8063     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8064     ASSERT_NE(-1, texCoordLoc);
8065     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8066 
8067     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8068     ASSERT_GL_NO_ERROR();
8069 
8070     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8071 }
8072 
8073 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)8074 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
8075 {
8076     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8077     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8078 
8079     constexpr char kFS[] =
8080         "precision mediump float;\n"
8081         "struct S\n"
8082         "{\n"
8083         "    sampler2D samplerMembers[2];\n"
8084         "};\n"
8085         "uniform S uStruct;\n"
8086         "uniform vec2 uTexCoord;\n"
8087         "\n"
8088         "vec4 foo(S str)\n"
8089         "{\n"
8090         "    return texture2D(str.samplerMembers[0], uTexCoord);\n"
8091         "}\n"
8092         "void main()\n"
8093         "{\n"
8094         "    gl_FragColor = foo(uStruct);\n"
8095         "}\n";
8096 
8097     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8098 
8099     // Initialize the texture with green.
8100     GLTexture tex;
8101     glActiveTexture(GL_TEXTURE0);
8102     glBindTexture(GL_TEXTURE_2D, tex);
8103     GLubyte texData[] = {0u, 255u, 0u, 255u};
8104     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8105     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8106     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8107     ASSERT_GL_NO_ERROR();
8108 
8109     // Draw
8110     glUseProgram(program);
8111     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
8112     ASSERT_NE(-1, samplerMemberLoc);
8113     glUniform1i(samplerMemberLoc, 0);
8114     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8115     ASSERT_NE(-1, texCoordLoc);
8116     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8117 
8118     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8119     ASSERT_GL_NO_ERROR();
8120 
8121     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8122 }
8123 
8124 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)8125 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
8126 {
8127     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8128     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8129 
8130     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
8131     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8132 
8133     const char kFragmentShader[] = R"(precision mediump float;
8134 struct S { sampler2D samplerMember; };
8135 struct T { S nest; };
8136 uniform T uStruct;
8137 uniform vec2 uTexCoord;
8138 vec4 foo2(S structVar)
8139 {
8140     return texture2D(structVar.samplerMember, uTexCoord);
8141 }
8142 vec4 foo(T structVar)
8143 {
8144     return foo2(structVar.nest);
8145 }
8146 void main()
8147 {
8148     gl_FragColor = foo(uStruct);
8149 })";
8150 
8151     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8152 
8153     // Initialize the texture with green.
8154     GLTexture tex;
8155     glActiveTexture(GL_TEXTURE0);
8156     glBindTexture(GL_TEXTURE_2D, tex);
8157     GLubyte texData[] = {0u, 255u, 0u, 255u};
8158     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8159     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8160     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8161     ASSERT_GL_NO_ERROR();
8162 
8163     // Draw
8164     glUseProgram(program);
8165     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8166     ASSERT_NE(-1, samplerMemberLoc);
8167     glUniform1i(samplerMemberLoc, 0);
8168     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8169     ASSERT_NE(-1, texCoordLoc);
8170     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8171 
8172     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8173     ASSERT_GL_NO_ERROR();
8174 
8175     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8176 }
8177 
8178 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)8179 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
8180 {
8181     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8182     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8183 
8184     const char kFragmentShader[] = R"(precision mediump float;
8185 struct S { sampler2D samplerMember; bool b; };
8186 uniform S uStruct;
8187 uniform vec2 uTexCoord;
8188 vec4 foo(S structVar)
8189 {
8190     if (structVar.b)
8191         return texture2D(structVar.samplerMember, uTexCoord);
8192     else
8193         return vec4(1, 0, 0, 1);
8194 }
8195 void main()
8196 {
8197     gl_FragColor = foo(uStruct);
8198 })";
8199 
8200     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8201 
8202     // Initialize the texture with green.
8203     GLTexture tex;
8204     glActiveTexture(GL_TEXTURE0);
8205     glBindTexture(GL_TEXTURE_2D, tex);
8206     GLubyte texData[] = {0u, 255u, 0u, 255u};
8207     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8208     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8209     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8210     ASSERT_GL_NO_ERROR();
8211 
8212     // Draw
8213     glUseProgram(program);
8214     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8215     ASSERT_NE(-1, samplerMemberLoc);
8216     glUniform1i(samplerMemberLoc, 0);
8217     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8218     ASSERT_NE(-1, texCoordLoc);
8219     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8220     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8221     ASSERT_NE(-1, bLoc);
8222     glUniform1i(bLoc, 1);
8223 
8224     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8225     ASSERT_GL_NO_ERROR();
8226 
8227     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8228 }
8229 
8230 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)8231 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
8232 {
8233     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8234     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8235 
8236     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
8237     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8238 
8239     const char kFragmentShader[] = R"(precision mediump float;
8240 struct S { sampler2D samplerMember; bool b; };
8241 struct T { S nest; bool b; };
8242 uniform T uStruct;
8243 uniform vec2 uTexCoord;
8244 vec4 foo2(S structVar)
8245 {
8246     if (structVar.b)
8247         return texture2D(structVar.samplerMember, uTexCoord);
8248     else
8249         return vec4(1, 0, 0, 1);
8250 }
8251 vec4 foo(T structVar)
8252 {
8253     if (structVar.b)
8254         return foo2(structVar.nest);
8255     else
8256         return vec4(1, 0, 0, 1);
8257 }
8258 void main()
8259 {
8260     gl_FragColor = foo(uStruct);
8261 })";
8262 
8263     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8264 
8265     // Initialize the texture with green.
8266     GLTexture tex;
8267     glActiveTexture(GL_TEXTURE0);
8268     glBindTexture(GL_TEXTURE_2D, tex);
8269     GLubyte texData[] = {0u, 255u, 0u, 255u};
8270     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8271     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8272     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8273     ASSERT_GL_NO_ERROR();
8274 
8275     // Draw
8276     glUseProgram(program);
8277     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8278     ASSERT_NE(-1, samplerMemberLoc);
8279     glUniform1i(samplerMemberLoc, 0);
8280     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8281     ASSERT_NE(-1, texCoordLoc);
8282     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8283 
8284     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8285     ASSERT_NE(-1, bLoc);
8286     glUniform1i(bLoc, 1);
8287 
8288     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8289     ASSERT_NE(-1, nestbLoc);
8290     glUniform1i(nestbLoc, 1);
8291 
8292     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8293     ASSERT_GL_NO_ERROR();
8294 
8295     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8296 }
8297 
8298 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)8299 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
8300 {
8301     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8302     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8303 
8304     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
8305     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8306 
8307     const char kFragmentShader[] = R"(precision mediump float;
8308 struct S { bool b; sampler2D samplerMember; };
8309 struct T { bool b; S nest; };
8310 uniform T uStruct;
8311 uniform vec2 uTexCoord;
8312 vec4 foo2(S structVar)
8313 {
8314     if (structVar.b)
8315         return texture2D(structVar.samplerMember, uTexCoord);
8316     else
8317         return vec4(1, 0, 0, 1);
8318 }
8319 vec4 foo(T structVar)
8320 {
8321     if (structVar.b)
8322         return foo2(structVar.nest);
8323     else
8324         return vec4(1, 0, 0, 1);
8325 }
8326 void main()
8327 {
8328     gl_FragColor = foo(uStruct);
8329 })";
8330 
8331     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8332 
8333     // Initialize the texture with green.
8334     GLTexture tex;
8335     glActiveTexture(GL_TEXTURE0);
8336     glBindTexture(GL_TEXTURE_2D, tex);
8337     GLubyte texData[] = {0u, 255u, 0u, 255u};
8338     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8339     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8340     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8341     ASSERT_GL_NO_ERROR();
8342 
8343     // Draw
8344     glUseProgram(program);
8345     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8346     ASSERT_NE(-1, samplerMemberLoc);
8347     glUniform1i(samplerMemberLoc, 0);
8348     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8349     ASSERT_NE(-1, texCoordLoc);
8350     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8351 
8352     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8353     ASSERT_NE(-1, bLoc);
8354     glUniform1i(bLoc, 1);
8355 
8356     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8357     ASSERT_NE(-1, nestbLoc);
8358     glUniform1i(nestbLoc, 1);
8359 
8360     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8361     ASSERT_GL_NO_ERROR();
8362 
8363     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8364 }
8365 // Test that a global variable declared after main() works. This is a regression test for an issue
8366 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)8367 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
8368 {
8369     constexpr char kFS[] =
8370         "precision mediump float;\n"
8371         "int getFoo();\n"
8372         "uniform int u_zero;\n"
8373         "void main()\n"
8374         "{\n"
8375         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
8376         "    if (getFoo() == 0)\n"
8377         "    {\n"
8378         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
8379         "    }\n"
8380         "}\n"
8381         "int foo;\n"
8382         "int getFoo()\n"
8383         "{\n"
8384         "    foo = u_zero;\n"
8385         "    return foo;\n"
8386         "}\n";
8387 
8388     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8389     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8390     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8391 }
8392 
8393 // Test calling array length() with a "this" expression having side effects inside a loop condition.
8394 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)8395 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
8396 {
8397     // "a" gets doubled three times in the below program.
8398     constexpr char kFS[] = R"(#version 300 es
8399 precision highp float;
8400 out vec4 my_FragColor;
8401 uniform int u_zero;
8402 int a;
8403 int[2] doubleA()
8404 {
8405     a *= 2;
8406     return int[2](a, a);
8407 }
8408 void main()
8409 {
8410     a = u_zero + 1;
8411     for (int i = 0; i < doubleA().length(); ++i)
8412     {}
8413     if (a == 8)
8414     {
8415         my_FragColor = vec4(0, 1, 0, 1);
8416     }
8417     else
8418     {
8419         my_FragColor = vec4(1, 0, 0, 1);
8420     }
8421 })";
8422 
8423     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8424     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8425     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8426 }
8427 
8428 // Test calling array length() with a "this" expression having side effects that interact with side
8429 // effects of another operand of the same sequence operator. The spec says that sequence operator
8430 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)8431 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
8432 {
8433     constexpr char kFS[] = R"(#version 300 es
8434 precision highp float;
8435 out vec4 my_FragColor;
8436 uniform int u_zero;
8437 int a;
8438 int[3] doubleA()
8439 {
8440     a *= 2;
8441     return int[3](a, a, a);
8442 }
8443 void main()
8444 {
8445     a = u_zero;
8446     int b = (a++, doubleA().length());
8447     if (b == 3 && a == 2)
8448     {
8449         my_FragColor = vec4(0, 1, 0, 1);
8450     }
8451     else
8452     {
8453         my_FragColor = vec4(1, 0, 0, 1);
8454     }
8455 })";
8456 
8457     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8458     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8459     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8460 }
8461 
8462 // Test calling array length() with a "this" expression that also contains a call of array length().
8463 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)8464 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
8465 {
8466     constexpr char kFS[] = R"(#version 300 es
8467 precision highp float;
8468 out vec4 my_FragColor;
8469 uniform int u_zero;
8470 int a;
8471 int[3] multiplyA(int multiplier)
8472 {
8473     a *= multiplier;
8474     return int[3](a, a, a);
8475 }
8476 void main()
8477 {
8478     a = u_zero + 1;
8479     int b = multiplyA(multiplyA(2).length()).length();
8480     if (b == 3 && a == 6)
8481     {
8482         my_FragColor = vec4(0, 1, 0, 1);
8483     }
8484     else
8485     {
8486         my_FragColor = vec4(1, 0, 0, 1);
8487     }
8488 })";
8489 
8490     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8491     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8492     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8493 }
8494 
8495 // Test calling array length() with a "this" expression having side effects inside an if condition.
8496 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)8497 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
8498 {
8499     // Bug in the shader translator.  http://anglebug.com/3829
8500     ANGLE_SKIP_TEST_IF(true);
8501 
8502     // "a" shouldn't get modified by this shader.
8503     constexpr char kFS[] = R"(#version 300 es
8504 precision highp float;
8505 out vec4 my_FragColor;
8506 uniform int u_zero;
8507 int a;
8508 int[2] doubleA()
8509 {
8510     a *= 2;
8511     return int[2](a, a);
8512 }
8513 void main()
8514 {
8515     a = u_zero + 1;
8516     if (u_zero != 0 && doubleA().length() == 2)
8517     {
8518         ++a;
8519     }
8520     if (a == 1)
8521     {
8522         my_FragColor = vec4(0, 1, 0, 1);
8523     }
8524     else
8525     {
8526         my_FragColor = vec4(1, 0, 0, 1);
8527     }
8528 })";
8529 
8530     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8531     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8532     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8533 }
8534 
8535 // Test calling array length() with a "this" expression having side effects in a statement where the
8536 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)8537 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
8538 {
8539     // Bug in the shader translator.  http://anglebug.com/3829
8540     ANGLE_SKIP_TEST_IF(true);
8541 
8542     // "a" shouldn't get modified by this shader.
8543     constexpr char kFS[] = R"(#version 300 es
8544 precision highp float;
8545 out vec4 my_FragColor;
8546 uniform int u_zero;
8547 int a;
8548 int[2] doubleA()
8549 {
8550     a *= 2;
8551     return int[2](a, a);
8552 }
8553 void main()
8554 {
8555     a = u_zero + 1;
8556     bool test = u_zero != 0 && doubleA().length() == 2;
8557     if (a == 1)
8558     {
8559         my_FragColor = vec4(0, 1, 0, 1);
8560     }
8561     else
8562     {
8563         my_FragColor = vec4(1, 0, 0, 1);
8564     }
8565 })";
8566 
8567     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8568     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8569     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8570 }
8571 
8572 // Test that array length inside vector constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructor)8573 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructor)
8574 {
8575     const char kVS[] = R"(#version 300 es
8576 precision highp float;
8577 flat out uvec4 v;
8578 
8579 int[1] f0()
8580 {
8581     return int[1](1);
8582 }
8583 void main()
8584 {
8585     v = uvec4(vec4(f0().length()));
8586 
8587     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8588     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8589     gl_Position.zw = vec2(0, 1);
8590 })";
8591 
8592     const char kFS[] = R"(#version 300 es
8593 precision highp float;
8594 flat in uvec4 v;
8595 out vec4 color;
8596 
8597 bool isEq(uint a, float b) { return abs(float(a) - b) < 0.01; }
8598 
8599 void main()
8600 {
8601     if (isEq(v[0], 1.) &&
8602         isEq(v[1], 1.) &&
8603         isEq(v[2], 1.) &&
8604         isEq(v[3], 1.))
8605     {
8606         color = vec4(0, 1, 0, 1);
8607     }
8608     else
8609     {
8610         color = vec4(1, 0, 0, 1);
8611     }
8612 })";
8613 
8614     ANGLE_GL_PROGRAM(program, kVS, kFS);
8615     glUseProgram(program);
8616     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8617     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8618 }
8619 
8620 // Test that array length inside vector constructor works in complex expression.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructorComplex)8621 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructorComplex)
8622 {
8623     const char kVS[] = R"(#version 300 es
8624 precision highp float;
8625 out vec4 v;
8626 
8627 int[1] f0()
8628 {
8629     return int[1](1);
8630 }
8631 void main()
8632 {
8633     v = vec4(float(uint(f0().length()) + 1u) / 4.);
8634 
8635     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8636     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8637     gl_Position.zw = vec2(0, 1);
8638 })";
8639 
8640     const char kFS[] = R"(#version 300 es
8641 precision highp float;
8642 in vec4 v;
8643 out vec4 color;
8644 
8645 bool isEq(float a, float b) { return abs(float(a) - b) < 0.01; }
8646 
8647 void main()
8648 {
8649     if (isEq(v[0], 0.5) &&
8650         isEq(v[1], 0.5) &&
8651         isEq(v[2], 0.5) &&
8652         isEq(v[3], 0.5))
8653     {
8654         color = vec4(0, 1, 0, 1);
8655     }
8656     else
8657     {
8658         color = vec4(1, 0, 0, 1);
8659     }
8660 })";
8661 
8662     ANGLE_GL_PROGRAM(program, kVS, kFS);
8663     glUseProgram(program);
8664     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8665     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8666 }
8667 
8668 // Test that array length inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInMatrixConstructor)8669 TEST_P(GLSLTest_ES3, ArrayLengthInMatrixConstructor)
8670 {
8671     const char kVS[] = R"(#version 300 es
8672 precision highp float;
8673 out mat2x2 v;
8674 
8675 int[1] f0()
8676 {
8677     return int[1](1);
8678 }
8679 void main()
8680 {
8681     v = mat2x2(f0().length());
8682 
8683     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8684     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8685     gl_Position.zw = vec2(0, 1);
8686 })";
8687 
8688     const char kFS[] = R"(#version 300 es
8689 precision highp float;
8690 in mat2x2 v;
8691 out vec4 color;
8692 
8693 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8694 
8695 void main()
8696 {
8697     if (isEq(v[0][0], 1.) &&
8698         isEq(v[0][1], 0.) &&
8699         isEq(v[1][0], 0.) &&
8700         isEq(v[1][1], 1.))
8701     {
8702         color = vec4(0, 1, 0, 1);
8703     }
8704     else
8705     {
8706         color = vec4(1, 0, 0, 1);
8707     }
8708 })";
8709 
8710     ANGLE_GL_PROGRAM(program, kVS, kFS);
8711     glUseProgram(program);
8712     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8713     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8714 }
8715 
8716 // Test that array length inside vector constructor inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorInMatrixConstructor)8717 TEST_P(GLSLTest_ES3, ArrayLengthInVectorInMatrixConstructor)
8718 {
8719     const char kVS[] = R"(#version 300 es
8720 precision highp float;
8721 out mat2x2 v;
8722 
8723 int[1] f0()
8724 {
8725     return int[1](1);
8726 }
8727 void main()
8728 {
8729     v = mat2x2(vec2(f0().length()), f0().length(), 0);
8730 
8731     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8732     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8733     gl_Position.zw = vec2(0, 1);
8734 })";
8735 
8736     const char kFS[] = R"(#version 300 es
8737 precision highp float;
8738 in mat2x2 v;
8739 out vec4 color;
8740 
8741 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8742 
8743 void main()
8744 {
8745     if (isEq(v[0][0], 1.) &&
8746         isEq(v[0][1], 1.) &&
8747         isEq(v[1][0], 1.) &&
8748         isEq(v[1][1], 0.))
8749     {
8750         color = vec4(0, 1, 0, 1);
8751     }
8752     else
8753     {
8754         color = vec4(1, 0, 0, 1);
8755     }
8756 })";
8757 
8758     ANGLE_GL_PROGRAM(program, kVS, kFS);
8759     glUseProgram(program);
8760     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8761     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8762 }
8763 
8764 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)8765 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
8766 {
8767     constexpr char kFS[] = R"(#version 300 es
8768 precision highp float;
8769 uniform int u;
8770 void main()
8771 {
8772     switch (u)
8773     {
8774         case 0:
8775             ivec2 i;
8776             i.yx;
8777     }
8778 })";
8779 
8780     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8781 }
8782 
8783 // Test that switch fall-through works correctly.
8784 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)8785 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
8786 {
8787     constexpr char kFS[] = R"(#version 300 es
8788 precision highp float;
8789 out vec4 my_FragColor;
8790 uniform int u_zero;
8791 
8792 void main()
8793 {
8794     int i = 0;
8795     // switch should fall through both cases.
8796     switch(u_zero)
8797     {
8798         case 0:
8799             i += 1;
8800         case 1:
8801             i += 2;
8802     }
8803     if (i == 3)
8804     {
8805         my_FragColor = vec4(0, 1, 0, 1);
8806     }
8807     else
8808     {
8809         my_FragColor = vec4(1, 0, 0, 1);
8810     }
8811 })";
8812 
8813     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8814     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8815     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8816 }
8817 
8818 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)8819 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
8820 {
8821     constexpr char kFS[] = R"(#version 300 es
8822 
8823 precision highp float;
8824 out vec4 my_FragColor;
8825 
8826 uniform int u_zero;
8827 
8828 void main()
8829 {
8830     switch (u_zero)
8831     {
8832         case 1:
8833             my_FragColor = vec4(1, 0, 0, 1);
8834             break;
8835         default:
8836             my_FragColor = vec4(0, 1, 0, 1);
8837     }
8838 })";
8839 
8840     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8841     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8842     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8843 }
8844 
8845 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)8846 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
8847 {
8848     constexpr char kFS[] = R"(#version 300 es
8849 
8850 precision mediump float;
8851 uniform int i;
8852 void main()
8853 {
8854     switch (i)
8855     {
8856         case 0:
8857             break;
8858         default:
8859             {}
8860     }
8861 })";
8862     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8863 }
8864 
8865 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)8866 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
8867 {
8868     constexpr char kFS[] = R"(#version 300 es
8869 
8870 precision mediump float;
8871 uniform int i;
8872 void main()
8873 {
8874     switch (i)
8875     {
8876         case 0:
8877             break;
8878         default:
8879             float;
8880     }
8881 })";
8882     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8883 }
8884 
8885 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)8886 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
8887 {
8888     constexpr char kFS[] = R"(#version 300 es
8889 
8890 precision highp float;
8891 
8892 uniform int u_zero;
8893 out vec4 my_FragColor;
8894 
8895 bool test(int n)
8896 {
8897     switch(n) {
8898         case 0:
8899         {
8900             {
8901                 break;
8902             }
8903         }
8904         case 1:
8905         {
8906             return true;
8907         }
8908         case 2:
8909         {
8910             n++;
8911         }
8912     }
8913     return false;
8914 }
8915 
8916 void main()
8917 {
8918     my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
8919 })";
8920 
8921     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8922     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8923     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8924 }
8925 
8926 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
8927 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)8928 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
8929 {
8930     constexpr char kFS[] = R"(#version 300 es
8931 
8932 precision highp float;
8933 out vec4 my_FragColor;
8934 
8935 uniform int u_zero;
8936 
8937 void main()
8938 {
8939     my_FragColor = vec4(1, 0, 0, 1);
8940     switch (u_zero)
8941     {
8942         case 0:
8943             ivec2 i;
8944             i = ivec2(1, 0);
8945         default:
8946             my_FragColor = vec4(0, i[0], 0, 1);
8947     }
8948 })";
8949 
8950     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8951     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8952     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8953 }
8954 
8955 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
8956 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)8957 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
8958 {
8959     constexpr char kFS[] = R"(#version 300 es
8960 
8961 precision highp float;
8962 out vec4 my_FragColor;
8963 
8964 uniform int u_zero;
8965 uniform int u_zero2;
8966 
8967 void main()
8968 {
8969     my_FragColor = vec4(1, 0, 0, 1);
8970     switch (u_zero)
8971     {
8972         case 0:
8973             ivec2 i;
8974             i = ivec2(1, 0);
8975             switch (u_zero2)
8976             {
8977                 case 0:
8978                     int j;
8979                 default:
8980                     j = 1;
8981                     i *= j;
8982             }
8983         default:
8984             my_FragColor = vec4(0, i[0], 0, 1);
8985     }
8986 })";
8987 
8988     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8989     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8990     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8991 }
8992 
8993 // Test that an empty switch/case statement is translated in a way that compiles and executes the
8994 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)8995 TEST_P(GLSLTest_ES3, EmptySwitch)
8996 {
8997     constexpr char kFS[] = R"(#version 300 es
8998 
8999 precision highp float;
9000 
9001 uniform int u_zero;
9002 out vec4 my_FragColor;
9003 
9004 void main()
9005 {
9006     int i = u_zero;
9007     switch(++i) {}
9008     my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9009 })";
9010 
9011     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9012     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9013     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9014 }
9015 
9016 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)9017 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
9018 {
9019     // Incorrect output color was seen on Android. http://anglebug.com/2226
9020     ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
9021 
9022     constexpr char kFS[] = R"(#version 300 es
9023 
9024 precision highp float;
9025 out vec4 my_FragColor;
9026 
9027 uniform float u_zero;
9028 
9029 struct S
9030 {
9031     float field;
9032 };
9033 
9034 void main()
9035 {
9036     const S constS = S(1.0);
9037     S nonConstS = constS;
9038     nonConstS.field = u_zero;
9039     bool fail = (constS == nonConstS);
9040     my_FragColor = vec4(0, 1, 0, 1);
9041     if (fail)
9042     {
9043         my_FragColor = vec4(1, 0, 0, 1);
9044     }
9045 })";
9046 
9047     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9048     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9049     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9050 }
9051 
9052 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)9053 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
9054 {
9055     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
9056     // struct member. Not sure if it's being overly strict.
9057     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
9058     constexpr char kVS[] = R"(#version 300 es
9059 in vec4 inputAttribute;
9060 
9061 flat out struct S
9062 {
9063     int field;
9064 } v_s;
9065 
9066 void main()
9067 {
9068     v_s.field = 1;
9069     gl_Position = inputAttribute;
9070 })";
9071 
9072     constexpr char kFS[] = R"(#version 300 es
9073 
9074 precision highp float;
9075 out vec4 my_FragColor;
9076 
9077 flat in struct S
9078 {
9079     int field;
9080 } v_s;
9081 
9082 void main()
9083 {
9084     bool success = (v_s.field == 1);
9085     my_FragColor = vec4(1, 0, 0, 1);
9086     if (success)
9087     {
9088         my_FragColor = vec4(0, 1, 0, 1);
9089     }
9090 })";
9091 
9092     ANGLE_GL_PROGRAM(program, kVS, kFS);
9093     drawQuad(program, "inputAttribute", 0.5f);
9094     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9095 }
9096 
9097 // Test that multi variables struct should not crash in separated struct expressions.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition2)9098 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition2)
9099 {
9100     constexpr char kVS[] = R"(#version 300 es
9101 in vec4 inputAttribute;
9102 flat out struct A
9103 {
9104     int a;
9105 } z1, z2;
9106 void main()
9107 {
9108     z1.a = 1;
9109     z2.a = 2;
9110     gl_Position = inputAttribute;
9111 })";
9112     constexpr char kFS[] = R"(#version 300 es
9113 precision highp float;
9114 out vec4 my_FragColor;
9115 flat in struct A
9116 {
9117     int a;
9118 } z1, z2;
9119 void main()
9120 {
9121     bool success = (z1.a == 1 && z2.a == 2);
9122     my_FragColor = vec4(1, 0, 0, 1);
9123     if (success)
9124     {
9125         my_FragColor = vec4(0, 1, 0, 1);
9126     }
9127 })";
9128     ANGLE_GL_PROGRAM(program, kVS, kFS);
9129     drawQuad(program.get(), "inputAttribute", 0.5f);
9130     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9131 }
9132 
9133 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)9134 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
9135 {
9136     constexpr char kVS[] = R"(#version 300 es
9137 in vec4 position;
9138 uniform highp float inVal;
9139 out highp float myVarying;
9140 
9141 void main()
9142 {
9143     myVarying = inVal;
9144     gl_Position = position;
9145 })";
9146 
9147     constexpr char kFS[] = R"(#version 300 es
9148 precision highp float;
9149 out vec4 my_FragColor;
9150 in mediump float myVarying;
9151 
9152 void main()
9153 {
9154     my_FragColor = vec4(1, 0, 0, 1);
9155     if (myVarying > 1.0)
9156     {
9157         my_FragColor = vec4(0, 1, 0, 1);
9158     }
9159 })";
9160 
9161     ANGLE_GL_PROGRAM(program, kVS, kFS);
9162 
9163     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9164     glClear(GL_COLOR_BUFFER_BIT);
9165     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9166 
9167     glUseProgram(program);
9168     GLint positionLocation              = glGetAttribLocation(program, "position");
9169     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9170     for (Vector3 &vertex : quadVertices)
9171     {
9172         vertex.z() = 0.5f;
9173     }
9174     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9175     glEnableVertexAttribArray(positionLocation);
9176 
9177     GLint inValLoc = glGetUniformLocation(program, "inVal");
9178     ASSERT_NE(-1, inValLoc);
9179     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9180 
9181     glDrawArrays(GL_TRIANGLES, 0, 6);
9182     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9183 }
9184 
9185 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)9186 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
9187 {
9188     // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
9189     // precision", thus this is the same test as MismatchPrecisionFloat but including it for
9190     // completeness in case something changes.
9191     constexpr char kVS[] = R"(#version 300 es
9192 in vec4 position;
9193 uniform highp float inVal;
9194 out highp float myVarying;
9195 
9196 void main()
9197 {
9198     myVarying = inVal;
9199     gl_Position = position;
9200 })";
9201 
9202     constexpr char kFS[] = R"(#version 300 es
9203 precision highp float;
9204 out vec4 my_FragColor;
9205 in lowp float myVarying;
9206 
9207 void main()
9208 {
9209     my_FragColor = vec4(1, 0, 0, 1);
9210     if (myVarying > 1.0)
9211     {
9212         my_FragColor = vec4(0, 1, 0, 1);
9213     }
9214 })";
9215 
9216     ANGLE_GL_PROGRAM(program, kVS, kFS);
9217 
9218     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9219     glClear(GL_COLOR_BUFFER_BIT);
9220     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9221 
9222     glUseProgram(program);
9223     GLint positionLocation              = glGetAttribLocation(program, "position");
9224     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9225     for (Vector3 &vertex : quadVertices)
9226     {
9227         vertex.z() = 0.5f;
9228     }
9229     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9230     glEnableVertexAttribArray(positionLocation);
9231 
9232     GLint inValLoc = glGetUniformLocation(program, "inVal");
9233     ASSERT_NE(-1, inValLoc);
9234     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9235 
9236     glDrawArrays(GL_TRIANGLES, 0, 6);
9237     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9238 }
9239 
9240 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)9241 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
9242 {
9243     constexpr char kVS[] = R"(#version 300 es
9244 in vec2 position;
9245 uniform highp float inVal;
9246 out highp float myVarying;
9247 out highp vec2 texCoord;
9248 
9249 void main()
9250 {
9251     myVarying = inVal;
9252     gl_Position = vec4(position, 0, 1);
9253     texCoord = position * 0.5 + vec2(0.5);
9254 })";
9255 
9256     constexpr char kFS[] = R"(#version 300 es
9257 precision highp float;
9258 out vec4 my_FragColor;
9259 in mediump float myVarying;
9260 in mediump vec2 texCoord;
9261 
9262 void main()
9263 {
9264     my_FragColor = vec4(1, 0, 0, 1);
9265     if (myVarying > 1.0)
9266     {
9267         my_FragColor = vec4(0, 1, 0, 1);
9268     }
9269 })";
9270 
9271     ANGLE_GL_PROGRAM(program, kVS, kFS);
9272 
9273     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9274     glClear(GL_COLOR_BUFFER_BIT);
9275     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9276 
9277     glUseProgram(program);
9278     GLint positionLocation              = glGetAttribLocation(program, "position");
9279     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9280     for (Vector3 &vertex : quadVertices)
9281     {
9282         vertex.z() = 0.5f;
9283     }
9284     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9285     glEnableVertexAttribArray(positionLocation);
9286 
9287     GLint inValLoc = glGetUniformLocation(program, "inVal");
9288     ASSERT_NE(-1, inValLoc);
9289     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9290 
9291     glDrawArrays(GL_TRIANGLES, 0, 6);
9292     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9293 }
9294 
9295 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)9296 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
9297 {
9298     constexpr char kVS[] = R"(#version 300 es
9299 in vec2 position;
9300 uniform highp float inVal;
9301 out mediump float myVarying;
9302 
9303 void main()
9304 {
9305     myVarying = inVal;
9306     gl_Position = vec4(position, 0, 1);
9307 })";
9308 
9309     constexpr char kFS[] = R"(#version 300 es
9310 precision highp float;
9311 out vec4 my_FragColor;
9312 in highp float myVarying;
9313 
9314 void main()
9315 {
9316     my_FragColor = vec4(1, 0, 0, 1);
9317     if (myVarying > 1.0)
9318     {
9319         my_FragColor = vec4(0, 1, 0, 1);
9320     }
9321 })";
9322 
9323     ANGLE_GL_PROGRAM(program, kVS, kFS);
9324 
9325     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9326     glClear(GL_COLOR_BUFFER_BIT);
9327     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9328 
9329     glUseProgram(program);
9330     GLint positionLocation              = glGetAttribLocation(program, "position");
9331     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9332     for (Vector3 &vertex : quadVertices)
9333     {
9334         vertex.z() = 0.5f;
9335     }
9336     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9337     glEnableVertexAttribArray(positionLocation);
9338 
9339     GLint inValLoc = glGetUniformLocation(program, "inVal");
9340     ASSERT_NE(-1, inValLoc);
9341     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9342 
9343     glDrawArrays(GL_TRIANGLES, 0, 6);
9344     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9345 }
9346 
9347 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)9348 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
9349 {
9350     constexpr char kFS[] = R"(precision mediump float;
9351 
9352 void main() {
9353     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9354     for (int i = 0; i < 2; i++)
9355     {
9356         gl_FragColor += (2.0 * gl_FragCoord.x);
9357     }
9358     if (gl_FragColor.g == gl_FragColor.r &&
9359         gl_FragColor.b == gl_FragColor.r &&
9360         gl_FragColor.a == gl_FragColor.r)
9361     {
9362         gl_FragColor = vec4(0, 1, 0, 1);
9363     }
9364 })";
9365 
9366     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9367     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9368     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9369 }
9370 
9371 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)9372 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
9373 {
9374     constexpr char kFS[] = R"(precision mediump float;
9375 
9376 void main() {
9377     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9378     for (int i = 0; i < 2; i++)
9379     {
9380         float x = gl_FragCoord.x;
9381         gl_FragColor = gl_FragColor + (x /= 2.0);
9382     }
9383     if (gl_FragColor.g == gl_FragColor.r &&
9384         gl_FragColor.b == gl_FragColor.r &&
9385         gl_FragColor.a == gl_FragColor.r)
9386     {
9387         gl_FragColor = vec4(0, 1, 0, 1);
9388     }
9389 })";
9390 
9391     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9392     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9393     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9394 }
9395 
9396 // Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation.
TEST_P(GLSLTest,VectorScalarArithmeticWithSideEffectInLoop)9397 TEST_P(GLSLTest, VectorScalarArithmeticWithSideEffectInLoop)
9398 {
9399     // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past
9400     // (notice how sbcd references i outside the for loop.  The loop condition doesn't look right
9401     // either):
9402     //
9403     //     #version 450
9404     //     void main(){
9405     //     (gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
9406     //     mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
9407     //     vec3 _ures = vec3(0.0, 0.0, 0.0);
9408     //     vec3 sbcd = vec3(_ures[_ui]);
9409     //     for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)),
9410     //     sbcd)), _ui)], (_ui < 7)); )
9411     //     {
9412     //     }
9413     //     }
9414 
9415     constexpr char kVS[] = R"(
9416 void main()
9417 {
9418     mat3 tmp;
9419     vec3 res;
9420     for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;);
9421 })";
9422 
9423     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9424 
9425     const char *sourceArray[1] = {kVS};
9426     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
9427     glShaderSource(shader, 1, sourceArray, lengths);
9428     glCompileShader(shader);
9429 
9430     GLint compileResult;
9431     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9432     EXPECT_NE(compileResult, 0);
9433 }
9434 
9435 // Test that packing of excessive 3-column variables does not overflow the count of 3-column
9436 // variables in VariablePacker
TEST_P(WebGL2GLSLTest,ExcessiveMat3UniformPacking)9437 TEST_P(WebGL2GLSLTest, ExcessiveMat3UniformPacking)
9438 {
9439     std::ostringstream srcStream;
9440 
9441     srcStream << "#version 300 es\n";
9442     srcStream << "precision mediump float;\n";
9443     srcStream << "out vec4 finalColor;\n";
9444     srcStream << "in vec4 color;\n";
9445     srcStream << "uniform mat4 r[254];\n";
9446 
9447     srcStream << "uniform mat3 ";
9448     constexpr size_t kNumUniforms = 10000;
9449     for (size_t i = 0; i < kNumUniforms; ++i)
9450     {
9451         if (i > 0)
9452         {
9453             srcStream << ", ";
9454         }
9455         srcStream << "m3a_" << i << "[256]";
9456     }
9457     srcStream << ";\n";
9458 
9459     srcStream << "void main(void) { finalColor = color; }\n";
9460     std::string src = std::move(srcStream).str();
9461 
9462     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9463 
9464     const char *sourceArray[1] = {src.c_str()};
9465     GLint lengths[1]           = {static_cast<GLint>(src.length())};
9466     glShaderSource(shader, 1, sourceArray, lengths);
9467     glCompileShader(shader);
9468 
9469     GLint compileResult;
9470     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9471     EXPECT_EQ(compileResult, 0);
9472 }
9473 
9474 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
9475 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)9476 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
9477 {
9478     constexpr char kVS[] = R"(#version 300 es
9479 
9480 in vec4 inputAttribute;
9481 
9482 flat out int v;
9483 
9484 void main()
9485 {
9486     v = 1;
9487     gl_Position = inputAttribute;
9488 })";
9489 
9490     constexpr char kFS[] = R"(#version 300 es
9491 
9492 precision highp float;
9493 out vec4 my_FragColor;
9494 
9495 flat in int v;
9496 
9497 void main()
9498 {
9499     my_FragColor = vec4(0, (true ? v : 0), 0, 1);
9500 })";
9501 
9502     ANGLE_GL_PROGRAM(program, kVS, kFS);
9503     drawQuad(program, "inputAttribute", 0.5f);
9504     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9505 }
9506 
9507 // Verify that the link error message from last link failure is cleared when the new link is
9508 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)9509 TEST_P(GLSLTest, ClearLinkErrorLog)
9510 {
9511     constexpr char kVS[] = R"(attribute vec4 vert_in;
9512 varying vec4 vert_out;
9513 void main()
9514 {
9515     gl_Position = vert_in;
9516     vert_out = vert_in;
9517 })";
9518 
9519     constexpr char kFS[] = R"(precision mediump float;
9520 varying vec4 frag_in;
9521 void main()
9522 {
9523     gl_FragColor = frag_in;
9524 })";
9525 
9526     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
9527     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
9528 
9529     GLuint program = glCreateProgram();
9530 
9531     // The first time the program link fails because of lack of fragment shader.
9532     glAttachShader(program, vs);
9533     glLinkProgram(program);
9534     GLint linkStatus = GL_TRUE;
9535     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
9536     ASSERT_FALSE(linkStatus);
9537 
9538     const std::string lackOfFragmentShader = QueryErrorMessage(program);
9539     EXPECT_TRUE(lackOfFragmentShader != "");
9540 
9541     // The second time the program link fails because of the mismatch of the varying types.
9542     glAttachShader(program, fs);
9543     glLinkProgram(program);
9544     linkStatus = GL_TRUE;
9545     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
9546     ASSERT_FALSE(linkStatus);
9547 
9548     const std::string varyingTypeMismatch = QueryErrorMessage(program);
9549     EXPECT_TRUE(varyingTypeMismatch != "");
9550 
9551     EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
9552 
9553     glDetachShader(program, vs);
9554     glDetachShader(program, fs);
9555     glDeleteShader(vs);
9556     glDeleteShader(fs);
9557     glDeleteProgram(program);
9558 
9559     ASSERT_GL_NO_ERROR();
9560 }
9561 
9562 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)9563 TEST_P(GLSLTest, DrawAfterShaderLinkError)
9564 {
9565     constexpr char kVS[]    = R"(attribute vec4 position;
9566         varying vec4 vColor;
9567         void main()
9568         {
9569             vColor = vec4(0.0, 1.0, 0.0, 1.0);
9570             gl_Position = position;
9571         })";
9572     constexpr char kFS[]    = R"(precision mediump float;
9573         varying vec4 vColor;
9574         void main()
9575         {
9576             gl_FragColor = vColor;
9577         })";
9578     constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
9579 
9580     GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
9581 
9582     // Create bad fragment shader
9583     {
9584         const char *sourceArray[1] = {kBadFS};
9585         glShaderSource(fsBad, 1, sourceArray, nullptr);
9586         glCompileShader(fsBad);
9587 
9588         GLint compileResult;
9589         glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
9590         ASSERT_FALSE(compileResult);
9591     }
9592 
9593     ANGLE_GL_PROGRAM(program, kVS, kFS);
9594     GLuint fs = GetProgramShader(program, GL_FRAGMENT_SHADER);
9595 
9596     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9597     glClear(GL_COLOR_BUFFER_BIT);
9598     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9599 
9600     glUseProgram(program);
9601     GLint positionLocation              = glGetAttribLocation(program, "position");
9602     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9603     for (Vector3 &vertex : quadVertices)
9604     {
9605         vertex.z() = 0.5f;
9606     }
9607     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9608     glEnableVertexAttribArray(positionLocation);
9609     glDrawArrays(GL_TRIANGLES, 0, 6);
9610     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9611 
9612     glDetachShader(program, fs);
9613     glAttachShader(program, fsBad);
9614     glLinkProgram(program);
9615     GLint linkStatus = GL_TRUE;
9616     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
9617     ASSERT_FALSE(linkStatus);
9618 
9619     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9620     glClear(GL_COLOR_BUFFER_BIT);
9621     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9622 
9623     glDrawArrays(GL_TRIANGLES, 0, 6);
9624     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9625 }
9626 
9627 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)9628 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
9629 {
9630     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
9631 varying vec4 vertex_out;
9632 void main()
9633 {
9634     vertex_out = inputAttribute;
9635     gl_Position = inputAttribute;
9636 })";
9637 
9638     constexpr char kFS[] = R"(precision mediump float;
9639 varying float vertex_out;
9640 void main()
9641 {
9642     gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
9643 })";
9644 
9645     validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
9646 }
9647 
9648 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)9649 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
9650 {
9651     constexpr char kVS[] = R"(#version 300 es
9652 in vec4 inputAttribute;
9653 struct S {
9654     float val1;
9655     vec4 val2;
9656 };
9657 out S vertex_out;
9658 void main()
9659 {
9660     vertex_out.val2 = inputAttribute;
9661     vertex_out.val1 = inputAttribute[0];
9662     gl_Position = inputAttribute;
9663 })";
9664 
9665     constexpr char kFS[] = R"(#version 300 es
9666 precision mediump float;
9667 struct S {
9668     float val1;
9669     vec4 val3;
9670 };
9671 in S vertex_out;
9672 layout (location = 0) out vec4 frag_out;
9673 void main()
9674 {
9675     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
9676 })";
9677 
9678     validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
9679 }
9680 
9681 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)9682 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
9683 {
9684     constexpr char kVS[] = R"(#version 300 es
9685 in vec4 inputAttribute;
9686 struct S {
9687     float val1;
9688     vec4 val2;
9689 };
9690 out S vertex_out;
9691 void main()
9692 {
9693     vertex_out.val2 = inputAttribute;
9694     vertex_out.val1 = inputAttribute[0];
9695     gl_Position = inputAttribute;
9696 })";
9697 
9698     constexpr char kFS[] = R"(#version 300 es
9699 precision mediump float;
9700 struct S {
9701     float val1;
9702     vec2 val2;
9703 };
9704 in S vertex_out;
9705 layout (location = 0) out vec4 frag_out;
9706 void main()
9707 {
9708     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
9709 })";
9710 
9711     validateComponentsInErrorMessage(kVS, kFS, "Types",
9712                                      "varying 'vertex_out' member 'vertex_out.val2'");
9713 }
9714 
9715 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
9716 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)9717 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
9718 {
9719     constexpr char kVS[] = R"(
9720 struct T
9721 {
9722     vec2 t1;
9723     vec3 t2;
9724 };
9725 struct S {
9726     T val1;
9727     vec4 val2;
9728 };
9729 uniform S uni;
9730 
9731 attribute vec4 inputAttribute;
9732 varying vec4 vertex_out;
9733 void main()
9734 {
9735     vertex_out = uni.val2;
9736     gl_Position = inputAttribute;
9737 })";
9738 
9739     constexpr char kFS[] = R"(precision highp float;
9740 struct T
9741 {
9742     vec2 t1;
9743     vec3 t3;
9744 };
9745 struct S {
9746     T val1;
9747     vec4 val2;
9748 };
9749 uniform S uni;
9750 
9751 varying vec4 vertex_out;
9752 void main()
9753 {
9754     gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
9755 })";
9756 
9757     validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
9758 }
9759 
9760 // Validate error messages  when the link mismatch occurs on the type of a non-struct uniform block
9761 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)9762 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
9763 {
9764     constexpr char kVS[] = R"(#version 300 es
9765 uniform S {
9766     vec2 val1;
9767     vec4 val2;
9768 } uni;
9769 
9770 in vec4 inputAttribute;
9771 out vec4 vertex_out;
9772 void main()
9773 {
9774     vertex_out = uni.val2;
9775     gl_Position = inputAttribute;
9776 })";
9777 
9778     constexpr char kFS[] = R"(#version 300 es
9779 precision highp float;
9780 uniform S {
9781     vec2 val1;
9782     vec3 val2;
9783 } uni;
9784 
9785 in vec4 vertex_out;
9786 layout (location = 0) out vec4 frag_out;
9787 void main()
9788 {
9789     frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
9790 })";
9791 
9792     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
9793 }
9794 
9795 // Validate error messages  when the link mismatch occurs on the type of a member of a uniform block
9796 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)9797 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
9798 {
9799     constexpr char kVS[] = R"(#version 300 es
9800 struct T
9801 {
9802     vec2 t1;
9803     vec3 t2;
9804 };
9805 uniform S {
9806     T val1;
9807     vec4 val2;
9808 } uni;
9809 
9810 in vec4 inputAttribute;
9811 out vec4 vertex_out;
9812 void main()
9813 {
9814     vertex_out = uni.val2;
9815     gl_Position = inputAttribute;
9816 })";
9817 
9818     constexpr char kFS[] = R"(#version 300 es
9819 precision highp float;
9820 struct T
9821 {
9822     vec2 t1;
9823     vec4 t2;
9824 };
9825 uniform S {
9826     T val1;
9827     vec4 val2;
9828 } uni;
9829 
9830 in vec4 vertex_out;
9831 layout (location = 0) out vec4 frag_out;
9832 void main()
9833 {
9834     frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
9835 })";
9836 
9837     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
9838 }
9839 
9840 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
9841 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)9842 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
9843 {
9844     constexpr char kVS[] = R"(#version 300 es
9845 precision mediump float;
9846 
9847 void main()
9848 {
9849     gl_Position = vec4(0, 1, 0, 1);
9850 })";
9851 
9852     constexpr char kFS[] = R"(#version 300 es
9853 precision mediump float;
9854 in float foo;
9855 out vec4 my_FragColor;
9856 
9857 void main()
9858 {
9859     if (false)
9860     {
9861         float unreferenced = foo;
9862     }
9863     my_FragColor = vec4(0, 1, 0, 1);
9864 })";
9865 
9866     validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
9867 }
9868 
9869 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)9870 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
9871 {
9872     constexpr char kVS[] = R"(#version 300 es
9873 precision mediump float;
9874 in vec4 iv;
9875 out vec4 v;
9876 void main()
9877 {
9878     gl_Position = iv;
9879     v = iv;
9880 })";
9881 
9882     constexpr char kFS[] = R"(#version 300 es
9883 precision mediump float;
9884 in vec4 v;
9885 out vec4 color;
9886 void main()
9887 {
9888     color = true ? vec4(0.0) : v;
9889 })";
9890 
9891     ANGLE_GL_PROGRAM(program, kVS, kFS);
9892 }
9893 
9894 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)9895 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
9896 {
9897     constexpr char kVS[] = R"(#version 310 es
9898 precision highp float;
9899 in vec4 position;
9900 layout(location = 1) out vec4 shaderOutput;
9901 void main() {
9902     gl_Position = position;
9903     shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
9904 })";
9905 
9906     constexpr char kFS[] = R"(#version 310 es
9907 precision highp float;
9908 layout(location = 1) in vec4 shaderInput;
9909 out vec4 outColor;
9910 void main() {
9911     outColor = shaderInput;
9912 })";
9913 
9914     ANGLE_GL_PROGRAM(program, kVS, kFS);
9915     drawQuad(program, "position", 0.5f);
9916     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9917 }
9918 
9919 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)9920 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
9921 {
9922     // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
9923     // up red. http://crbug.com/838885
9924     ANGLE_SKIP_TEST_IF(IsD3D11());
9925 
9926     constexpr char kFS[] = R"(#version 300 es
9927 precision highp float;
9928 out vec4 my_FragColor;
9929 void main()
9930 {
9931     vec2 coord = gl_FragCoord.xy / 500.0;
9932     my_FragColor = vec4(1, 0, 0, 1);
9933     if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
9934     {
9935         my_FragColor = vec4(0, 1, 0, 1);
9936     }
9937 })";
9938 
9939     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9940     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9941     // Verify that all the corners of the rendered result are green.
9942     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9943     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
9944     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
9945     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
9946 }
9947 
9948 // Verify that a link error is generated when the sum of the number of active image uniforms and
9949 // active shader storage blocks in a rendering pipeline exceeds
9950 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)9951 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
9952 {
9953     // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
9954     // D3D11 back-ends.
9955     ANGLE_SKIP_TEST_IF(IsD3D11());
9956 
9957     GLint maxVertexShaderStorageBlocks;
9958     GLint maxVertexImageUniforms;
9959     GLint maxFragmentShaderStorageBlocks;
9960     GLint maxFragmentImageUniforms;
9961     GLint maxCombinedShaderStorageBlocks;
9962     GLint maxCombinedImageUniforms;
9963     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
9964     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
9965     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
9966     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
9967     glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
9968     glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
9969 
9970     ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
9971     ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
9972     ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
9973     ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
9974 
9975     GLint vertexSSBOs   = maxVertexShaderStorageBlocks;
9976     GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
9977     // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
9978     if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
9979     {
9980         fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
9981     }
9982 
9983     GLint vertexImages   = maxVertexImageUniforms;
9984     GLint fragmentImages = maxFragmentImageUniforms;
9985     // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
9986     if (vertexImages + fragmentImages > maxCombinedImageUniforms)
9987     {
9988         vertexImages = maxCombinedImageUniforms - fragmentImages;
9989     }
9990 
9991     GLint maxDrawBuffers;
9992     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
9993 
9994     GLint maxCombinedShaderOutputResources;
9995     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
9996     ASSERT_GL_NO_ERROR();
9997 
9998     ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
9999                            maxDrawBuffers <=
10000                        maxCombinedShaderOutputResources);
10001 
10002     std::ostringstream vertexStream;
10003     vertexStream << "#version 310 es\n";
10004     for (int i = 0; i < vertexSSBOs; ++i)
10005     {
10006         vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10007                      << "{\n"
10008                         "    float data;\n"
10009                         "} ssbo"
10010                      << i << ";\n";
10011     }
10012     vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
10013                  << "];\n";
10014     vertexStream << "void main()\n"
10015                     "{\n"
10016                     "    float val = 0.1;\n"
10017                     "    vec4 val2 = vec4(0.0);\n";
10018     for (int i = 0; i < vertexSSBOs; ++i)
10019     {
10020         vertexStream << "    val += ssbo" << i << ".data; \n";
10021     }
10022     for (int i = 0; i < vertexImages; ++i)
10023     {
10024         vertexStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10025     }
10026     vertexStream << "    gl_Position = vec4(val, val2);\n"
10027                     "}\n";
10028 
10029     std::ostringstream fragmentStream;
10030     fragmentStream << "#version 310 es\n" << "precision highp float;\n";
10031     for (int i = 0; i < fragmentSSBOs; ++i)
10032     {
10033         fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10034                        << "{\n"
10035                           "    float data;\n"
10036                           "} ssbo"
10037                        << i << ";\n";
10038     }
10039     fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
10040                    << fragmentImages << "];\n";
10041     fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
10042 
10043     fragmentStream << "void main()\n"
10044                       "{\n"
10045                       "    float val = 0.1;\n"
10046                       "    vec4 val2 = vec4(0.0);\n";
10047     for (int i = 0; i < fragmentSSBOs; ++i)
10048     {
10049         fragmentStream << "    val += ssbo" << i << ".data; \n";
10050     }
10051     for (int i = 0; i < fragmentImages; ++i)
10052     {
10053         fragmentStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10054     }
10055     for (int i = 0; i < maxDrawBuffers; ++i)
10056     {
10057         fragmentStream << "    foutput[" << i << "] = vec4(val, val2);\n";
10058     }
10059     fragmentStream << "}\n";
10060 
10061     GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
10062     EXPECT_EQ(0u, program);
10063 
10064     ASSERT_GL_NO_ERROR();
10065 }
10066 
10067 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
10068 // function works correctly.
TEST_P(GLSLTest_ES3,AssignToSwizzled)10069 TEST_P(GLSLTest_ES3, AssignToSwizzled)
10070 {
10071     constexpr char kFS[] = R"(#version 300 es
10072 precision highp float;
10073 out vec4 my_FragColor;
10074 
10075 uniform float uzero;
10076 
10077 vec3 fun(float s, float v)
10078 {
10079     vec3 r = vec3(0);
10080     if (s < 1.0) {
10081         r.x = r.y = r.z = v;
10082         return r;
10083     }
10084     return r;
10085 }
10086 
10087 void main()
10088 {
10089     my_FragColor.a = 1.0;
10090     my_FragColor.rgb = fun(uzero, 1.0);
10091 })";
10092 
10093     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10094     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10095     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10096 }
10097 
10098 // Similar to AssignToSwizzled, but uses other assignment operators than `=`.
TEST_P(GLSLTest_ES3,AssignToSwizzled2)10099 TEST_P(GLSLTest_ES3, AssignToSwizzled2)
10100 {
10101     constexpr char kFS[] = R"(#version 300 es
10102 precision highp float;
10103 out vec4 my_FragColor;
10104 
10105 uniform float uzero;
10106 
10107 vec3 fun(float s, float v)
10108 {
10109     vec3 r = vec3(0.125, 0.5, 0.);
10110     if (s < 1.0) {
10111         r.x /= r.y *= r.z += v;
10112         return r;
10113     }
10114     return r;
10115 }
10116 
10117 void main()
10118 {
10119     my_FragColor.a = 1.0;
10120     my_FragColor.rgb = fun(uzero, 1.0);
10121 })";
10122 
10123     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10124     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10125     EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 255, 1);
10126 }
10127 
10128 // Test a fragment shader that returns inside if (that being the only branch that actually gets
10129 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)10130 TEST_P(GLSLTest, IfElseIfAndReturn)
10131 {
10132     constexpr char kVS[] = R"(attribute vec4 a_position;
10133 varying vec2 vPos;
10134 void main()
10135 {
10136     gl_Position = a_position;
10137     vPos = a_position.xy;
10138 })";
10139 
10140     constexpr char kFS[] = R"(precision mediump float;
10141 varying vec2 vPos;
10142 void main()
10143 {
10144     if (vPos.x < 1.0) // This colors the whole canvas green
10145     {
10146         gl_FragColor = vec4(0, 1, 0, 1);
10147         return;
10148     }
10149     else if (vPos.x < 1.1) // This should have no effect
10150     {
10151         gl_FragColor = vec4(1, 0, 0, 1);
10152     }
10153 })";
10154 
10155     ANGLE_GL_PROGRAM(program, kVS, kFS);
10156     drawQuad(program, "a_position", 0.5f);
10157     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10158 }
10159 
10160 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)10161 TEST_P(GLSLTest, IfElsePrunedBlocks)
10162 {
10163     constexpr char kFS[] = R"(precision mediump float;
10164 uniform float u;
10165 void main()
10166 {
10167     // if with only a pruned true block
10168     if (u > 0.0)
10169         if (false) discard;
10170 
10171     // if with a pruned true block and a false block
10172     if (u > 0.0)
10173     {
10174         if (false) discard;
10175     }
10176     else
10177         ;
10178 
10179     // if with a true block and a pruned false block
10180     if (u > 0.0)
10181         ;
10182     else
10183         if (false) discard;
10184 
10185     // if with a pruned true block and a pruned false block
10186     if (u > 0.0)
10187     {
10188         if (false) discard;
10189     }
10190     else
10191         if (false) discard;
10192 
10193     gl_FragColor = vec4(0, 1, 0, 1);
10194 })";
10195 
10196     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10197     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10198     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10199 }
10200 
10201 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)10202 TEST_P(GLSLTest, PointCoordConsistency)
10203 {
10204     constexpr char kPointCoordVS[] = R"(attribute vec2 position;
10205 uniform vec2 viewportSize;
10206 void main()
10207 {
10208    gl_Position = vec4(position, 0, 1);
10209    gl_PointSize = viewportSize.x;
10210 })";
10211 
10212     constexpr char kPointCoordFS[] = R"(void main()
10213 {
10214     gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
10215 })";
10216 
10217     ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
10218     glUseProgram(program);
10219 
10220     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10221     ASSERT_NE(-1, uniLoc);
10222     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10223                 static_cast<GLfloat>(getWindowHeight()));
10224 
10225     // Draw to backbuffer.
10226     glClear(GL_COLOR_BUFFER_BIT);
10227     glDrawArrays(GL_POINTS, 0, 1);
10228     ASSERT_GL_NO_ERROR();
10229 
10230     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10231     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10232                  backbufferData.data());
10233 
10234     GLTexture tex;
10235     glBindTexture(GL_TEXTURE_2D, tex);
10236     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10237                  GL_UNSIGNED_BYTE, nullptr);
10238 
10239     GLFramebuffer fbo;
10240     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10241     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10242     ASSERT_GL_NO_ERROR();
10243     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10244 
10245     // Draw to user FBO.
10246     glClear(GL_COLOR_BUFFER_BIT);
10247     glDrawArrays(GL_POINTS, 0, 1);
10248     ASSERT_GL_NO_ERROR();
10249 
10250     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10251     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10252                  userFBOData.data());
10253 
10254     ASSERT_GL_NO_ERROR();
10255     ASSERT_EQ(userFBOData.size(), backbufferData.size());
10256     EXPECT_EQ(userFBOData, backbufferData);
10257 }
10258 
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)10259 bool SubrectEquals(const std::vector<GLColor> &bigArray,
10260                    const std::vector<GLColor> &smallArray,
10261                    int bigSize,
10262                    int offset,
10263                    int smallSize)
10264 {
10265     int badPixels = 0;
10266     for (int y = 0; y < smallSize; y++)
10267     {
10268         for (int x = 0; x < smallSize; x++)
10269         {
10270             int bigOffset   = (y + offset) * bigSize + x + offset;
10271             int smallOffset = y * smallSize + x;
10272             if (bigArray[bigOffset] != smallArray[smallOffset])
10273                 badPixels++;
10274         }
10275     }
10276     return badPixels == 0;
10277 }
10278 
10279 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)10280 TEST_P(GLSLTest, FragCoordConsistency)
10281 {
10282     constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
10283 void main()
10284 {
10285     gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
10286 })";
10287 
10288     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
10289     glUseProgram(program);
10290 
10291     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10292     ASSERT_NE(-1, uniLoc);
10293     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10294                 static_cast<GLfloat>(getWindowHeight()));
10295 
10296     // Draw to backbuffer.
10297     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10298     ASSERT_GL_NO_ERROR();
10299 
10300     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10301     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10302                  backbufferData.data());
10303 
10304     GLTexture tex;
10305     glBindTexture(GL_TEXTURE_2D, tex);
10306     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10307                  GL_UNSIGNED_BYTE, nullptr);
10308 
10309     GLFramebuffer fbo;
10310     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10311     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10312     ASSERT_GL_NO_ERROR();
10313     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10314 
10315     // Draw to user FBO.
10316     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10317     ASSERT_GL_NO_ERROR();
10318 
10319     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10320     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10321                  userFBOData.data());
10322 
10323     ASSERT_GL_NO_ERROR();
10324     ASSERT_EQ(userFBOData.size(), backbufferData.size());
10325     EXPECT_EQ(userFBOData, backbufferData)
10326         << "FragCoord should be the same to default and user FBO";
10327 
10328     // Repeat the same test but with a smaller viewport.
10329     ASSERT_EQ(getWindowHeight(), getWindowWidth());
10330     const int kQuarterSize = getWindowWidth() >> 2;
10331     glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
10332 
10333     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10334     glClear(GL_COLOR_BUFFER_BIT);
10335     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10336 
10337     std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
10338     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10339                  GL_UNSIGNED_BYTE, userFBOViewportData.data());
10340 
10341     glBindFramebuffer(GL_FRAMEBUFFER, 0);
10342     glClear(GL_COLOR_BUFFER_BIT);
10343     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10344 
10345     std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
10346     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10347                  GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
10348     ASSERT_GL_NO_ERROR();
10349     EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
10350         << "FragCoord should be the same to default and user FBO even with a custom viewport";
10351 
10352     // Check that the subrectangles are the same between the viewport and non-viewport modes.
10353     EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
10354                               kQuarterSize * 2));
10355     EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
10356                               kQuarterSize, kQuarterSize * 2));
10357 }
10358 
10359 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)10360 TEST_P(GLSLTest, DefinedInMacroSucceeds)
10361 {
10362     constexpr char kVS[] = R"(precision mediump float;
10363 attribute highp vec4 position;
10364 varying vec2 out0;
10365 
10366 void main()
10367 {
10368 #define AAA defined(BBB)
10369 
10370 #if !AAA
10371     out0 = vec2(0.0, 1.0);
10372 #else
10373     out0 = vec2(1.0, 0.0);
10374 #endif
10375     gl_Position = position;
10376 })";
10377 
10378     constexpr char kFS[] = R"(precision mediump float;
10379 varying vec2 out0;
10380 void main()
10381 {
10382     gl_FragColor = vec4(out0, 0, 1);
10383 })";
10384 
10385     ANGLE_GL_PROGRAM(program, kVS, kFS);
10386     drawQuad(program, "position", 0.5f);
10387     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10388 }
10389 
10390 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)10391 TEST_P(GLSLTest, DefinedInMacroWithUndef)
10392 {
10393     constexpr char kVS[] = R"(precision mediump float;
10394 attribute highp vec4 position;
10395 varying vec2 out0;
10396 
10397 void main()
10398 {
10399 #define BBB 1
10400 #define AAA defined(BBB)
10401 #undef BBB
10402 
10403 #if AAA
10404     out0 = vec2(1.0, 0.0);
10405 #else
10406     out0 = vec2(0.0, 1.0);
10407 #endif
10408     gl_Position = position;
10409 })";
10410 
10411     constexpr char kFS[] = R"(precision mediump float;
10412 varying vec2 out0;
10413 void main()
10414 {
10415     gl_FragColor = vec4(out0, 0, 1);
10416 })";
10417 
10418     ANGLE_GL_PROGRAM(program, kVS, kFS);
10419     drawQuad(program, "position", 0.5f);
10420     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10421 }
10422 
10423 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)10424 TEST_P(GLSLTest, DefinedAfterMacroUsage)
10425 {
10426     constexpr char kVS[] = R"(precision mediump float;
10427 attribute highp vec4 position;
10428 varying vec2 out0;
10429 
10430 void main()
10431 {
10432 #define AAA defined(BBB)
10433 #define BBB 1
10434 
10435 #if AAA
10436     out0 = vec2(0.0, 1.0);
10437 #else
10438     out0 = vec2(1.0, 0.0);
10439 #endif
10440     gl_Position = position;
10441 })";
10442 
10443     constexpr char kFS[] = R"(precision mediump float;
10444 varying vec2 out0;
10445 void main()
10446 {
10447     gl_FragColor = vec4(out0, 0, 1);
10448 })";
10449 
10450     ANGLE_GL_PROGRAM(program, kVS, kFS);
10451     drawQuad(program, "position", 0.5f);
10452     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10453 }
10454 
10455 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)10456 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
10457 {
10458     constexpr char kVS[] = R"(precision mediump float;
10459 attribute highp vec4 position;
10460 varying vec2 out0;
10461 
10462 void main()
10463 {
10464 #define BBB 1
10465 #define AAA(defi, ned) defi ## ned(BBB)
10466 
10467 #if AAA(defi, ned)
10468     out0 = vec2(0.0, 1.0);
10469 #else
10470     out0 = vec2(1.0, 0.0);
10471 #endif
10472     gl_Position = position;
10473 })";
10474 
10475     constexpr char kFS[] = R"(precision mediump float;
10476 varying vec2 out0;
10477 void main()
10478 {
10479     gl_FragColor = vec4(out0, 0, 1);
10480 })";
10481 
10482     GLuint program = CompileProgram(kVS, kFS);
10483     EXPECT_EQ(0u, program);
10484     glDeleteProgram(program);
10485 }
10486 
10487 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)10488 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
10489 {
10490     constexpr char kVS[] = R"(precision mediump float;
10491 attribute highp vec4 position;
10492 varying vec2 out0;
10493 
10494 void main()
10495 {
10496 #define BBB 1
10497 #define AAA(defined) defined(BBB)
10498 
10499 #if AAA(defined)
10500     out0 = vec2(0.0, 1.0);
10501 #else
10502     out0 = vec2(1.0, 0.0);
10503 #endif
10504     gl_Position = position;
10505 })";
10506 
10507     constexpr char kFS[] = R"(precision mediump float;
10508 varying vec2 out0;
10509 void main()
10510 {
10511     gl_FragColor = vec4(out0, 0, 1);
10512 })";
10513 
10514     GLuint program = CompileProgram(kVS, kFS);
10515     EXPECT_EQ(0u, program);
10516     glDeleteProgram(program);
10517 }
10518 
10519 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)10520 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
10521 {
10522     constexpr char kVS[] = R"(precision mediump float;
10523 attribute highp vec4 position;
10524 varying float out0;
10525 
10526 void main()
10527 {
10528 #define AAA defined(BBB)
10529 
10530 #if !AAA
10531     out0 = 1.0;
10532 #else
10533     out0 = 0.0;
10534 #endif
10535     gl_Position = dEQP_Position;
10536 })";
10537 
10538     constexpr char kFS[] = R"(precision mediump float;
10539 varying float out0;
10540 void main()
10541 {
10542     gl_FragColor = vec4(out0, 0, 0, 1);
10543 })";
10544 
10545     GLuint program = CompileProgram(kVS, kFS);
10546     EXPECT_EQ(0u, program);
10547     glDeleteProgram(program);
10548 }
10549 
10550 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)10551 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
10552 {
10553     constexpr char kVS[] = R"(void main()
10554 {
10555     gl_Position = vec4(1, 0, 0, 1);
10556 })";
10557 
10558     constexpr char kFS[] = R"(#if defined(GL_ES)
10559 precision mediump float;
10560 void main()
10561 {
10562     gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
10563 }
10564 #else
10565 foo
10566 #endif
10567 )";
10568 
10569     ANGLE_GL_PROGRAM(program, kVS, kFS);
10570 }
10571 
10572 // Test that inactive output variables compile ok in combination with initOutputVariables
10573 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)10574 TEST_P(WebGL2GLSLTest, InactiveOutput)
10575 {
10576     constexpr char kFS[] = R"(#version 300 es
10577 precision highp float;
10578 out vec4 _cassgl_2_;
10579 void main()
10580 {
10581 })";
10582 
10583     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
10584     EXPECT_NE(shader, 0u);
10585 }
10586 
10587 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)10588 TEST_P(GLSLTest, ValidIndexClampES100)
10589 {
10590     // http://anglebug.com/6027
10591     ANGLE_SKIP_TEST_IF(IsD3D9());
10592 
10593     constexpr char kFS[] = R"(
10594 precision mediump float;
10595 uniform int u;
10596 uniform mat4 m[2];
10597 void main()
10598 {
10599     gl_FragColor = vec4(m[u][1].xyz, 1);
10600 }
10601 )";
10602 
10603     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10604     glUseProgram(program);
10605 
10606     GLint uniformLocation = glGetUniformLocation(program, "u");
10607     ASSERT_NE(-1, uniformLocation);
10608 
10609     GLint matrixLocation = glGetUniformLocation(program, "m");
10610     ASSERT_NE(matrixLocation, -1);
10611     const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
10612                                              0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
10613                                              1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
10614                                              0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
10615     glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
10616 
10617     glUniform1i(uniformLocation, 1);
10618     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10619     EXPECT_GL_NO_ERROR();
10620 
10621     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10622 }
10623 
10624 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)10625 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
10626 {
10627     constexpr char kFS[] = R"(#version 300 es
10628 precision mediump float;
10629 out vec4 color;
10630 uniform int u;
10631 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
10632 void main()
10633 {
10634     color = vec4(m[u][2].xyz, 1);
10635 }
10636 )";
10637 
10638     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10639     glUseProgram(program);
10640 
10641     GLint uniformLocation = glGetUniformLocation(program, "u");
10642     ASSERT_NE(-1, uniformLocation);
10643 
10644     glUniform1i(uniformLocation, 2);
10645     EXPECT_GL_NO_ERROR();
10646     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10647     EXPECT_GL_NO_ERROR();
10648 
10649     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10650 }
10651 
10652 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)10653 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
10654 {
10655     constexpr char kFS[] = R"(#version 300 es
10656 precision mediump float;
10657 
10658 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
10659 const mat4x2 matB = mat4x2(1.0/2.0, 1.0/4.0, 1.0/8.0, 1.0/16.0, 1.0/32.0, 1.0/64.0, 1.0/128.0, 1.0/256.0);
10660 
10661 out vec4 color;
10662 
10663 void main()
10664 {
10665     mat4x2 result = matrixCompMult(matA, matB);
10666     vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
10667     if (vresult == vec2(4.0, 4.0))
10668     {
10669         color = vec4(0.0, 1.0, 0.0, 1.0);
10670     }
10671     else
10672     {
10673         color = vec4(1.0, 0.0, 0.0, 1.0);
10674     }
10675 })";
10676 
10677     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10678     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10679     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10680 }
10681 
10682 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)10683 TEST_P(GLSLTest_ES3, InitSameNameArray)
10684 {
10685     constexpr char kFS[] = R"(#version 300 es
10686       precision highp float;
10687       out vec4 my_FragColor;
10688 
10689       void main()
10690       {
10691           float arr[2] = float[2](1.0, 1.0);
10692           {
10693               float arr[2] = arr;
10694               my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
10695           }
10696       })";
10697 
10698     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10699     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10700     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10701 }
10702 
10703 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)10704 TEST_P(GLSLTest, FragData)
10705 {
10706     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
10707     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10708     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10709     EXPECT_GL_NO_ERROR();
10710     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10711 }
10712 
10713 // Tests using gl_FragData[0] instead of gl_FragColor with GL_SAMPLE_ALPHA_TO_COVERAGE
10714 // Regression test for https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5520
TEST_P(GLSLTest,FragData_AlphaToCoverage)10715 TEST_P(GLSLTest, FragData_AlphaToCoverage)
10716 {
10717     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
10718     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10719     glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
10720     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10721     EXPECT_GL_NO_ERROR();
10722     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10723 }
10724 
10725 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)10726 TEST_P(GLSLTest, MemoryExhaustedTest)
10727 {
10728     GLuint program =
10729         CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
10730     EXPECT_NE(0u, program);
10731 }
10732 
10733 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)10734 TEST_P(GLSLTest, InactiveSamplersInStruct)
10735 {
10736     constexpr char kVS[] = R"(attribute vec4 a_position;
10737 void main() {
10738   gl_Position = a_position;
10739 })";
10740 
10741     constexpr char kFS[] = R"(precision highp float;
10742 struct S
10743 {
10744     vec4 v;
10745     sampler2D t[10];
10746 };
10747 uniform S s;
10748 void main() {
10749   gl_FragColor = s.v;
10750 })";
10751 
10752     ANGLE_GL_PROGRAM(program, kVS, kFS);
10753 
10754     drawQuad(program, "a_position", 0.5f);
10755 }
10756 
10757 // Helper functions for MixedRowAndColumnMajorMatrices* tests
10758 
10759 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)10760 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
10761 {
10762     return (value + alignment - 1) & ~(alignment - 1);
10763 }
10764 
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)10765 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
10766 {
10767     unsigned int outputInitData = 0;
10768     glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
10769     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10770     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
10771     EXPECT_GL_NO_ERROR();
10772 }
10773 
10774 // Fill provided buffer with matrices based on the given dimensions.  The buffer should be large
10775 // enough to accomodate the data.
FillBuffer(const std::pair<uint32_t,uint32_t> matrixDims[],const bool matrixIsColMajor[],size_t matrixCount,float data[],bool isStd430,bool isTransposed)10776 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
10777                     const bool matrixIsColMajor[],
10778                     size_t matrixCount,
10779                     float data[],
10780                     bool isStd430,
10781                     bool isTransposed)
10782 {
10783     size_t offset = 0;
10784     for (size_t m = 0; m < matrixCount; ++m)
10785     {
10786         uint32_t cols   = matrixDims[m].first;
10787         uint32_t rows   = matrixDims[m].second;
10788         bool isColMajor = matrixIsColMajor[m] != isTransposed;
10789 
10790         uint32_t arraySize              = isColMajor ? cols : rows;
10791         uint32_t arrayElementComponents = isColMajor ? rows : cols;
10792         // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
10793         // MixedRowAndColumnMajorMatrices* tests don't use).  With std430, small matrices can have
10794         // a stride of 2 between rows/columns.
10795         uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
10796 
10797         offset = RoundUpPow2(offset, stride);
10798 
10799         for (uint32_t i = 0; i < arraySize; ++i)
10800         {
10801             for (uint32_t c = 0; c < arrayElementComponents; ++c)
10802             {
10803                 uint32_t row = isColMajor ? c : i;
10804                 uint32_t col = isColMajor ? i : c;
10805 
10806                 data[offset + i * stride + c] = col * 4 + row;
10807             }
10808         }
10809 
10810         offset += arraySize * stride;
10811     }
10812     return offset;
10813 }
10814 
10815 // Initialize and bind the buffer.
10816 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)10817 void InitBuffer(GLuint program,
10818                 const char *name,
10819                 GLuint buffer,
10820                 uint32_t bindingIndex,
10821                 const T data[],
10822                 uint32_t dataSize,
10823                 bool isUniform)
10824 {
10825     GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
10826 
10827     glBindBufferBase(bindPoint, bindingIndex, buffer);
10828     glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
10829 
10830     if (isUniform)
10831     {
10832         GLint blockIndex = glGetUniformBlockIndex(program, name);
10833         glUniformBlockBinding(program, blockIndex, bindingIndex);
10834     }
10835 }
10836 
10837 // Verify that buffer data is written by the shader as expected.
10838 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)10839 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
10840 {
10841     uint32_t sizeInBytes = dataSize * sizeof(*data);
10842 
10843     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10844 
10845     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
10846 
10847     const T *ptr = reinterpret_cast<const T *>(
10848         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeInBytes, GL_MAP_READ_BIT));
10849 
10850     bool isCorrect = memcmp(ptr, data, sizeInBytes) == 0;
10851     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10852 
10853     return isCorrect;
10854 }
10855 
10856 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)10857 bool VerifySuccess(GLuint buffer)
10858 {
10859     uint32_t success = 1;
10860     return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
10861 }
10862 
10863 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
10864 // both std140 and std430 layouts.  Tests many combinations of std140 vs std430, struct being used
10865 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
10866 // nested structs, matrix arrays, inout parameters etc.
10867 //
10868 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)10869 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
10870 {
10871     GLint maxComputeShaderStorageBlocks;
10872     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
10873 
10874     // The test uses 9 SSBOs.  Skip if not that many are supported.
10875     ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
10876 
10877     // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
10878     // UBO also see it as row-major despite explicit column-major qualifier.
10879     // http://anglebug.com/3830
10880     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
10881 
10882     // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
10883     // read column-major despite explicit row-major qualifier.  http://anglebug.com/3837
10884     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10885 
10886     // Fails on windows AMD on GL: http://anglebug.com/3838
10887     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
10888 
10889     // Fails to compile the shader on Android.  http://anglebug.com/3839
10890     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
10891 
10892     // Fails on assertion in translation to D3D.  http://anglebug.com/3841
10893     ANGLE_SKIP_TEST_IF(IsD3D11());
10894 
10895     // Fails on SSBO validation on Android/Vulkan.  http://anglebug.com/3840
10896     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
10897 
10898     // Fails input verification as well as std140 SSBO validation.  http://anglebug.com/3844
10899     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
10900 
10901     // Fails on ARM on Vulkan.  http://anglebug.com/4492
10902     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
10903 
10904     constexpr char kCS[] = R"(#version 310 es
10905 precision highp float;
10906 layout(local_size_x=1) in;
10907 
10908 struct Inner
10909 {
10910     mat3x4 m3c4r;
10911     mat4x3 m4c3r;
10912 };
10913 
10914 struct Matrices
10915 {
10916     mat2 m2c2r;
10917     mat2x3 m2c3r[2];
10918     mat3x2 m3c2r;
10919     Inner inner;
10920 };
10921 
10922 // For simplicity, the layouts are either of:
10923 // - col-major mat4, row-major rest
10924 // - row-major mat4, col-major rest
10925 //
10926 // The former is tagged with c, the latter with r.
10927 layout(std140, column_major) uniform Ubo140c
10928 {
10929     mat4 m4c4r;
10930     layout(row_major) Matrices m;
10931 } ubo140cIn;
10932 
10933 layout(std140, row_major) uniform Ubo140r
10934 {
10935     mat4 m4c4r;
10936     layout(column_major) Matrices m;
10937 } ubo140rIn;
10938 
10939 layout(std140, row_major, binding = 0) buffer Ssbo140c
10940 {
10941     layout(column_major) mat4 m4c4r;
10942     Matrices m;
10943 } ssbo140cIn;
10944 
10945 layout(std140, column_major, binding = 1) buffer Ssbo140r
10946 {
10947     layout(row_major) mat4 m4c4r;
10948     Matrices m;
10949 } ssbo140rIn;
10950 
10951 layout(std430, column_major, binding = 2) buffer Ssbo430c
10952 {
10953     mat4 m4c4r;
10954     layout(row_major) Matrices m;
10955 } ssbo430cIn;
10956 
10957 layout(std430, row_major, binding = 3) buffer Ssbo430r
10958 {
10959     mat4 m4c4r;
10960     layout(column_major) Matrices m;
10961 } ssbo430rIn;
10962 
10963 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
10964 {
10965     layout(column_major) mat4 m4c4r;
10966     Matrices m;
10967 } ssbo140cOut;
10968 
10969 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
10970 {
10971     layout(row_major) mat4 m4c4r;
10972     Matrices m;
10973 } ssbo140rOut;
10974 
10975 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
10976 {
10977     mat4 m4c4r;
10978     layout(row_major) Matrices m;
10979 } ssbo430cOut;
10980 
10981 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
10982 {
10983     mat4 m4c4r;
10984     layout(column_major) Matrices m;
10985 } ssbo430rOut;
10986 
10987 layout(std140, binding = 8) buffer Result
10988 {
10989     uint success;
10990 } resultOut;
10991 
10992 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
10993 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
10994 
10995 #define VERIFY_IN(result, mat, cols, rows)                  \
10996     EXPECT(result, mat[0].x, 0.0);                          \
10997     EXPECT(result, mat[0][1], 1.0);                         \
10998     EXPECTV(result, mat[0].xy, vec2(0, 1));                 \
10999     EXPECTV(result, mat[1].xy, vec2(4, 5));                 \
11000     for (int c = 0; c < cols; ++c)                          \
11001     {                                                       \
11002         for (int r = 0; r < rows; ++r)                      \
11003         {                                                   \
11004             EXPECT(result, mat[c][r], float(c * 4 + r));    \
11005         }                                                   \
11006     }
11007 
11008 #define COPY(matIn, matOut, cols, rows)     \
11009     matOut = matOut + matIn;                \
11010     /* random operations for testing */     \
11011     matOut[0].x += matIn[0].x + matIn[1].x; \
11012     matOut[0].x -= matIn[1].x;              \
11013     matOut[0][1] += matIn[0][1];            \
11014     matOut[1] += matIn[1];                  \
11015     matOut[1].xy -= matIn[1].xy;            \
11016     /* undo the above to get back matIn */  \
11017     matOut[0].x -= matIn[0].x;              \
11018     matOut[0][1] -= matIn[0][1];            \
11019     matOut[1] -= matIn[1];                  \
11020     matOut[1].xy += matIn[1].xy;
11021 
11022 bool verifyMatrices(in Matrices m)
11023 {
11024     bool result = true;
11025     VERIFY_IN(result, m.m2c2r, 2, 2);
11026     VERIFY_IN(result, m.m2c3r[0], 2, 3);
11027     VERIFY_IN(result, m.m2c3r[1], 2, 3);
11028     VERIFY_IN(result, m.m3c2r, 3, 2);
11029     VERIFY_IN(result, m.inner.m3c4r, 3, 4);
11030     VERIFY_IN(result, m.inner.m4c3r, 4, 3);
11031     return result;
11032 }
11033 
11034 mat4 copyMat4(in mat4 m)
11035 {
11036     return m;
11037 }
11038 
11039 void copyMatrices(in Matrices mIn, inout Matrices mOut)
11040 {
11041     COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
11042     COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
11043     COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
11044     COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
11045     COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
11046     COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
11047 }
11048 
11049 void main()
11050 {
11051     bool result = true;
11052 
11053     VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
11054     VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
11055     EXPECT(result, verifyMatrices(ubo140cIn.m), true);
11056 
11057     VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
11058     VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
11059     EXPECT(result, verifyMatrices(ubo140rIn.m), true);
11060 
11061     VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
11062     VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
11063     EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
11064 
11065     VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
11066     VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
11067     EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
11068 
11069     VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
11070     VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
11071     EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
11072 
11073     VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
11074     VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
11075     EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
11076 
11077     // Only assign to SSBO from a single invocation.
11078     if (gl_GlobalInvocationID.x == 0u)
11079     {
11080         ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
11081         copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
11082         ssbo140cOut.m.m2c3r[1] = mat2x3(0);
11083         COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
11084 
11085         ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
11086         copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
11087         ssbo140rOut.m.inner.m3c4r = mat3x4(0);
11088         COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
11089 
11090         ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
11091         copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
11092         ssbo430cOut.m.m3c2r = mat3x2(0);
11093         COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
11094 
11095         ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
11096         copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
11097         ssbo430rOut.m.inner.m4c3r = mat4x3(0);
11098         COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
11099 
11100         resultOut.success = uint(result);
11101     }
11102 })";
11103 
11104     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11105     EXPECT_GL_NO_ERROR();
11106 
11107     constexpr size_t kMatrixCount                                     = 7;
11108     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11109         {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
11110     };
11111     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11112         true, false, false, false, false, false, false,
11113     };
11114 
11115     float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
11116     float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
11117     float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
11118     float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
11119     float dataZeros[kMatrixCount * 4 * 4]          = {};
11120 
11121     const uint32_t sizeStd140ColMajor =
11122         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
11123     const uint32_t sizeStd140RowMajor =
11124         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
11125     const uint32_t sizeStd430ColMajor =
11126         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
11127     const uint32_t sizeStd430RowMajor =
11128         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
11129 
11130     GLBuffer uboStd140ColMajor, uboStd140RowMajor;
11131     GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
11132     GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
11133     GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
11134     GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
11135 
11136     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11137                true);
11138     InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11139                true);
11140     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11141                false);
11142     InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11143                false);
11144     InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
11145                false);
11146     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
11147                false);
11148     InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
11149                false);
11150     InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
11151                false);
11152     InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
11153                false);
11154     InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
11155                false);
11156     EXPECT_GL_NO_ERROR();
11157 
11158     GLBuffer outputBuffer;
11159     CreateOutputBuffer(&outputBuffer, 8);
11160 
11161     glUseProgram(program);
11162     glDispatchCompute(1, 1, 1);
11163     EXPECT_GL_NO_ERROR();
11164     EXPECT_TRUE(VerifySuccess(outputBuffer));
11165 
11166     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
11167     EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
11168     EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
11169     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
11170 }
11171 
11172 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)11173 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
11174 {
11175     constexpr char kFS[] = R"(#version 300 es
11176 precision highp float;
11177 out vec4 outColor;
11178 
11179 layout(std140, row_major) uniform Ubo
11180 {
11181     mat4 m1;
11182 };
11183 
11184 void main()
11185 {
11186     outColor = m1[3] / 255.0;
11187 })";
11188 
11189     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11190     EXPECT_GL_NO_ERROR();
11191 
11192     constexpr size_t kMatrixCount                                     = 1;
11193     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11194         {4, 4},
11195     };
11196     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11197         false,
11198     };
11199 
11200     float data[kMatrixCount * 4 * 4] = {};
11201 
11202     const uint32_t size =
11203         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11204 
11205     GLBuffer ubos;
11206 
11207     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11208 
11209     EXPECT_GL_NO_ERROR();
11210 
11211     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11212     EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
11213 }
11214 
11215 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)11216 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
11217 {
11218     constexpr char kFS[] = R"(#version 300 es
11219 precision highp float;
11220 out vec4 outColor;
11221 
11222 layout(std140, row_major) uniform Ubo
11223 {
11224     mat2x3 m1;
11225 };
11226 
11227 void main()
11228 {
11229     outColor = vec4(m1[1], 0) / 255.0;
11230 })";
11231 
11232     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11233     EXPECT_GL_NO_ERROR();
11234 
11235     constexpr size_t kMatrixCount                                     = 1;
11236     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11237         {2, 3},
11238     };
11239     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11240         false,
11241     };
11242 
11243     float data[kMatrixCount * 3 * 4] = {};
11244 
11245     const uint32_t size =
11246         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11247 
11248     GLBuffer ubos;
11249 
11250     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11251 
11252     EXPECT_GL_NO_ERROR();
11253 
11254     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11255     EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
11256 }
11257 
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)11258 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
11259 {
11260     constexpr char kFS[] = R"(#version 300 es
11261 precision highp float;
11262 out vec4 outColor;
11263 
11264 layout(std140, row_major) uniform Ubo
11265 {
11266     mat3x2 m1;
11267 };
11268 
11269 void main()
11270 {
11271     outColor = vec4(m1[2], 0, 0) / 255.0;
11272 })";
11273 
11274     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11275     EXPECT_GL_NO_ERROR();
11276 
11277     constexpr size_t kMatrixCount                                     = 1;
11278     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11279         {3, 2},
11280     };
11281     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11282         false,
11283     };
11284 
11285     float data[kMatrixCount * 2 * 4] = {};
11286 
11287     const uint32_t size =
11288         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11289 
11290     GLBuffer ubos;
11291 
11292     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11293 
11294     EXPECT_GL_NO_ERROR();
11295 
11296     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11297     EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
11298 }
11299 
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)11300 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
11301 {
11302     // Many OpenGL drivers seem to fail this
11303     ANGLE_SKIP_TEST_IF((IsLinux() || IsMac()) && IsOpenGL());
11304 
11305     constexpr char kFS[] = R"(#version 300 es
11306 precision mediump float;
11307 
11308 uniform Ubo {
11309   layout(row_major) mat4 u_mat[3];
11310   layout(row_major) mat4 u_ndx[3];
11311 } stuff;
11312 
11313 precision highp float;
11314 out vec4 outColor;
11315 
11316 void main() {
11317   outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
11318 }
11319 )";
11320 
11321     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11322     EXPECT_GL_NO_ERROR();
11323 
11324     typedef float vec4[4];
11325     typedef vec4 mat4[4];
11326 
11327     constexpr size_t kMatrixCount = 6;
11328     mat4 data[]                   = {
11329         {
11330             {0, 1, 2, 3},      //
11331             {4, 5, 6, 7},      //
11332             {8, 9, 10, 11},    //
11333             {12, 13, 14, 15},  //
11334         },
11335         {
11336             //     +-- we should be looking up this column
11337             //     V
11338             {0, 4, 8, 12},   //
11339             {1, 5, 9, 13},   //
11340             {2, 6, 10, 14},  //
11341             {3, 7, 11, 15},  //
11342         },
11343         {
11344             {0, 2, 4, 6},      //
11345             {8, 10, 12, 14},   //
11346             {16, 18, 20, 22},  //
11347             {24, 26, 28, 30},  //
11348         },
11349         {
11350             {0, 0, 0, 0},  //
11351             {0, 0, 0, 0},  //
11352             {0, 0, 0, 0},  //
11353             {0, 0, 0, 0},  //
11354         },
11355         {
11356             {0, 0, 0, 0},  //
11357             {0, 0, 0, 2},  //
11358             {0, 0, 0, 0},  //
11359             {0, 1, 0, 0},
11360             //  ^
11361             //  +-- we should be using this element
11362         },
11363         {
11364             {0, 0, 0, 0},  //
11365             {0, 0, 0, 0},  //
11366             {0, 0, 0, 0},  //
11367             {0, 0, 0, 0},  //
11368         },
11369     };
11370 
11371     GLBuffer ubos;
11372     InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
11373     EXPECT_GL_NO_ERROR();
11374 
11375     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11376     EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
11377 }
11378 
11379 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)11380 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
11381 {
11382     // Fails to compile the shader on Android: http://anglebug.com/3839
11383     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11384 
11385     // http://anglebug.com/3837
11386     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11387 
11388     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
11389     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11390 
11391     // Fails on windows AMD on GL: http://anglebug.com/3838
11392     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11393 
11394     // Fails on D3D due to mistranslation: http://anglebug.com/3841
11395     ANGLE_SKIP_TEST_IF(IsD3D11());
11396 
11397     constexpr char kFS[] = R"(#version 300 es
11398 precision highp float;
11399 out vec4 outColor;
11400 
11401 layout(std140, column_major) uniform Ubo
11402 {
11403     mat4 m1;
11404     layout(row_major) mat4 m2;
11405 } ubo[3];
11406 
11407 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11408 
11409 #define VERIFY_IN(result, mat, cols, rows)                  \
11410     for (int c = 0; c < cols; ++c)                          \
11411     {                                                       \
11412         for (int r = 0; r < rows; ++r)                      \
11413         {                                                   \
11414             EXPECT(result, mat[c][r], float(c * 4 + r));    \
11415         }                                                   \
11416     }
11417 
11418 void main()
11419 {
11420     bool result = true;
11421 
11422     VERIFY_IN(result, ubo[0].m1, 4, 4);
11423     VERIFY_IN(result, ubo[0].m2, 4, 4);
11424 
11425     VERIFY_IN(result, ubo[1].m1, 4, 4);
11426     VERIFY_IN(result, ubo[1].m2, 4, 4);
11427 
11428     VERIFY_IN(result, ubo[2].m1, 4, 4);
11429     VERIFY_IN(result, ubo[2].m2, 4, 4);
11430 
11431     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11432 })";
11433 
11434     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11435     EXPECT_GL_NO_ERROR();
11436 
11437     constexpr size_t kMatrixCount                                     = 2;
11438     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11439         {4, 4},
11440         {4, 4},
11441     };
11442     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11443         true,
11444         false,
11445     };
11446 
11447     float data[kMatrixCount * 4 * 4] = {};
11448 
11449     const uint32_t size =
11450         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11451 
11452     GLBuffer ubos[3];
11453 
11454     InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
11455     InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
11456     InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
11457 
11458     EXPECT_GL_NO_ERROR();
11459 
11460     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11461     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11462 }
11463 
11464 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)11465 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
11466 {
11467     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
11468     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11469 
11470     // Fails on D3D due to mistranslation: http://anglebug.com/3841
11471     ANGLE_SKIP_TEST_IF(IsD3D11());
11472 
11473     constexpr char kFS[] = R"(#version 300 es
11474 precision highp float;
11475 out vec4 outColor;
11476 
11477 struct S
11478 {
11479     mat2x3 m2[3];
11480 };
11481 
11482 layout(std140, column_major) uniform Ubo
11483 {
11484     mat4 m1;
11485     layout(row_major) S s[2];
11486 } ubo;
11487 
11488 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11489 
11490 #define VERIFY_IN(result, mat, cols, rows)                  \
11491     for (int c = 0; c < cols; ++c)                          \
11492     {                                                       \
11493         for (int r = 0; r < rows; ++r)                      \
11494         {                                                   \
11495             EXPECT(result, mat[c][r], float(c * 4 + r));    \
11496         }                                                   \
11497     }
11498 
11499 bool verify2x3(mat2x3 mat)
11500 {
11501     bool result = true;
11502 
11503     for (int c = 0; c < 2; ++c)
11504     {
11505         for (int r = 0; r < 3; ++r)
11506         {
11507             EXPECT(result, mat[c][r], float(c * 4 + r));
11508         }
11509     }
11510 
11511     return result;
11512 }
11513 
11514 void main()
11515 {
11516     bool result = true;
11517 
11518     int sideEffect = 0;
11519     VERIFY_IN(result, ubo.m1, 4, 4);
11520     EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
11521     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
11522     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
11523 
11524     EXPECT(result, sideEffect, 2);
11525 
11526     EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
11527     EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
11528     EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
11529 
11530     EXPECT(result, sideEffect, 4);
11531 
11532     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11533 })";
11534 
11535     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11536     EXPECT_GL_NO_ERROR();
11537 
11538     constexpr size_t kMatrixCount                                     = 7;
11539     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11540         {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
11541     };
11542     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11543         true, false, false, false, false, false, false,
11544     };
11545 
11546     float data[kMatrixCount * 4 * 4] = {};
11547 
11548     const uint32_t size =
11549         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11550 
11551     GLBuffer ubo;
11552     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11553 
11554     EXPECT_GL_NO_ERROR();
11555 
11556     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11557     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11558 }
11559 
11560 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)11561 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
11562 {
11563     // http://anglebug.com/3837
11564     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11565 
11566     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11567     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
11568     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11569 
11570     constexpr char kFS[] = R"(#version 300 es
11571 precision highp float;
11572 out vec4 outColor;
11573 
11574 layout(std140, column_major) uniform Ubo
11575 {
11576     mat4 m1;
11577     layout(row_major) mat4 m2[2];
11578 } ubo;
11579 
11580 void main()
11581 {
11582     bool result = true;
11583 
11584     int x = 0;
11585     if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
11586     {
11587         result = true;
11588     }
11589     else
11590     {
11591         result = false;
11592     }
11593 
11594     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11595 })";
11596 
11597     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11598     EXPECT_GL_NO_ERROR();
11599 
11600     constexpr size_t kMatrixCount                                     = 3;
11601     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11602         {4, 4},
11603         {4, 4},
11604         {4, 4},
11605     };
11606     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11607 
11608     float data[kMatrixCount * 4 * 4] = {};
11609 
11610     const uint32_t size =
11611         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11612 
11613     GLBuffer ubo;
11614     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11615 
11616     EXPECT_GL_NO_ERROR();
11617 
11618     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11619     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11620 }
11621 
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)11622 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
11623 {
11624     // http://anglebug.com/3837
11625     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11626 
11627     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11628     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
11629     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11630 
11631     constexpr char kFS[] = R"(#version 300 es
11632 precision highp float;
11633 out vec4 outColor;
11634 
11635 layout(std140, column_major) uniform Ubo
11636 {
11637     mat4 m1;
11638     layout(row_major) mat4 m2[2];
11639 } ubo;
11640 
11641 void main()
11642 {
11643     bool result = false;
11644 
11645     for(int x = 0; x < 1; ++x)
11646     {
11647         if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
11648           result = true;
11649         }
11650     }
11651     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11652 })";
11653 
11654     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11655     EXPECT_GL_NO_ERROR();
11656 
11657     constexpr size_t kMatrixCount                                     = 3;
11658     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11659         {4, 4},
11660         {4, 4},
11661         {4, 4},
11662     };
11663     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11664 
11665     float data[kMatrixCount * 4 * 4] = {};
11666 
11667     const uint32_t size =
11668         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11669 
11670     GLBuffer ubo;
11671     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11672 
11673     EXPECT_GL_NO_ERROR();
11674 
11675     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11676     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11677 }
11678 
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)11679 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
11680 {
11681     // http://anglebug.com/3837
11682     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11683 
11684     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11685     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
11686     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11687 
11688     constexpr char kFS[] = R"(#version 300 es
11689 precision highp float;
11690 out vec4 outColor;
11691 
11692 layout(std140, column_major) uniform Ubo
11693 {
11694     mat4 m1;
11695     layout(row_major) mat4 m2[2];
11696 } ubo;
11697 
11698 void main()
11699 {
11700     bool result = false;
11701 
11702     for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
11703     {
11704         result = true;
11705     }
11706     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11707 })";
11708 
11709     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11710     EXPECT_GL_NO_ERROR();
11711 
11712     constexpr size_t kMatrixCount                                     = 3;
11713     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11714         {4, 4},
11715         {4, 4},
11716         {4, 4},
11717     };
11718     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11719 
11720     float data[kMatrixCount * 4 * 4] = {};
11721 
11722     const uint32_t size =
11723         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11724 
11725     GLBuffer ubo;
11726     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11727 
11728     EXPECT_GL_NO_ERROR();
11729 
11730     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11731     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11732 }
11733 
11734 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)11735 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
11736 {
11737     // Fails on Android: http://anglebug.com/3839
11738     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11739 
11740     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11741     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
11742     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11743 
11744     constexpr char kFS[] = R"(#version 300 es
11745 precision highp float;
11746 out vec4 outColor;
11747 
11748 layout(std140, column_major) uniform Ubo
11749 {
11750     mat4 m1;
11751     layout(row_major) mat4 m2[2];
11752 } ubo;
11753 
11754 void main()
11755 {
11756     bool result = true;
11757 
11758     int x = 0;
11759     if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
11760     {
11761         // First x == 1 should prevent the side effect of the second expression (x = 1) from
11762         // being executed.  If x = 1 is run before the if, the condition of the if would be true,
11763         // which is a failure.
11764         result = false;
11765     }
11766     if (x == 1)
11767     {
11768         result = false;
11769     }
11770 
11771     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11772 })";
11773 
11774     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11775     EXPECT_GL_NO_ERROR();
11776 
11777     constexpr size_t kMatrixCount                                     = 3;
11778     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11779         {4, 4},
11780         {4, 4},
11781         {4, 4},
11782     };
11783     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11784 
11785     float data[kMatrixCount * 4 * 4] = {};
11786 
11787     const uint32_t size =
11788         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11789 
11790     GLBuffer ubo;
11791     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11792 
11793     EXPECT_GL_NO_ERROR();
11794 
11795     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11796     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11797 }
11798 
11799 // Test that dynamic indexing of swizzled l-values should work.
11800 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)11801 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
11802 {
11803     // The shader first assigns v.x to v.z (1.0)
11804     // Then v.y to v.y (2.0)
11805     // Then v.z to v.x (1.0)
11806     constexpr char kFS[] = R"(#version 300 es
11807 precision highp float;
11808 out vec4 my_FragColor;
11809 void main() {
11810     vec3 v = vec3(1.0, 2.0, 3.0);
11811     for (int i = 0; i < 3; i++) {
11812         v.zyx[i] = v[i];
11813     }
11814     my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11815 })";
11816 
11817     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11818     EXPECT_GL_NO_ERROR();
11819     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11820     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11821 }
11822 
11823 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)11824 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
11825 {
11826     constexpr char kFS[] = R"(#version 300 es
11827 precision mediump float;
11828 out vec4 color;
11829 
11830 vec4 f(vec4 c)
11831 {
11832     return c;
11833     // dead code
11834     c = vec4(0, 0, 1, 1);
11835     return c;
11836 }
11837 
11838 void main()
11839 {
11840     vec4 result = vec4(0, 0.5, 0, 1);
11841     int var = int(result.y * 2.2);
11842 
11843     {
11844         if (result.x > 1.0)
11845         {
11846             discard;
11847             // dead code
11848             result = vec4(1, 0, 0, 1);
11849         }
11850         for (int i = 0; i < 3; ++i)
11851         {
11852             if (i < 2)
11853             {
11854                 result = f(result);
11855                 continue;
11856                 // dead code
11857                 result = vec4(1, 0, 1, 1);
11858             }
11859             result = f(result);
11860             break;
11861             // dead code
11862             result = vec4(1, 0, 1, 0);
11863         }
11864         while (true)
11865         {
11866             if (result.x > -1.0)
11867             {
11868                 {
11869                     result = f(result);
11870                     {
11871                         break;
11872                         // dead code
11873                         result = vec4(1, 0, 0, 0);
11874                     }
11875                     // dead code
11876                     for (int j = 0; j < 3; ++j)
11877                     {
11878                         if (j > 1) continue;
11879                         result = vec4(0, 0, 1, 0);
11880                         color = vec4(0.5, 0, 0.5, 0.5);
11881                         return;
11882                     }
11883                 }
11884                 // dead code
11885                 result = vec4(0.5, 0, 0, 0);
11886             }
11887         }
11888         switch (var)
11889         {
11890         case 2:
11891             return;
11892             // dead code
11893             color = vec4(0.25, 0, 0.25, 0.25);
11894         case 1:
11895             {
11896                 // Make sure this path is not pruned due to the return in the previous case.
11897                 result.y += 0.5;
11898                 break;
11899                 // dead code
11900                 color = vec4(0.25, 0, 0, 0);
11901             }
11902             // dead code
11903             color = vec4(0, 0, 0.25, 0);
11904             break;
11905         default:
11906             break;
11907         }
11908 
11909         color = result;
11910         return;
11911         // dead code
11912         color = vec4(0, 0, 0.5, 0);
11913     }
11914     // dead code
11915     color = vec4(0, 0, 0, 0.5);
11916 })";
11917 
11918     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11919 
11920     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11921     EXPECT_GL_NO_ERROR();
11922 
11923     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11924 }
11925 
11926 // Regression test based on fuzzer issue.  If a case has statements that are pruned, and those
11927 // pruned statements in turn have branches, and another case follows, a prior implementation of
11928 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)11929 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
11930 {
11931     constexpr char kFS[] = R"(#version 300 es
11932 precision mediump float;
11933 out vec4 color;
11934 void main()
11935 {
11936     color = vec4(0, 1, 0, 1);
11937     switch(0)
11938     {
11939     case 0:
11940         break;
11941         break;
11942         color = vec4(1, 0, 0, 1);   // The bug was pruning this statement twice
11943     default:
11944         color = vec4(0, 0, 1, 1);
11945         break;
11946     }
11947 })";
11948 
11949     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11950 
11951     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11952     EXPECT_GL_NO_ERROR();
11953 
11954     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11955 }
11956 
11957 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
11958 // make sure they are all linked ok.  The front-end sorts these resources and traverses the list of
11959 // "uniforms" to find the range for each resource.  A bug there was causing some resource ranges to
11960 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)11961 TEST_P(GLSLTest_ES31, MixOfAllResources)
11962 {
11963     // http://anglebug.com/5072
11964     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
11965 
11966     constexpr char kComputeShader[] = R"(#version 310 es
11967 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
11968 layout(binding = 1, std430) buffer Output {
11969   uint ubo_value;
11970   uint default_value;
11971   uint sampler_value;
11972   uint ac_value;
11973   uint image_value;
11974 } outbuf;
11975 uniform Input {
11976   uint input_value;
11977 } inbuf;
11978 uniform uint default_uniform;
11979 uniform sampler2D smplr;
11980 layout(binding=0) uniform atomic_uint ac;
11981 layout(r32ui) uniform highp readonly uimage2D image;
11982 
11983 void main(void)
11984 {
11985   outbuf.ubo_value = inbuf.input_value;
11986   outbuf.default_value = default_uniform;
11987   outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
11988   outbuf.ac_value = atomicCounterIncrement(ac);
11989   outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
11990 }
11991 )";
11992     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
11993     EXPECT_GL_NO_ERROR();
11994 
11995     glUseProgram(program);
11996 
11997     unsigned int inputData = 89u;
11998     GLBuffer inputBuffer;
11999     glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
12000     glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
12001     GLuint inputBufferIndex = glGetUniformBlockIndex(program, "Input");
12002     ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
12003     glUniformBlockBinding(program, inputBufferIndex, 0);
12004     glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
12005 
12006     unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
12007                                       0x13579BDFu};
12008     GLBuffer outputBuffer;
12009     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12010     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
12011     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12012     EXPECT_GL_NO_ERROR();
12013 
12014     unsigned int uniformData = 456u;
12015     GLint uniformLocation    = glGetUniformLocation(program, "default_uniform");
12016     ASSERT_NE(uniformLocation, -1);
12017     glUniform1ui(uniformLocation, uniformData);
12018 
12019     unsigned int acData = 2u;
12020     GLBuffer atomicCounterBuffer;
12021     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12022     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12023     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12024     EXPECT_GL_NO_ERROR();
12025 
12026     unsigned int imageData = 33u;
12027     GLTexture image;
12028     glBindTexture(GL_TEXTURE_2D, image);
12029     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
12030     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
12031     glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
12032     EXPECT_GL_NO_ERROR();
12033 
12034     GLColor textureData(127, 18, 189, 211);
12035     GLTexture texture;
12036     glBindTexture(GL_TEXTURE_2D, texture);
12037     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
12038     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12039     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12040     ASSERT_GL_NO_ERROR();
12041 
12042     glDispatchCompute(1, 1, 1);
12043     EXPECT_GL_NO_ERROR();
12044 
12045     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12046 
12047     // read back
12048     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12049         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12050     EXPECT_EQ(ptr[0], inputData);
12051     EXPECT_EQ(ptr[1], uniformData);
12052     EXPECT_NEAR(ptr[2], textureData.R, 1.0);
12053     EXPECT_EQ(ptr[3], acData);
12054     EXPECT_EQ(ptr[4], imageData);
12055 
12056     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12057 }
12058 
12059 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)12060 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
12061 {
12062     // http://anglebug.com/5546
12063     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12064 
12065     // anglebug.com/3832 - no sampler array params on Android
12066     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12067 
12068     constexpr char kComputeShader[] = R"(#version 310 es
12069 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12070 
12071 layout(binding = 1, std430) buffer Output {
12072   uint success;
12073 } outbuf;
12074 
12075 uniform uint initialAcValue;
12076 uniform sampler2D smplr[2][3];
12077 layout(binding=0) uniform atomic_uint ac;
12078 
12079 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12080 {
12081     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12082                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12083                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12084     uint aResult = atomicCounterIncrement(a);
12085 
12086     return sExpect == sResult && aExpect == aResult;
12087 }
12088 
12089 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12090 {
12091     bool success = true;
12092     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
12093     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
12094     return success;
12095 }
12096 
12097 void main(void)
12098 {
12099     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
12100 }
12101 )";
12102     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12103     EXPECT_GL_NO_ERROR();
12104 
12105     glUseProgram(program);
12106 
12107     unsigned int outputInitData = 0x12345678u;
12108     GLBuffer outputBuffer;
12109     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12110     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12111     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12112     EXPECT_GL_NO_ERROR();
12113 
12114     unsigned int acData   = 2u;
12115     GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
12116     ASSERT_NE(uniformLocation, -1);
12117     glUniform1ui(uniformLocation, acData);
12118 
12119     GLBuffer atomicCounterBuffer;
12120     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12121     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12122     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12123     EXPECT_GL_NO_ERROR();
12124 
12125     const std::array<GLColor, 6> kTextureData = {
12126         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12127         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
12128     };
12129     GLTexture textures[2][3];
12130 
12131     for (int dim1 = 0; dim1 < 2; ++dim1)
12132     {
12133         for (int dim2 = 0; dim2 < 3; ++dim2)
12134         {
12135             int textureUnit = dim1 * 3 + dim2;
12136             glActiveTexture(GL_TEXTURE0 + textureUnit);
12137             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12138             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12139                          &kTextureData[textureUnit]);
12140             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12141             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12142 
12143             std::stringstream uniformName;
12144             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12145             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12146             EXPECT_NE(samplerLocation, -1);
12147             glUniform1i(samplerLocation, textureUnit);
12148         }
12149     }
12150     ASSERT_GL_NO_ERROR();
12151 
12152     glDispatchCompute(1, 1, 1);
12153     EXPECT_GL_NO_ERROR();
12154 
12155     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12156 
12157     // read back
12158     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12159         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12160     EXPECT_EQ(ptr[0], 1u);
12161 
12162     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12163 }
12164 
12165 // Test that array of array of samplers used as function parameter with an index that has a
12166 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)12167 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
12168 {
12169     // http://anglebug.com/5546
12170     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12171 
12172     // anglebug.com/3832 - no sampler array params on Android
12173     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12174 
12175     // Skip if EXT_gpu_shader5 is not enabled.
12176     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12177 
12178     constexpr char kComputeShader[] = R"(#version 310 es
12179 #extension GL_EXT_gpu_shader5 : require
12180 
12181 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12182 
12183 layout(binding = 1, std430) buffer Output {
12184   uint success;
12185 } outbuf;
12186 
12187 uniform sampler2D smplr[2][3];
12188 layout(binding=0) uniform atomic_uint ac;
12189 
12190 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12191 {
12192     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12193                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12194                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12195     uint aResult = atomicCounter(a);
12196 
12197     return sExpect == sResult && aExpect == aResult;
12198 }
12199 
12200 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12201 {
12202     bool success = true;
12203     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
12204                     s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
12205     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
12206                     s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
12207     return success;
12208 }
12209 
12210 void main(void)
12211 {
12212     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
12213 }
12214 )";
12215     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12216     EXPECT_GL_NO_ERROR();
12217 
12218     glUseProgram(program);
12219 
12220     unsigned int outputInitData = 0x12345678u;
12221     GLBuffer outputBuffer;
12222     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12223     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12224     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12225     EXPECT_GL_NO_ERROR();
12226 
12227     unsigned int acData = 0u;
12228     GLBuffer atomicCounterBuffer;
12229     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12230     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12231     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12232     EXPECT_GL_NO_ERROR();
12233 
12234     const std::array<GLColor, 6> kTextureData = {
12235         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12236         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
12237     };
12238     GLTexture textures[2][3];
12239 
12240     for (int dim1 = 0; dim1 < 2; ++dim1)
12241     {
12242         for (int dim2 = 0; dim2 < 3; ++dim2)
12243         {
12244             int textureUnit = dim1 * 3 + dim2;
12245             glActiveTexture(GL_TEXTURE0 + textureUnit);
12246             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12247             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12248                          &kTextureData[textureUnit]);
12249             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12250             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12251 
12252             std::stringstream uniformName;
12253             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12254             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12255             EXPECT_NE(samplerLocation, -1);
12256             glUniform1i(samplerLocation, textureUnit);
12257         }
12258     }
12259     ASSERT_GL_NO_ERROR();
12260 
12261     glDispatchCompute(1, 1, 1);
12262     EXPECT_GL_NO_ERROR();
12263 
12264     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12265 
12266     // read back
12267     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12268         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12269     EXPECT_EQ(ptr[0], 1u);
12270 
12271     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12272 }
12273 
testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)12274 void GLSLTest_ES31::testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)
12275 {
12276     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
12277 
12278     int maxTextureImageUnits = 0;
12279     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12280     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12281 
12282     // anglebug.com/3832 - no sampler array params on Android
12283     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12284 
12285     // http://anglebug.com/5546
12286     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12287 
12288     std::string computeShader;
12289     constexpr char kGLSLVersion[]  = R"(#version 310 es
12290 )";
12291     constexpr char kGPUShaderEXT[] = R"(#extension GL_EXT_gpu_shader5 : require
12292 )";
12293     constexpr char kGPUShaderOES[] = R"(#extension GL_OES_gpu_shader5 : require
12294 )";
12295 
12296     computeShader.append(kGLSLVersion);
12297     if (usedExtension == APIExtensionVersion::EXT)
12298     {
12299         computeShader.append(kGPUShaderEXT);
12300     }
12301     else
12302     {
12303         computeShader.append(kGPUShaderOES);
12304     }
12305 
12306     constexpr char kComputeShaderBody[] = R"(
12307 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12308 
12309 layout(binding = 1, std430) buffer Output {
12310 uint success;
12311 } outbuf;
12312 
12313 uniform sampler2D smplr[2][3][4];
12314 layout(binding=0) uniform atomic_uint ac;
12315 
12316 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
12317 {
12318 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12319                       uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12320                       uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
12321                       uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
12322 uint aResult = atomicCounter(a);
12323 
12324 return sExpect == sResult && aExpect == aResult;
12325 }
12326 
12327 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
12328 {
12329 bool success = true;
12330 // [0][0]
12331 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
12332                 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
12333 // [1][0]
12334 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
12335                 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
12336 // [0][1]
12337 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
12338                 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
12339 // [0][2]
12340 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
12341                 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
12342 // [1][1]
12343 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
12344                 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
12345 // [1][2]
12346 uint acValue = atomicCounterIncrement(ac);  // Returns 5
12347 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
12348                 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
12349 
12350 return success;
12351 }
12352 
12353 void main(void)
12354 {
12355 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
12356 }
12357 )";
12358     computeShader.append(kComputeShaderBody);
12359 
12360     ANGLE_GL_COMPUTE_PROGRAM(program, computeShader.c_str());
12361     EXPECT_GL_NO_ERROR();
12362 
12363     glUseProgram(program);
12364 
12365     unsigned int outputInitData = 0x12345678u;
12366     GLBuffer outputBuffer;
12367     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12368     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12369     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12370     EXPECT_GL_NO_ERROR();
12371 
12372     unsigned int acData = 0u;
12373     GLBuffer atomicCounterBuffer;
12374     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12375     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12376     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12377     EXPECT_GL_NO_ERROR();
12378 
12379     const std::array<GLColor, 24> kTextureData = {
12380         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
12381         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
12382         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
12383         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
12384         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
12385         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
12386     };
12387     GLTexture textures[2][3][4];
12388 
12389     for (int dim1 = 0; dim1 < 2; ++dim1)
12390     {
12391         for (int dim2 = 0; dim2 < 3; ++dim2)
12392         {
12393             for (int dim3 = 0; dim3 < 4; ++dim3)
12394             {
12395                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
12396                 glActiveTexture(GL_TEXTURE0 + textureUnit);
12397                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
12398                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12399                              &kTextureData[textureUnit]);
12400                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12401                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12402 
12403                 std::stringstream uniformName;
12404                 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
12405                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12406                 EXPECT_NE(samplerLocation, -1);
12407                 glUniform1i(samplerLocation, textureUnit);
12408             }
12409         }
12410     }
12411     ASSERT_GL_NO_ERROR();
12412 
12413     glDispatchCompute(1, 1, 1);
12414     EXPECT_GL_NO_ERROR();
12415 
12416     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12417 
12418     // read back
12419     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12420         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12421     EXPECT_EQ(ptr[0], 1u);
12422 
12423     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12424 }
12425 
12426 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexEXT)12427 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexEXT)
12428 {
12429     // Skip if EXT_gpu_shader5 is not enabled.
12430     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12431     testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::EXT);
12432 }
12433 
12434 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexOES)12435 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexOES)
12436 {
12437     // Skip if OES_gpu_shader5 is not enabled.
12438     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_gpu_shader5"));
12439     testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::OES);
12440 }
12441 
12442 // Test that array of array of samplers can be indexed correctly with dynamic indices.  Uses
12443 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)12444 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
12445 {
12446     // Skip if EXT_gpu_shader5 is not enabled.
12447     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12448 
12449     int maxTextureImageUnits = 0;
12450     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12451     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12452 
12453     // http://anglebug.com/5072
12454     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
12455 
12456     // anglebug.com/3832 - no sampler array params on Android
12457     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12458 
12459     // http://anglebug.com/5546
12460     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12461 
12462     constexpr char kComputeShader[] = R"(#version 310 es
12463 #extension GL_EXT_gpu_shader5 : require
12464 
12465 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12466 
12467 layout(binding = 1, std430) buffer Output {
12468   uint success;
12469 } outbuf;
12470 
12471 struct I
12472 {
12473     uint index;
12474 };
12475 
12476 struct S
12477 {
12478     sampler2D smplr[4];
12479     I nested;
12480 };
12481 
12482 struct T
12483 {
12484     S nested[3];
12485     uint tIndex;
12486 };
12487 
12488 uniform T u[2];
12489 
12490 uint getValue(in sampler2D s)
12491 {
12492     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
12493 }
12494 
12495 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
12496 {
12497     uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
12498                           getValue(s[2]), getValue(s[3]));
12499 
12500     return sExpect == sResult;
12501 }
12502 
12503 bool samplerTest(T t, uint N)
12504 {
12505     // u[N].tIndex == 0 + N*4
12506     // u[N].nested[0].nested.index == 1 + N*4
12507     // u[N].nested[1].nested.index == 2 + N*4
12508     // u[N].nested[2].nested.index == 3 + N*4
12509 
12510     uvec4 colorOffset = N * 3u * 4u * uvec4(8);
12511 
12512     bool success = true;
12513     // [N][0]
12514     success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
12515                     t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
12516     // [N][1]
12517     success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
12518                     t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
12519     // [N][2]
12520     success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
12521                     t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
12522 
12523     return success;
12524 }
12525 
12526 bool uniformTest(T t, uint N)
12527 {
12528     // Also verify that expressions that involve structs-with-samplers are correct when not
12529     // referecing the sampler.
12530 
12531     bool success = true;
12532     success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
12533     success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
12534     success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
12535 
12536     success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
12537                 && success;
12538     success = (t.nested[t.nested[0].nested.index - t.tIndex     ].nested.index - t.tIndex == 2u)
12539                 && success;
12540     success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
12541                 && success;
12542 
12543     success = (t.nested[
12544                           t.nested[
12545                                      t.nested[2].nested.index - t.tIndex - 1u  // 2
12546                                   ].nested.index - t.tIndex - 2u               // 1
12547                        ].nested.index - t.tIndex                               // 2
12548                 == 2u) && success;
12549 
12550     return success;
12551 }
12552 
12553 void main(void)
12554 {
12555     bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
12556                     && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
12557     outbuf.success = uint(success);
12558 }
12559 )";
12560     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12561     EXPECT_GL_NO_ERROR();
12562 
12563     glUseProgram(program);
12564 
12565     unsigned int outputInitData = 0x12345678u;
12566     GLBuffer outputBuffer;
12567     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12568     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12569     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12570     EXPECT_GL_NO_ERROR();
12571 
12572     const std::array<GLColor, 24> kTextureData = {
12573         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
12574         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
12575         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
12576         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
12577         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
12578         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
12579     };
12580     GLTexture textures[2][3][4];
12581 
12582     for (int dim1 = 0; dim1 < 2; ++dim1)
12583     {
12584         for (int dim2 = 0; dim2 < 3; ++dim2)
12585         {
12586             for (int dim3 = 0; dim3 < 4; ++dim3)
12587             {
12588                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
12589                 glActiveTexture(GL_TEXTURE0 + textureUnit);
12590                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
12591                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12592                              &kTextureData[textureUnit]);
12593                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12594                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12595 
12596                 std::stringstream uniformName;
12597                 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
12598                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12599                 EXPECT_NE(samplerLocation, -1);
12600                 glUniform1i(samplerLocation, textureUnit);
12601             }
12602 
12603             std::stringstream uniformName;
12604             uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
12605             GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
12606             EXPECT_NE(nestedIndexLocation, -1);
12607             glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
12608         }
12609 
12610         std::stringstream uniformName;
12611         uniformName << "u[" << dim1 << "].tIndex";
12612         GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
12613         EXPECT_NE(indexLocation, -1);
12614         glUniform1ui(indexLocation, dim1 * 4);
12615     }
12616     ASSERT_GL_NO_ERROR();
12617 
12618     glDispatchCompute(1, 1, 1);
12619     EXPECT_GL_NO_ERROR();
12620 
12621     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12622 
12623     // read back
12624     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12625         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12626     EXPECT_EQ(ptr[0], 1u);
12627 
12628     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12629 }
12630 
12631 // Test that array of array of samplers work when indexed with an expression that's derived from an
12632 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)12633 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
12634 {
12635     // Skip if EXT_gpu_shader5 is not enabled.
12636     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12637 
12638     // anglebug.com/3832 - no sampler array params on Android
12639     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12640 
12641     constexpr char kComputeShader[] = R"(#version 310 es
12642 #extension GL_EXT_gpu_shader5 : require
12643 
12644 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12645 
12646 layout(binding = 1, std430) buffer Output {
12647   uint success;
12648 } outbuf;
12649 
12650 uniform sampler2D smplr[2][3];
12651 
12652 uint getValue(in sampler2D s)
12653 {
12654     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
12655 }
12656 
12657 bool runTest(in sampler2D s[2][3])
12658 {
12659     // s[0][0] should contain 2
12660     // s[0][1] should contain 0
12661     // s[0][2] should contain 1
12662     // s[1][0] should contain 1
12663     // s[1][1] should contain 2
12664     // s[1][2] should contain 0
12665 
12666     uint result = getValue(
12667                        s[
12668                            getValue(
12669                                 s[
12670                                     getValue(s[0][1])   // 0
12671                                 ][
12672                                     getValue(s[0][0])   // 2
12673                                 ]
12674                            )                      // s[0][2] -> 1
12675                        ][
12676                            getValue(
12677                                 s[
12678                                     getValue(s[1][0])   // 1
12679                                 ][
12680                                     getValue(s[1][1])   // 2
12681                                 ]
12682                            )                      // s[1][2] -> 0
12683                        ]
12684                   );                      // s[1][0] -> 1
12685 
12686     return result == 1u;
12687 }
12688 
12689 void main(void)
12690 {
12691     outbuf.success = uint(runTest(smplr));
12692 }
12693 )";
12694     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12695     EXPECT_GL_NO_ERROR();
12696 
12697     glUseProgram(program);
12698 
12699     unsigned int outputInitData = 0x12345678u;
12700     GLBuffer outputBuffer;
12701     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12702     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12703     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12704     EXPECT_GL_NO_ERROR();
12705 
12706     const std::array<GLColor, 6> kTextureData = {
12707         GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
12708         GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
12709     };
12710     GLTexture textures[2][3];
12711 
12712     for (int dim1 = 0; dim1 < 2; ++dim1)
12713     {
12714         for (int dim2 = 0; dim2 < 3; ++dim2)
12715         {
12716             int textureUnit = dim1 * 3 + dim2;
12717             glActiveTexture(GL_TEXTURE0 + textureUnit);
12718             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12719             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12720                          &kTextureData[textureUnit]);
12721             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12722             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12723 
12724             std::stringstream uniformName;
12725             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12726             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12727             EXPECT_NE(samplerLocation, -1);
12728             glUniform1i(samplerLocation, textureUnit);
12729         }
12730     }
12731     ASSERT_GL_NO_ERROR();
12732 
12733     glDispatchCompute(1, 1, 1);
12734     EXPECT_GL_NO_ERROR();
12735 
12736     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12737 
12738     // read back
12739     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12740         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12741     EXPECT_EQ(ptr[0], 1u);
12742 
12743     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12744 }
12745 
12746 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)12747 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
12748 {
12749     // http://anglebug.com/3831
12750     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
12751 
12752     // Fails on windows AMD on GL: http://anglebug.com/3838
12753     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
12754     // http://anglebug.com/5384
12755     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
12756 
12757     // Fails on D3D due to mistranslation: http://anglebug.com/3841
12758     ANGLE_SKIP_TEST_IF(IsD3D11());
12759 
12760     constexpr char kCS[] = R"(#version 310 es
12761 precision highp float;
12762 layout(local_size_x=1) in;
12763 
12764 layout(std140, column_major) uniform Ubo
12765 {
12766     mat4 m1;
12767     layout(row_major) mat4 m2;
12768 } ubo;
12769 
12770 layout(std140, row_major, binding = 0) buffer Ssbo
12771 {
12772     layout(column_major) mat4 m1;
12773     mat4 m2;
12774 } ssbo;
12775 
12776 layout(std140, binding = 1) buffer Result
12777 {
12778     uint success;
12779 } resultOut;
12780 
12781 void main()
12782 {
12783     bool result = true;
12784 
12785     // Only assign to SSBO from a single invocation.
12786     if (gl_GlobalInvocationID.x == 0u)
12787     {
12788         if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
12789         {
12790             result = false;
12791         }
12792 
12793         resultOut.success = uint(result);
12794     }
12795 })";
12796 
12797     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
12798     EXPECT_GL_NO_ERROR();
12799 
12800     constexpr size_t kMatrixCount                                     = 2;
12801     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12802         {4, 4},
12803         {4, 4},
12804     };
12805     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12806         true,
12807         false,
12808     };
12809 
12810     float data[kMatrixCount * 4 * 4]  = {};
12811     float zeros[kMatrixCount * 4 * 4] = {};
12812 
12813     const uint32_t size =
12814         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12815 
12816     GLBuffer ubo, ssbo;
12817 
12818     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12819     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
12820     EXPECT_GL_NO_ERROR();
12821 
12822     GLBuffer outputBuffer;
12823     CreateOutputBuffer(&outputBuffer, 1);
12824 
12825     glUseProgram(program);
12826     glDispatchCompute(1, 1, 1);
12827     EXPECT_GL_NO_ERROR();
12828     EXPECT_TRUE(VerifySuccess(outputBuffer));
12829 
12830     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
12831 }
12832 
12833 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)12834 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
12835 {
12836     // Fails on windows AMD on GL: http://anglebug.com/3838
12837     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
12838     // http://anglebug.com/5384
12839     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
12840 
12841     // Fails on D3D due to mistranslation: http://anglebug.com/3841
12842     ANGLE_SKIP_TEST_IF(IsD3D11());
12843 
12844     // Fails compiling shader on Android/Vulkan.  http://anglebug.com/4290
12845     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
12846 
12847     // Fails on ARM on Vulkan.  http://anglebug.com/4492
12848     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
12849 
12850     constexpr char kCS[] = R"(#version 310 es
12851 precision highp float;
12852 layout(local_size_x=1) in;
12853 
12854 layout(std140, column_major) uniform Ubo
12855 {
12856     mat4 m1;
12857     layout(row_major) mat4 m2[2][3];
12858 } ubo;
12859 
12860 layout(std140, row_major, binding = 0) buffer Ssbo
12861 {
12862     layout(column_major) mat4 m1;
12863     mat4 m2[2][3];
12864 } ssbo;
12865 
12866 layout(std140, binding = 1) buffer Result
12867 {
12868     uint success;
12869 } resultOut;
12870 
12871 void main()
12872 {
12873     bool result = true;
12874 
12875     // Only assign to SSBO from a single invocation.
12876     if (gl_GlobalInvocationID.x == 0u)
12877     {
12878         ssbo.m1 = ubo.m1;
12879         ssbo.m2 = ubo.m2;
12880 
12881         resultOut.success = uint(result);
12882     }
12883 })";
12884 
12885     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
12886     EXPECT_GL_NO_ERROR();
12887 
12888     constexpr size_t kMatrixCount                                     = 7;
12889     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12890         {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
12891     };
12892     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12893         true, false, false, false, false, false, false,
12894     };
12895 
12896     float data[kMatrixCount * 4 * 4]  = {};
12897     float zeros[kMatrixCount * 4 * 4] = {};
12898 
12899     const uint32_t size =
12900         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12901 
12902     GLBuffer ubo, ssbo;
12903 
12904     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12905     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
12906     EXPECT_GL_NO_ERROR();
12907 
12908     GLBuffer outputBuffer;
12909     CreateOutputBuffer(&outputBuffer, 1);
12910 
12911     glUseProgram(program);
12912     glDispatchCompute(1, 1, 1);
12913     EXPECT_GL_NO_ERROR();
12914     EXPECT_TRUE(VerifySuccess(outputBuffer));
12915 
12916     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
12917 }
12918 
12919 // Verify that types used differently (in different block storages, differently qualified etc) work
12920 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)12921 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
12922 {
12923     constexpr char kCS[] = R"(#version 310 es
12924 precision highp float;
12925 layout(local_size_x=1) in;
12926 
12927 struct Inner
12928 {
12929     mat3x2 m;
12930     float f[3];
12931     uvec2 u[2][4];
12932     ivec3 i;
12933     mat2x3 m2[3][2];
12934 };
12935 
12936 struct Outer
12937 {
12938     Inner i[2];
12939 };
12940 
12941 layout(std140, column_major) uniform Ubo140c
12942 {
12943     mat2 m;
12944     layout(row_major) Outer o;
12945 } ubo140cIn;
12946 
12947 layout(std430, row_major, binding = 0) buffer Ubo430r
12948 {
12949     mat2 m;
12950     layout(column_major) Outer o;
12951 } ubo430rIn;
12952 
12953 layout(std140, column_major, binding = 1) buffer Ssbo140c
12954 {
12955     layout(row_major) mat2 m[2];
12956     Outer o;
12957     layout(row_major) Inner i;
12958 } ssbo140cOut;
12959 
12960 layout(std430, row_major, binding = 2) buffer Ssbo430r
12961 {
12962     layout(column_major) mat2 m[2];
12963     Outer o;
12964     layout(column_major) Inner i;
12965 } ssbo430rOut;
12966 
12967 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
12968 {
12969     ssbo140cOut.o.i[innerIndex].u = u;
12970 }
12971 
12972 void writeBlockArgToStd140(Inner i, int innerIndex)
12973 {
12974     ssbo140cOut.o.i[innerIndex] = i;
12975 }
12976 
12977 mat2x3[3][2] readFromStd140(int innerIndex)
12978 {
12979     return ubo140cIn.o.i[0].m2;
12980 }
12981 
12982 Inner readBlockFromStd430(int innerIndex)
12983 {
12984     return ubo430rIn.o.i[innerIndex];
12985 }
12986 
12987 void copyFromStd140(out Inner i)
12988 {
12989     i = ubo140cIn.o.i[1];
12990 }
12991 
12992 void main(){
12993     // Directly copy from one layout to another.
12994     ssbo140cOut.m[0] = ubo140cIn.m;
12995     ssbo140cOut.m[1] = ubo430rIn.m;
12996     ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
12997     ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
12998     ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
12999 
13000     // Read from block and pass to function.
13001     writeArgToStd140(ubo140cIn.o.i[0].u, 0);
13002     writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
13003 
13004     // Have function return value read from block.
13005     ssbo140cOut.o.i[0].m2 = readFromStd140(0);
13006 
13007     // Have function fill in value as out parameter.
13008     copyFromStd140(ssbo140cOut.i);
13009 
13010     // Initialize local variable.
13011     mat2 mStd140 = ubo140cIn.m;
13012 
13013     // Copy to variable, through multiple assignments.
13014     mat2 mStd430, temp;
13015     mStd430 = temp = ubo430rIn.m;
13016 
13017     // Copy from local variable
13018     ssbo430rOut.m[0] = mStd140;
13019     ssbo430rOut.m[1] = mStd430;
13020 
13021     // Construct from struct.
13022     Inner iStd140 = ubo140cIn.o.i[1];
13023     Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
13024 
13025     // Copy struct from local variable.
13026     ssbo430rOut.o = oStd140;
13027 
13028     // Construct from arrays
13029     Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
13030                           ubo430rIn.o.i[1].f,
13031                           ubo430rIn.o.i[1].u,
13032                           ubo430rIn.o.i[1].i,
13033                           ubo430rIn.o.i[1].m2);
13034     ssbo430rOut.i = iStd430;
13035 })";
13036 
13037     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13038     EXPECT_GL_NO_ERROR();
13039 
13040     // Test data, laid out with padding (0) based on std140/std430 rules.
13041     // clang-format off
13042     const std::vector<float> ubo140cData = {
13043         // m (mat2, column-major)
13044         1, 2, 0, 0,     3, 4, 0, 0,
13045 
13046         // o.i[0].m (mat3x2, row-major)
13047         5, 7, 9, 0,     6, 8, 10, 0,
13048         // o.i[0].f (float[3])
13049         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
13050         // o.i[0].u (uvec2[2][4])
13051         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
13052         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
13053         // o.i[0].i (ivec3)
13054         31, 32, 33, 0,
13055         // o.i[0].m2 (mat2x3[3][2], row-major)
13056         34, 37, 0, 0,   35, 38, 0, 0,   36, 39, 0, 0,
13057         40, 43, 0, 0,   41, 44, 0, 0,   42, 45, 0, 0,
13058         46, 49, 0, 0,   47, 50, 0, 0,   48, 51, 0, 0,
13059         52, 55, 0, 0,   53, 56, 0, 0,   54, 57, 0, 0,
13060         58, 61, 0, 0,   59, 62, 0, 0,   60, 63, 0, 0,
13061         64, 67, 0, 0,   65, 68, 0, 0,   66, 69, 0, 0,
13062 
13063         // o.i[1].m (mat3x2, row-major)
13064         70, 72, 74, 0,     71, 73, 75, 0,
13065         // o.i[1].f (float[3])
13066         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
13067         // o.i[1].u (uvec2[2][4])
13068         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
13069         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
13070         // o.i[1].i (ivec3)
13071         96, 97, 98, 0,
13072         // o.i[1].m2 (mat2x3[3][2], row-major)
13073          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
13074         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
13075         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
13076         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
13077         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
13078         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
13079     };
13080     const std::vector<float> ubo430rData = {
13081         // m (mat2, row-major)
13082         135, 137,         136, 138,
13083 
13084         // o.i[0].m (mat3x2, column-major)
13085         139, 140,         141, 142,         143, 144,
13086         // o.i[0].f (float[3])
13087         146, 147, 148, 0,
13088         // o.i[0].u (uvec2[2][4])
13089         149, 150,         151, 152,         153, 154,         155, 156,
13090         157, 158,         159, 160,         161, 162,         163, 164, 0, 0,
13091         // o.i[0].i (ivec3)
13092         165, 166, 167, 0,
13093         // o.i[0].m2 (mat2x3[3][2], column-major)
13094         168, 169, 170, 0,   171, 172, 173, 0,
13095         174, 175, 176, 0,   177, 178, 179, 0,
13096         180, 181, 182, 0,   183, 184, 185, 0,
13097         186, 187, 188, 0,   189, 190, 191, 0,
13098         192, 193, 194, 0,   195, 196, 197, 0,
13099         198, 199, 200, 0,   201, 202, 203, 0,
13100 
13101         // o.i[1].m (mat3x2, column-major)
13102         204, 205,         206, 207,         208, 209,
13103         // o.i[1].f (float[3])
13104         211, 212, 213, 0,
13105         // o.i[1].u (uvec2[2][4])
13106         214, 215,         216, 217,         218, 219,         220, 221,
13107         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
13108         // o.i[1].i (ivec3)
13109         230, 231, 232, 0,
13110         // o.i[1].m2 (mat2x3[3][2], column-major)
13111         233, 234, 235, 0,   236, 237, 238, 0,
13112         239, 240, 241, 0,   242, 243, 244, 0,
13113         245, 246, 247, 0,   248, 249, 250, 0,
13114         251, 252, 253, 0,   254, 255, 256, 0,
13115         257, 258, 259, 0,   260, 261, 262, 0,
13116         263, 264, 265, 0,   266, 267, 268, 0,
13117     };
13118     const std::vector<float> ssbo140cExpect = {
13119         // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13120         1, 3, 0, 0,     2, 4, 0, 0,
13121         135, 137, 0, 0, 136, 138, 0, 0,
13122 
13123         // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
13124         5, 6, 0, 0,     7, 8, 0, 0,     9, 10, 0, 0,
13125         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
13126         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
13127         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
13128         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
13129         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
13130         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
13131         31, 32, 33, 0,
13132         // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
13133         34, 35, 36, 0,  37, 38, 39, 0,
13134         40, 41, 42, 0,  43, 44, 45, 0,
13135         46, 47, 48, 0,  49, 50, 51, 0,
13136         52, 53, 54, 0,  55, 56, 57, 0,
13137         58, 59, 60, 0,  61, 62, 63, 0,
13138         64, 65, 66, 0,  67, 68, 69, 0,
13139 
13140         // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
13141         139, 140, 0, 0,   141, 142, 0, 0,   143, 144, 0, 0,
13142         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
13143         146, 0, 0, 0,     147, 0, 0, 0,     148, 0, 0, 0,
13144         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
13145         149, 150, 0, 0,   151, 152, 0, 0,   153, 154, 0, 0,   155, 156, 0, 0,
13146         157, 158, 0, 0,   159, 160, 0, 0,   161, 162, 0, 0,   163, 164, 0, 0,
13147         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
13148         165, 166, 167, 0,
13149         // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
13150         168, 169, 170, 0,   171, 172, 173, 0,
13151         174, 175, 176, 0,   177, 178, 179, 0,
13152         180, 181, 182, 0,   183, 184, 185, 0,
13153         186, 187, 188, 0,   189, 190, 191, 0,
13154         192, 193, 194, 0,   195, 196, 197, 0,
13155         198, 199, 200, 0,   201, 202, 203, 0,
13156 
13157         // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13158         70, 72, 74, 0,     71, 73, 75, 0,
13159         // i.f (float[3]), copied from ubo140cIn.o.i[1].f
13160         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
13161         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13162         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
13163         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
13164         // i.i (ivec3), copied from ubo140cIn.o.i[1].i
13165         96, 97, 98, 0,
13166         // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13167          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
13168         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
13169         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
13170         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
13171         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
13172         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
13173     };
13174     const std::vector<float> ssbo430rExpect = {
13175         // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13176         1, 2,           3, 4,
13177         135, 136,       137, 138,
13178 
13179         // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13180         70, 72, 74, 0,  71, 73, 75, 0,
13181         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
13182         77, 78, 79, 0,
13183         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
13184         80, 81,         82, 83,         84, 85,         86, 87,
13185         88, 89,         90, 91,         92, 93,         94, 95,
13186         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
13187         96, 97, 98, 0,
13188         // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13189          99, 102,        100, 103,         101, 104,
13190         105, 108,        106, 109,         107, 110,
13191         111, 114,        112, 115,         113, 116,
13192         117, 120,        118, 121,         119, 122,
13193         123, 126,        124, 127,         125, 128,
13194         129, 132,        130, 133,         131, 134,
13195 
13196         // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
13197         204, 206, 208, 0,  205, 207, 209, 0,
13198         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
13199         211, 212, 213, 0,
13200         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13201         214, 215,         216, 217,         218, 219,         220, 221,
13202         222, 223,         224, 225,         226, 227,         228, 229,
13203         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
13204         230, 231, 232, 0,
13205         // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
13206         233, 236,         234, 237,         235, 238,
13207         239, 242,         240, 243,         241, 244,
13208         245, 248,         246, 249,         247, 250,
13209         251, 254,         252, 255,         253, 256,
13210         257, 260,         258, 261,         259, 262,
13211         263, 266,         264, 267,         265, 268,
13212 
13213         // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
13214         204, 205,          206, 207,         208, 209,
13215         // i.f (float[3]), copied from ubo430rIn.o.i[1].f
13216         211, 212, 213, 0,
13217         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13218         214, 215,         216, 217,         218, 219,         220, 221,
13219         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
13220         // i.i (ivec3), copied from ubo430rIn.o.i[1].i
13221         230, 231, 232, 0,
13222         // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
13223         233, 234, 235, 0,   236, 237, 238, 0,
13224         239, 240, 241, 0,   242, 243, 244, 0,
13225         245, 246, 247, 0,   248, 249, 250, 0,
13226         251, 252, 253, 0,   254, 255, 256, 0,
13227         257, 258, 259, 0,   260, 261, 262, 0,
13228         263, 264, 265, 0,   266, 267, 268, 0,
13229     };
13230     const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
13231     // clang-format on
13232 
13233     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13234     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13235 
13236     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13237                static_cast<uint32_t>(ubo140cData.size()), true);
13238     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13239                static_cast<uint32_t>(ubo430rData.size()), false);
13240     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
13241                static_cast<uint32_t>(ssbo140cExpect.size()), false);
13242     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13243                static_cast<uint32_t>(ssbo430rExpect.size()), false);
13244     EXPECT_GL_NO_ERROR();
13245 
13246     glUseProgram(program);
13247     glDispatchCompute(1, 1, 1);
13248     EXPECT_GL_NO_ERROR();
13249 
13250     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
13251                              static_cast<uint32_t>(ssbo140cExpect.size())));
13252     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13253                              static_cast<uint32_t>(ssbo430rExpect.size())));
13254 }
13255 
13256 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)13257 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
13258 {
13259     constexpr char kCS[] = R"(#version 310 es
13260 precision highp float;
13261 layout(local_size_x=1) in;
13262 
13263 struct Inner
13264 {
13265     bool b;
13266     bvec2 b2;
13267     bvec3 b3;
13268     bvec4 b4;
13269     bool ba[5];
13270     bvec2 b2a[2][3];
13271 };
13272 
13273 struct Outer
13274 {
13275     Inner i[2];
13276 };
13277 
13278 layout(std140) uniform Ubo140
13279 {
13280     Outer o;
13281 };
13282 
13283 layout(std430, binding = 0) buffer Ubo430
13284 {
13285     Outer o;
13286 } ubo430In;
13287 
13288 layout(std140, binding = 1) buffer Ssbo140
13289 {
13290     bool valid;
13291     Inner i;
13292 } ssbo140Out;
13293 
13294 layout(std430, binding = 2) buffer Ssbo430
13295 {
13296     bool valid;
13297     Inner i;
13298 };
13299 
13300 void writeArgToStd430(bool ba[5])
13301 {
13302     i.ba = ba;
13303 }
13304 
13305 bool[5] readFromStd430(uint innerIndex)
13306 {
13307     return ubo430In.o.i[innerIndex].ba;
13308 }
13309 
13310 void copyFromStd430(out bvec2 b2a[2][3])
13311 {
13312     b2a = ubo430In.o.i[0].b2a;
13313 }
13314 
13315 bool destroyContent(inout Inner iOut)
13316 {
13317     iOut.b = true;
13318     iOut.b2 = bvec2(true);
13319     iOut.b3 = bvec3(true);
13320     iOut.b4 = bvec4(true);
13321     iOut.ba = bool[5](true, true, true, true, true);
13322     bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
13323     iOut.b2a = bvec2[2][3](true3, true3);
13324     return true;
13325 }
13326 
13327 void main(){
13328     // Directly copy from one layout to another.
13329     i.b = o.i[0].b;
13330     i.b2 = o.i[0].b2;
13331     i.b2a = o.i[0].b2a;
13332 
13333     // Copy to temp with swizzle.
13334     bvec4 t1 = o.i[0].b3.yxzy;
13335     bvec4 t2 = o.i[0].b4.xxyy;
13336     bvec4 t3 = o.i[0].b4.zzww;
13337 
13338     // Copy from temp with swizzle.
13339     i.b3 = t1.ywz;
13340     i.b4.yz = bvec2(t2.z, t3.y);
13341     i.b4.wx = bvec2(t3.w, t2.x);
13342 
13343     // Copy by passing argument to function.
13344     writeArgToStd430(o.i[0].ba);
13345 
13346     // Copy by return value.
13347     ssbo140Out.i.ba = readFromStd430(0u);
13348 
13349     // Copy by out parameter.
13350     copyFromStd430(ssbo140Out.i.b2a);
13351 
13352     // Logical operations
13353     uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
13354     ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
13355     ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
13356     ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
13357     ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
13358 
13359     ssbo140Out.valid = true;
13360     ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
13361     ssbo140Out.valid = ssbo140Out.valid &&
13362             all(notEqual(o.i[1].b4, bvec4(o.i[1].ba[0], o.i[1].ba[1], o.i[1].ba[2], o.i[1].ba[3])));
13363     ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
13364     for (int x = 0; x < o.i[1].b2a.length(); ++x)
13365     {
13366         for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
13367         {
13368             ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
13369         }
13370     }
13371 
13372     valid = o.i[1] == ubo430In.o.i[1];
13373 
13374     // Make sure short-circuiting behavior is correct.
13375     bool falseVar = !valid && destroyContent(i);
13376     if (falseVar && destroyContent(ssbo140Out.i))
13377     {
13378         valid = false;
13379     }
13380 
13381     if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
13382     {
13383     }
13384     else
13385     {
13386         ssbo140Out.valid = false;
13387     }
13388 })";
13389 
13390     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13391     EXPECT_GL_NO_ERROR();
13392 
13393     // Test data, laid out with padding (0) based on std140/std430 rules.
13394     // clang-format off
13395     const std::vector<uint32_t> ubo140Data = {
13396         // o.i[0].b (bool)
13397         true, 0,
13398         // o.i[0].b2 (bvec2)
13399         true, false,
13400         // o.i[0].b3 (bvec3)
13401         true, true, false, 0,
13402         // o.i[0].b4 (bvec4)
13403         false, true, false, true,
13404         // o.i[0].ba (bool[5])
13405         true, 0, 0, 0,
13406         false, 0, 0, 0,
13407         false, 0, 0, 0,
13408         true, 0, 0, 0,
13409         true, 0, 0, 0,
13410         // o.i[0].b2a (bool[2][3])
13411         false, true, 0, 0,  true, true, 0, 0,    true, false, 0, 0,
13412         true, false, 0, 0,  false, false, 0, 0,  true, true, 0, 0,
13413 
13414         // o.i[1].b (bool)
13415         false, 0,
13416         // o.i[1].b2 (bvec2)
13417         true, true,
13418         // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
13419         false, true, true, 0,
13420         // o.i[1].b4 (bvec4)
13421         true, false, true, true,
13422         // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
13423         false, 0, 0, 0,
13424         true, 0, 0, 0,
13425         false, 0, 0, 0,
13426         false, 0, 0, 0,
13427         true, 0, 0, 0,
13428         // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
13429         false, false, 0, 0,  false, true, 0, 0,  false, false, 0, 0,
13430         true, false, 0, 0,   true, true, 0, 0,   true, false, 0, 0,
13431     };
13432     const std::vector<uint32_t> ubo430Data = {
13433         // o.i[0].b (bool)
13434         false, 0,
13435         // o.i[0].b2 (bvec2)
13436         true, true,
13437         // o.i[0].b3 (bvec3)
13438         false, false, true, 0,
13439         // o.i[0].b4 (bvec4)
13440         true, false, true, true,
13441         // o.i[0].ba (bool[5])
13442         false, false, false, true, false, 0,
13443         // o.i[0].b2a (bool[2][3])
13444         true, false,  true, false,  true, true,
13445         false, true,  true, true,   false, false, 0, 0,
13446 
13447         // o.i[1] expected to be equal to ubo140In.o.i[1]
13448         // o.i[1].b (bool)
13449         false, 0,
13450         // o.i[1].b2 (bvec2)
13451         true, true,
13452         // o.i[1].b3 (bvec3)
13453         false, true, true, 0,
13454         // o.i[1].b4 (bvec4)
13455         true, false, true, true,
13456         // o.i[1].ba (bool[5])
13457         false, true, false, false, true, 0,
13458         // o.i[1].b2a (bvec2[2][3])
13459         false, false,  false, true,  false, false,
13460         true, false,   true, true,   true, false,
13461     };
13462     const std::vector<uint32_t> ssbo140Expect = {
13463         // valid, expected to be true
13464         true, 0, 0, 0,
13465 
13466         // i.b (bool), ubo430In.o.i[0].b ? false : true
13467         true, 0,
13468         // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
13469         false, false,
13470         // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
13471         false, true, false, 0,
13472         // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
13473         true, true, true, false,
13474         // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
13475         false, 0, 0, 0,
13476         false, 0, 0, 0,
13477         false, 0, 0, 0,
13478         true, 0, 0, 0,
13479         false, 0, 0, 0,
13480         // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
13481         true, false, 0, 0,  true, false, 0, 0,   true, true, 0, 0,
13482         false, true, 0, 0,  true, true, 0, 0,    false, false, 0, 0,
13483     };
13484     const std::vector<uint32_t> ssbo430Expect = {
13485         // valid, expected to be true
13486         true, 0, 0, 0,
13487 
13488         // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
13489         true, 0,
13490         // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
13491         true, false,
13492         // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
13493         true, true, false, 0,
13494         // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
13495         false, true, false, true,
13496         // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
13497         true, false, false, true, true, 0,
13498         // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
13499         false, true,  true, true,    true, false,
13500         true, false,  false, false,  true, true, 0, 0,
13501     };
13502     const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
13503     // clang-format on
13504 
13505     GLBuffer uboStd140, uboStd430;
13506     GLBuffer ssboStd140, ssboStd430;
13507 
13508     InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
13509                static_cast<uint32_t>(ubo140Data.size()), true);
13510     InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
13511                static_cast<uint32_t>(ubo430Data.size()), false);
13512     InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
13513                static_cast<uint32_t>(ssbo140Expect.size()), false);
13514     InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
13515                static_cast<uint32_t>(ssbo430Expect.size()), false);
13516     EXPECT_GL_NO_ERROR();
13517 
13518     glUseProgram(program);
13519     glDispatchCompute(1, 1, 1);
13520     EXPECT_GL_NO_ERROR();
13521 
13522     EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
13523                              static_cast<uint32_t>(ssbo140Expect.size())));
13524     EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
13525                              static_cast<uint32_t>(ssbo430Expect.size())));
13526 }
13527 
13528 // Verify that ternary operator works when the operands are matrices used in different block
13529 // storage.
TEST_P(GLSLTest_ES31,TernaryOnMatricesInDifferentBlockStorages)13530 TEST_P(GLSLTest_ES31, TernaryOnMatricesInDifferentBlockStorages)
13531 {
13532     constexpr char kCS[] = R"(#version 310 es
13533 precision highp float;
13534 layout(local_size_x=1) in;
13535 
13536 layout(std140, column_major) uniform Ubo140c
13537 {
13538     uint u;
13539     layout(row_major) mat3x2 m;
13540 } ubo140cIn;
13541 
13542 layout(std430, row_major, binding = 0) buffer Ubo430r
13543 {
13544     uint u;
13545     layout(column_major) mat3x2 m;
13546 } ubo430rIn;
13547 
13548 layout(std140, column_major, binding = 1) buffer Ssbo140c
13549 {
13550     uint u;
13551     mat3x2 m;
13552 } ssbo140cIn;
13553 
13554 layout(std430, row_major, binding = 2) buffer Ssbo430r
13555 {
13556     mat3x2 m1;
13557     mat3x2 m2;
13558 } ssbo430rOut;
13559 
13560 void main(){
13561     ssbo430rOut.m1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.m : ubo430rIn.m;
13562     ssbo430rOut.m2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.m : ubo140cIn.m;
13563 
13564     mat3x2 m = mat3x2(0);
13565 
13566     ssbo430rOut.m1 = ubo140cIn.u == 0u ? m : ssbo430rOut.m1;
13567 })";
13568 
13569     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13570     EXPECT_GL_NO_ERROR();
13571 
13572     // Test data, laid out with padding (0) based on std140/std430 rules.
13573     // clang-format off
13574     const std::vector<float> ubo140cData = {
13575         // u (uint)
13576         1, 0, 0, 0,
13577 
13578         // m (mat3x2, row-major)
13579         5, 7, 9, 0,     6, 8, 10, 0,
13580     };
13581     const std::vector<float> ubo430rData = {
13582         // u (uint)
13583         135, 0,
13584 
13585         // m (mat3x2, column-major)
13586         139, 140,         141, 142,         143, 144,
13587     };
13588     const std::vector<float> ssbo140cData = {
13589         // u (uint)
13590         204, 0, 0, 0,
13591 
13592         // m (mat3x2, column-major)
13593         205, 206, 0, 0,  207, 208, 0, 0,  209, 210, 0, 0,
13594     };
13595     const std::vector<float> ssbo430rExpect = {
13596         // m1 (mat3x2, row-major), copied from ubo430rIn.m
13597         139, 141, 143, 0,  140, 142, 144, 0,
13598 
13599         // m2 (mat3x2, row-major), copied from ssbo140cIn.m
13600         205, 207, 209, 0,  206, 208, 210, 0,
13601     };
13602     const std::vector<float> zeros(ssbo430rExpect.size(), 0);
13603     // clang-format on
13604 
13605     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13606     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13607 
13608     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13609                static_cast<uint32_t>(ubo140cData.size()), true);
13610     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13611                static_cast<uint32_t>(ubo430rData.size()), false);
13612     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
13613                static_cast<uint32_t>(ssbo140cData.size()), false);
13614     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13615                static_cast<uint32_t>(ssbo430rExpect.size()), false);
13616     EXPECT_GL_NO_ERROR();
13617 
13618     glUseProgram(program);
13619     glDispatchCompute(1, 1, 1);
13620     EXPECT_GL_NO_ERROR();
13621 
13622     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13623                              static_cast<uint32_t>(ssbo430rExpect.size())));
13624 }
13625 
13626 // Verify that ternary operator works when the operands are structs used in different block
13627 // storage.
TEST_P(GLSLTest_ES31,TernaryOnStructsInDifferentBlockStorages)13628 TEST_P(GLSLTest_ES31, TernaryOnStructsInDifferentBlockStorages)
13629 {
13630     constexpr char kCS[] = R"(#version 310 es
13631 precision highp float;
13632 layout(local_size_x=1) in;
13633 
13634 struct S
13635 {
13636     mat3x2 m[2];
13637 };
13638 
13639 layout(std140, column_major) uniform Ubo140c
13640 {
13641     uint u;
13642     layout(row_major) S s;
13643 } ubo140cIn;
13644 
13645 layout(std430, row_major, binding = 0) buffer Ubo430r
13646 {
13647     uint u;
13648     layout(column_major) S s;
13649 } ubo430rIn;
13650 
13651 layout(std140, column_major, binding = 1) buffer Ssbo140c
13652 {
13653     uint u;
13654     S s;
13655 } ssbo140cIn;
13656 
13657 layout(std430, row_major, binding = 2) buffer Ssbo430r
13658 {
13659     S s1;
13660     S s2;
13661 } ssbo430rOut;
13662 
13663 void main(){
13664     ssbo430rOut.s1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.s : ubo430rIn.s;
13665     ssbo430rOut.s2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.s : ubo140cIn.s;
13666 
13667     S s;
13668     s.m[0] = mat3x2(0);
13669     s.m[1] = mat3x2(0);
13670 
13671     ssbo430rOut.s1 = ubo140cIn.u == 0u ? s : ssbo430rOut.s1;
13672 })";
13673 
13674     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13675     EXPECT_GL_NO_ERROR();
13676 
13677     // Test data, laid out with padding (0) based on std140/std430 rules.
13678     // clang-format off
13679     const std::vector<float> ubo140cData = {
13680         // u (uint)
13681         1, 0, 0, 0,
13682 
13683         // s.m[0] (mat3x2, row-major)
13684         5, 7, 9, 0,     6, 8, 10, 0,
13685         // s.m[1] (mat3x2, row-major)
13686         25, 27, 29, 0,  26, 28, 30, 0,
13687     };
13688     const std::vector<float> ubo430rData = {
13689         // u (uint)
13690         135, 0,
13691 
13692         // s.m[0] (mat3x2, column-major)
13693         139, 140,         141, 142,         143, 144,
13694         // s.m[1] (mat3x2, column-major)
13695         189, 190,         191, 192,         193, 194,
13696     };
13697     const std::vector<float> ssbo140cData = {
13698         // u (uint)
13699         204, 0, 0, 0,
13700 
13701         // s.m[0] (mat3x2, column-major)
13702         205, 206, 0, 0,  207, 208, 0, 0,  209, 210, 0, 0,
13703         // s.m[1] (mat3x2, column-major)
13704         245, 246, 0, 0,  247, 248, 0, 0,  249, 250, 0, 0,
13705     };
13706     const std::vector<float> ssbo430rExpect = {
13707         // s1.m[0] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
13708         139, 141, 143, 0,  140, 142, 144, 0,
13709         // s1.m[1] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
13710         189, 191, 193, 0,  190, 192, 194, 0,
13711 
13712         // s2.m[0] (mat3x2, row-major), copied from ssbo140cIn.m
13713         205, 207, 209, 0,  206, 208, 210, 0,
13714         // s2.m[1] (mat3x2, row-major), copied from ssbo140cIn.m
13715         245, 247, 249, 0,  246, 248, 250, 0,
13716     };
13717     const std::vector<float> zeros(ssbo430rExpect.size(), 0);
13718     // clang-format on
13719 
13720     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13721     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13722 
13723     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13724                static_cast<uint32_t>(ubo140cData.size()), true);
13725     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13726                static_cast<uint32_t>(ubo430rData.size()), false);
13727     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
13728                static_cast<uint32_t>(ssbo140cData.size()), false);
13729     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13730                static_cast<uint32_t>(ssbo430rExpect.size()), false);
13731     EXPECT_GL_NO_ERROR();
13732 
13733     glUseProgram(program);
13734     glDispatchCompute(1, 1, 1);
13735     EXPECT_GL_NO_ERROR();
13736 
13737     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13738                              static_cast<uint32_t>(ssbo430rExpect.size())));
13739 }
13740 
13741 // Verify that uint in interface block cast to bool works.
TEST_P(GLSLTest_ES3,UintCastToBoolFromInterfaceBlocks)13742 TEST_P(GLSLTest_ES3, UintCastToBoolFromInterfaceBlocks)
13743 {
13744     constexpr char kFS[] = R"(#version 300 es
13745 precision mediump float;
13746 
13747 uniform uvec4 uv4;
13748 uniform uvec2 uv2;
13749 uniform uint u1;
13750 uniform uint u2;
13751 
13752 out vec4 colorOut;
13753 
13754 void main()
13755 {
13756     bvec4 bv4 = bvec4(uv4);
13757     bvec2 bv2 = bvec2(uv2);
13758     bool b1 = bool(u1);
13759     bool b2 = bool(u2);
13760 
13761     vec4 vv4 = mix(vec4(0), vec4(0.4), bv4);
13762     vec2 vv2 = mix(vec2(0), vec2(0.7), bv2);
13763     float v1 = b1 ? 1.0 : 0.0;
13764     float v2 = b2 ? 0.0 : 1.0;
13765 
13766     colorOut = vec4(vv4.x - vv4.y + vv4.z + vv4.w,
13767                         (vv2.y - vv2.x) * 1.5,
13768                         v1,
13769                         v2);
13770 })";
13771 
13772     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
13773     EXPECT_GL_NO_ERROR();
13774 
13775     glUseProgram(program);
13776     GLint uv4 = glGetUniformLocation(program, "uv4");
13777     GLint uv2 = glGetUniformLocation(program, "uv2");
13778     GLint u1  = glGetUniformLocation(program, "u1");
13779     GLint u2  = glGetUniformLocation(program, "u2");
13780     ASSERT_NE(uv4, -1);
13781     ASSERT_NE(uv2, -1);
13782     ASSERT_NE(u1, -1);
13783     ASSERT_NE(u2, -1);
13784 
13785     glUniform4ui(uv4, 123, 0, 9, 8297312);
13786     glUniform2ui(uv2, 0, 90812);
13787     glUniform1ui(u1, 8979421);
13788     glUniform1ui(u2, 0);
13789 
13790     glClearColor(0, 0, 0, 0);
13791     glClear(GL_COLOR_BUFFER_BIT);
13792 
13793     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13794     EXPECT_GL_NO_ERROR();
13795 
13796     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
13797 }
13798 
13799 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)13800 TEST_P(GLSLTest_ES3, PreciseNotReserved)
13801 {
13802     // Skip in ES3.1+ as the precise keyword is reserved/core.
13803     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
13804                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
13805 
13806     constexpr char kFS[] = R"(#version 300 es
13807 precision mediump float;
13808 in float precise;
13809 out vec4 my_FragColor;
13810 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
13811 
13812     constexpr char kVS[] = R"(#version 300 es
13813 in vec4 a_position;
13814 out float precise;
13815 void main() { precise = a_position.x; gl_Position = a_position; })";
13816 
13817     GLuint program = CompileProgram(kVS, kFS);
13818     EXPECT_NE(0u, program);
13819 }
13820 
13821 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)13822 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
13823 {
13824     // Skip if EXT_gpu_shader5 is enabled.
13825     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13826     // Skip in ES3.2+ as the precise keyword is core.
13827     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
13828                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
13829 
13830     constexpr char kFS[] = R"(#version 310 es
13831 precision mediump float;
13832 in float v_varying;
13833 out vec4 my_FragColor;
13834 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
13835 
13836     constexpr char kVS[] = R"(#version 310 es
13837 in vec4 a_position;
13838 precise out float v_varying;
13839 void main() { v_varying = a_position.x; gl_Position = a_position; })";
13840 
13841     // Should fail, as precise is a reserved keyword when the extension is not enabled.
13842     GLuint program = CompileProgram(kVS, kFS);
13843     EXPECT_EQ(0u, program);
13844 }
13845 
13846 // Test that reusing the same variable name for different uses across stages links fine.  The SPIR-V
13847 // transformation should ignore all names for non-shader-interface variables and not get confused by
13848 // them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)13849 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
13850 {
13851     constexpr char kVS[] = R"(#version 310 es
13852 precision mediump float;
13853 uniform highp vec4 a;
13854 in highp vec4 b;
13855 in highp vec4 c;
13856 in highp vec4 d;
13857 out highp vec4 e;
13858 
13859 vec4 f(vec4 a)
13860 {
13861     return a;
13862 }
13863 
13864 vec4 g(vec4 f)
13865 {
13866     return f + f;
13867 }
13868 
13869 void main() {
13870     e = f(b) + a;
13871     gl_Position = g(c) + f(d);
13872 }
13873 )";
13874 
13875     constexpr char kFS[] = R"(#version 310 es
13876 precision mediump float;
13877 in highp vec4 e;
13878 uniform sampler2D f;
13879 layout(rgba8) uniform highp readonly image2D g;
13880 uniform A
13881 {
13882     vec4 x;
13883 } c;
13884 layout(std140, binding=0) buffer B
13885 {
13886     vec4 x;
13887 } d[2];
13888 out vec4 col;
13889 
13890 vec4 h(vec4 c)
13891 {
13892     return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
13893 }
13894 
13895 vec4 i(vec4 x, vec4 y)
13896 {
13897     return vec4(x.xy, y.zw);
13898 }
13899 
13900 void main() {
13901     col = h(e) + i(c.x, d[0].x) + d[1].x;
13902 }
13903 )";
13904 
13905     GLuint program = CompileProgram(kVS, kFS);
13906     EXPECT_NE(0u, program);
13907 }
13908 
13909 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)13910 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
13911 {
13912     constexpr char kVS[] = R"(#version 310 es
13913 precision mediump float;
13914 in highp vec4 variableWithSameName;
13915 
13916 void main() {
13917     gl_Position = variableWithSameName;
13918 }
13919 )";
13920 
13921     constexpr char kFS[] = R"(#version 310 es
13922 precision mediump float;
13923 uniform vec4 variableWithSameName;
13924 out vec4 col;
13925 
13926 void main() {
13927     col = vec4(variableWithSameName);
13928 }
13929 )";
13930 
13931     GLuint program = CompileProgram(kVS, kFS);
13932     EXPECT_NE(0u, program);
13933 }
13934 
13935 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)13936 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
13937 {
13938     // Nvidia driver bug: http://anglebug.com/5240
13939     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
13940 
13941     constexpr char kVSUnused[] = R"(#version 300 es
13942 precision highp float;
13943 uniform highp vec4 positionIn;
13944 
13945 void main()
13946 {
13947     gl_Position = vec4(1, 0, 0, 1);
13948 })";
13949 
13950     constexpr char kVSStaticUse[] = R"(#version 300 es
13951 precision highp float;
13952 uniform highp vec4 positionIn;
13953 
13954 void main()
13955 {
13956     gl_Position = positionIn;
13957 })";
13958 
13959     constexpr char kFSUnused[] = R"(#version 300 es
13960 precision highp float;
13961 uniform highp vec4 positionIn;
13962 out vec4 my_FragColor;
13963 
13964 void main()
13965 {
13966     my_FragColor = vec4(1, 0, 0, 1);
13967 })";
13968 
13969     constexpr char kFSStaticUse[] = R"(#version 300 es
13970 precision highp float;
13971 uniform mediump vec4 positionIn;
13972 out vec4 my_FragColor;
13973 
13974 void main()
13975 {
13976     my_FragColor = vec4(1, 0, 0, positionIn.z);
13977 })";
13978 
13979     GLuint program = 0;
13980 
13981     program = CompileProgram(kVSUnused, kFSUnused);
13982     EXPECT_NE(0u, program);
13983 
13984     program = CompileProgram(kVSUnused, kFSStaticUse);
13985     EXPECT_NE(0u, program);
13986 
13987     program = CompileProgram(kVSStaticUse, kFSUnused);
13988     EXPECT_NE(0u, program);
13989 
13990     program = CompileProgram(kVSStaticUse, kFSStaticUse);
13991     EXPECT_EQ(0u, program);
13992 }
13993 
13994 // Validate that link fails when two instanceless interface blocks with different block names but
13995 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)13996 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
13997 {
13998     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
13999 
14000     constexpr char kVS[] = R"(#version 310 es
14001 in highp vec4 position;
14002 layout(binding = 0) buffer BlockA { mediump float a; };
14003 void main()
14004 {
14005     a = 0.0;
14006     gl_Position = position;
14007 })";
14008 
14009     constexpr char kFS[] = R"(#version 310 es
14010 precision mediump float;
14011 layout(location = 0) out mediump vec4 color;
14012 uniform BlockB { float a; };
14013 void main()
14014 {
14015     color = vec4(a, a, a, 1.0);
14016 })";
14017 
14018     GLuint program = CompileProgram(kVS, kFS);
14019     EXPECT_EQ(0u, program);
14020 }
14021 
14022 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)14023 TEST_P(GLSLTest_ES31, IOBlockLocations)
14024 {
14025     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14026     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14027 
14028     constexpr char kVS[] = R"(#version 310 es
14029 #extension GL_EXT_shader_io_blocks : require
14030 
14031 in highp vec4 position;
14032 
14033 layout(location = 0) out vec4 aOut;
14034 
14035 layout(location = 6) out VSBlock
14036 {
14037     vec4 b;     // location 6
14038     vec4 c;     // location 7
14039     layout(location = 1) vec4 d;
14040     vec4 e;     // location 2
14041     vec4 f[2];  // locations 3 and 4
14042 } blockOut;
14043 
14044 layout(location = 5) out vec4 gOut;
14045 
14046 void main()
14047 {
14048     aOut = vec4(0.03, 0.06, 0.09, 0.12);
14049     blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
14050     blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
14051     blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
14052     blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
14053     blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
14054     blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
14055     gOut = vec4(0.84, 0.87, 0.9, 0.93);
14056     gl_Position = position;
14057 })";
14058 
14059     constexpr char kGS[] = R"(#version 310 es
14060 #extension GL_EXT_geometry_shader : require
14061 layout (triangles) in;
14062 layout (triangle_strip, max_vertices = 3) out;
14063 
14064 // Input varyings
14065 layout(location = 0) in vec4 aIn[];
14066 
14067 layout(location = 6) in VSBlock
14068 {
14069     vec4 b;
14070     vec4 c;
14071     layout(location = 1) vec4 d;
14072     vec4 e;
14073     vec4 f[2];
14074 } blockIn[];
14075 
14076 layout(location = 5) in vec4 gIn[];
14077 
14078 // Output varyings
14079 layout(location = 1) out vec4 aOut;
14080 
14081 layout(location = 0) out GSBlock
14082 {
14083     vec4 b;     // location 0
14084     layout(location = 3) vec4 c;
14085     layout(location = 7) vec4 d;
14086     layout(location = 5) vec4 e[2];
14087     layout(location = 4) vec4 f;
14088 } blockOut;
14089 
14090 layout(location = 2) out vec4 gOut;
14091 
14092 void main()
14093 {
14094     int n;
14095     for (n = 0; n < gl_in.length(); n++)
14096     {
14097         gl_Position = gl_in[n].gl_Position;
14098 
14099         aOut = aIn[n];
14100         blockOut.b = blockIn[n].b;
14101         blockOut.c = blockIn[n].c;
14102         blockOut.d = blockIn[n].d;
14103         blockOut.e[0] = blockIn[n].e;
14104         blockOut.e[1] = blockIn[n].f[0];
14105         blockOut.f = blockIn[n].f[1];
14106         gOut = gIn[n];
14107 
14108         EmitVertex();
14109     }
14110     EndPrimitive();
14111 })";
14112 
14113     constexpr char kFS[] = R"(#version 310 es
14114 #extension GL_EXT_shader_io_blocks : require
14115 precision mediump float;
14116 
14117 layout(location = 0) out mediump vec4 color;
14118 
14119 layout(location = 1) in vec4 aIn;
14120 
14121 layout(location = 0) in GSBlock
14122 {
14123     vec4 b;
14124     layout(location = 3) vec4 c;
14125     layout(location = 7) vec4 d;
14126     layout(location = 5) vec4 e[2];
14127     layout(location = 4) vec4 f;
14128 } blockIn;
14129 
14130 layout(location = 2) in vec4 gIn;
14131 
14132 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14133 
14134 void main()
14135 {
14136     bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
14137     bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
14138                  isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
14139                  isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
14140                  isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14141                  isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
14142                  isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
14143     bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
14144 
14145     color = vec4(passR, passG, passB, 1.0);
14146 })";
14147 
14148     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14149     EXPECT_GL_NO_ERROR();
14150 
14151     GLTexture color;
14152     glBindTexture(GL_TEXTURE_2D, color);
14153     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14154 
14155     GLFramebuffer fbo;
14156     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14157     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14158 
14159     drawQuad(program, "position", 0);
14160 
14161     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14162 }
14163 
14164 // Test using builtins that can only be redefined with gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexRedefinition)14165 TEST_P(GLSLTest_ES31, PerVertexRedefinition)
14166 {
14167     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14168     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14169 
14170     constexpr char kVS[] = R"(#version 310 es
14171 void main()
14172 {
14173     gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14174 })";
14175 
14176     constexpr char kGS[] = R"(#version 310 es
14177 #extension GL_EXT_geometry_shader : require
14178 #extension GL_EXT_clip_cull_distance : require
14179 
14180 layout(lines_adjacency, invocations = 3) in;
14181 layout(points, max_vertices = 16) out;
14182 
14183 out gl_PerVertex {
14184     vec4 gl_Position;
14185     float gl_ClipDistance[4];
14186     float gl_CullDistance[4];
14187 };
14188 
14189 void main()
14190 {
14191     for (int n = 0; n < 16; ++n)
14192     {
14193         gl_Position = vec4(n, 0.0, 0.0, 1.0);
14194         EmitVertex();
14195     }
14196 
14197     EndPrimitive();
14198 })";
14199 
14200     constexpr char kFS[] = R"(#version 310 es
14201 precision highp float;
14202 
14203 out vec4 result;
14204 
14205 void main()
14206 {
14207     result = vec4(1.0);
14208 })";
14209 
14210     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14211     EXPECT_GL_NO_ERROR();
14212 }
14213 
14214 // Negative test using builtins that can only be used when redefining gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexNegativeTest)14215 TEST_P(GLSLTest_ES31, PerVertexNegativeTest)
14216 {
14217     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14218     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14219 
14220     constexpr char kVS[] = R"(#version 310 es
14221 void main()
14222 {
14223     gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14224 })";
14225 
14226     constexpr char kGS[] = R"(#version 310 es
14227 #extension GL_EXT_geometry_shader : require
14228 #extension GL_EXT_clip_cull_distance : require
14229 
14230 layout(lines_adjacency, invocations = 3) in;
14231 layout(points, max_vertices = 16) out;
14232 
14233 vec4 gl_Position;
14234 float gl_ClipDistance[4];
14235 float gl_CullDistance[4];
14236 
14237 void main()
14238 {
14239     for (int n = 0; n < 16; ++n)
14240     {
14241         gl_Position = vec4(n, 0.0, 0.0, 1.0);
14242         EmitVertex();
14243     }
14244 
14245     EndPrimitive();
14246 })";
14247 
14248     constexpr char kFS[] = R"(#version 310 es
14249 precision highp float;
14250 
14251 out vec4 result;
14252 
14253 void main()
14254 {
14255     result = vec4(1.0);
14256 })";
14257 
14258     GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14259     EXPECT_EQ(0u, program);
14260     glDeleteProgram(program);
14261 }
14262 
14263 // Negative test using builtins that can only be used when redefining gl_PerVertex
14264 // but have the builtins in a differently named struct
TEST_P(GLSLTest_ES31,PerVertexRenamedNegativeTest)14265 TEST_P(GLSLTest_ES31, PerVertexRenamedNegativeTest)
14266 {
14267     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14268     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14269 
14270     constexpr char kVS[] = R"(#version 310 es
14271 void main()
14272 {
14273     gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14274 })";
14275 
14276     constexpr char kGS[] = R"(#version 310 es
14277 #extension GL_EXT_geometry_shader : require
14278 #extension GL_EXT_clip_cull_distance : require
14279 
14280 layout(lines_adjacency, invocations = 3) in;
14281 layout(points, max_vertices = 16) out;
14282 
14283 out Block {
14284     vec4 gl_Position;
14285     float gl_ClipDistance[4];
14286     float gl_CullDistance[4];
14287 };
14288 
14289 void main()
14290 {
14291     for (int n = 0; n < 16; ++n)
14292     {
14293         gl_Position = vec4(n, 0.0, 0.0, 1.0);
14294         EmitVertex();
14295     }
14296 
14297     EndPrimitive();
14298 })";
14299 
14300     constexpr char kFS[] = R"(#version 310 es
14301 precision highp float;
14302 
14303 out vec4 result;
14304 
14305 void main()
14306 {
14307     result = vec4(1.0);
14308 })";
14309 
14310     GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14311     EXPECT_EQ(0u, program);
14312     glDeleteProgram(program);
14313 }
14314 
14315 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)14316 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
14317 {
14318     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14319 
14320     constexpr char kVS[] = R"(#version 310 es
14321 #extension GL_EXT_shader_io_blocks : require
14322 
14323 in highp vec4 position;
14324 
14325 out VSBlock1
14326 {
14327     vec4 a;
14328     vec4 b[2];
14329 } blockOut1;
14330 
14331 out VSBlock2
14332 {
14333     vec4 c[2];
14334     vec4 d;
14335 } blockOut2;
14336 
14337 void main()
14338 {
14339     blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
14340     blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
14341     blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
14342     blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
14343     blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
14344     blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
14345     gl_Position = position;
14346 })";
14347 
14348     constexpr char kFS[] = R"(#version 310 es
14349 #extension GL_EXT_shader_io_blocks : require
14350 precision mediump float;
14351 
14352 layout(location = 0) out mediump vec4 color;
14353 
14354 in VSBlock1
14355 {
14356     vec4 a;
14357     vec4 b[2];
14358 } blockIn1;
14359 
14360 in VSBlock2
14361 {
14362     vec4 c[2];
14363     vec4 d;
14364 } blockIn2;
14365 
14366 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14367 
14368 void main()
14369 {
14370     bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
14371     bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
14372                  isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
14373     bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14374                  isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
14375     bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
14376 
14377     color = vec4(passR, passG, passB, passA);
14378 })";
14379 
14380     ANGLE_GL_PROGRAM(program, kVS, kFS);
14381     EXPECT_GL_NO_ERROR();
14382 
14383     GLTexture color;
14384     glBindTexture(GL_TEXTURE_2D, color);
14385     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14386 
14387     GLFramebuffer fbo;
14388     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14389     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14390 
14391     drawQuad(program, "position", 0);
14392 
14393     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14394 }
14395 
14396 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)14397 TEST_P(GLSLTest_ES31, IOBlockArray)
14398 {
14399     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14400 
14401     constexpr char kVS[] = R"(#version 310 es
14402 #extension GL_EXT_shader_io_blocks : require
14403 
14404 in highp vec4 position;
14405 
14406 out VSBlock1
14407 {
14408     vec4 b[2];
14409 } blockOut1[2];
14410 
14411 out VSBlock2
14412 {
14413     vec4 d;
14414 } blockOut2[3];
14415 
14416 void main()
14417 {
14418     blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
14419     blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
14420     blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
14421     blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
14422     blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
14423     blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
14424     blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
14425     gl_Position = position;
14426 })";
14427 
14428     constexpr char kFS[] = R"(#version 310 es
14429 #extension GL_EXT_shader_io_blocks : require
14430 precision mediump float;
14431 
14432 layout(location = 0) out mediump vec4 color;
14433 
14434 in VSBlock1
14435 {
14436     vec4 b[2];
14437 } blockIn1[2];
14438 
14439 in VSBlock2
14440 {
14441     vec4 d;
14442 } blockIn2[3];
14443 
14444 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14445 
14446 void main()
14447 {
14448     bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
14449                  isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
14450     bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
14451                  isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
14452     bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
14453     bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
14454                  isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
14455 
14456     color = vec4(passR, passG, passB, passA);
14457 })";
14458 
14459     ANGLE_GL_PROGRAM(program, kVS, kFS);
14460     EXPECT_GL_NO_ERROR();
14461 
14462     GLTexture color;
14463     glBindTexture(GL_TEXTURE_2D, color);
14464     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14465 
14466     GLFramebuffer fbo;
14467     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14468     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14469 
14470     drawQuad(program, "position", 0);
14471 
14472     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14473 }
14474 
14475 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)14476 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
14477 {
14478     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14479 
14480     constexpr char kVS[] = R"(#version 310 es
14481 #extension GL_EXT_shader_io_blocks : require
14482 in highp vec4 position;
14483 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14484 void main()
14485 {
14486     blockOut1.a = vec4(0);
14487     blockOut1.b[0] = vec4(0);
14488     blockOut1.b[1] = vec4(0);
14489     gl_Position = position;
14490 })";
14491 
14492     constexpr char kFS[] = R"(#version 310 es
14493 #extension GL_EXT_shader_io_blocks : require
14494 precision mediump float;
14495 layout(location = 0) out mediump vec4 color;
14496 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
14497 void main()
14498 {
14499     color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14500 })";
14501 
14502     GLuint program = CompileProgram(kVS, kFS);
14503     EXPECT_EQ(0u, program);
14504 }
14505 
14506 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)14507 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
14508 {
14509     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14510 
14511     constexpr char kVS[] = R"(#version 310 es
14512 #extension GL_EXT_shader_io_blocks : require
14513 in highp vec4 position;
14514 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14515 void main()
14516 {
14517     blockOut1.a = vec4(0);
14518     blockOut1.b[0] = vec4(0);
14519     blockOut1.b[1] = vec4(0);
14520     gl_Position = position;
14521 })";
14522 
14523     constexpr char kFS[] = R"(#version 310 es
14524 #extension GL_EXT_shader_io_blocks : require
14525 precision mediump float;
14526 layout(location = 0) out mediump vec4 color;
14527 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
14528 void main()
14529 {
14530     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14531 })";
14532 
14533     GLuint program = CompileProgram(kVS, kFS);
14534     EXPECT_EQ(0u, program);
14535 }
14536 
14537 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)14538 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
14539 {
14540     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14541 
14542     constexpr char kVS[] = R"(#version 310 es
14543 #extension GL_EXT_shader_io_blocks : require
14544 in highp vec4 position;
14545 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14546 void main()
14547 {
14548     blockOut1.a = vec4(0);
14549     blockOut1.b[0] = vec4(0);
14550     blockOut1.b[1] = vec4(0);
14551     gl_Position = position;
14552 })";
14553 
14554     constexpr char kFS[] = R"(#version 310 es
14555 #extension GL_EXT_shader_io_blocks : require
14556 precision mediump float;
14557 layout(location = 0) out mediump vec4 color;
14558 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
14559 void main()
14560 {
14561     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14562 })";
14563 
14564     GLuint program = CompileProgram(kVS, kFS);
14565     EXPECT_EQ(0u, program);
14566 }
14567 
14568 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)14569 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
14570 {
14571     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14572 
14573     constexpr char kVS[] = R"(#version 310 es
14574 #extension GL_EXT_shader_io_blocks : require
14575 in highp vec4 position;
14576 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14577 void main()
14578 {
14579     blockOut1.a = vec4(0);
14580     blockOut1.b[0] = vec4(0);
14581     blockOut1.b[1] = vec4(0);
14582     gl_Position = position;
14583 })";
14584 
14585     constexpr char kFS[] = R"(#version 310 es
14586 #extension GL_EXT_shader_io_blocks : require
14587 precision mediump float;
14588 layout(location = 0) out mediump vec4 color;
14589 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
14590 void main()
14591 {
14592     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14593 })";
14594 
14595     GLuint program = CompileProgram(kVS, kFS);
14596     EXPECT_EQ(0u, program);
14597 }
14598 
14599 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)14600 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
14601 {
14602     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14603 
14604     constexpr char kVS[] = R"(#version 310 es
14605 #extension GL_EXT_shader_io_blocks : require
14606 in highp vec4 position;
14607 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
14608 void main()
14609 {
14610     blockOut1.a = vec4(0);
14611     blockOut1.b[0] = vec4(0);
14612     blockOut1.b[1] = vec4(0);
14613     gl_Position = position;
14614 })";
14615 
14616     constexpr char kFS[] = R"(#version 310 es
14617 #extension GL_EXT_shader_io_blocks : require
14618 precision mediump float;
14619 layout(location = 0) out mediump vec4 color;
14620 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
14621 void main()
14622 {
14623     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14624 })";
14625 
14626     GLuint program = CompileProgram(kVS, kFS);
14627     EXPECT_EQ(0u, program);
14628 }
14629 
14630 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)14631 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
14632 {
14633     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14634 
14635     constexpr char kVS[] = R"(#version 310 es
14636 #extension GL_EXT_shader_io_blocks : require
14637 in highp vec4 position;
14638 struct S1 { vec4 a; vec4 b[2]; };
14639 out VSBlock { S1 s; } blockOut1;
14640 void main()
14641 {
14642     blockOut1.s.a = vec4(0);
14643     blockOut1.s.b[0] = vec4(0);
14644     blockOut1.s.b[1] = vec4(0);
14645     gl_Position = position;
14646 })";
14647 
14648     constexpr char kFS[] = R"(#version 310 es
14649 #extension GL_EXT_shader_io_blocks : require
14650 precision mediump float;
14651 layout(location = 0) out mediump vec4 color;
14652 struct S2 { vec4 a; vec4 b[2]; };
14653 in VSBlock { S2 s; } blockIn1;
14654 void main()
14655 {
14656     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14657 })";
14658 
14659     GLuint program = CompileProgram(kVS, kFS);
14660     EXPECT_EQ(0u, program);
14661 }
14662 
14663 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)14664 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
14665 {
14666     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14667 
14668     constexpr char kVS[] = R"(#version 310 es
14669 #extension GL_EXT_shader_io_blocks : require
14670 in highp vec4 position;
14671 struct S { vec4 c; vec4 b[2]; };
14672 out VSBlock { S s; } blockOut1;
14673 void main()
14674 {
14675     blockOut1.s.c = vec4(0);
14676     blockOut1.s.b[0] = vec4(0);
14677     blockOut1.s.b[1] = vec4(0);
14678     gl_Position = position;
14679 })";
14680 
14681     constexpr char kFS[] = R"(#version 310 es
14682 #extension GL_EXT_shader_io_blocks : require
14683 precision mediump float;
14684 layout(location = 0) out mediump vec4 color;
14685 struct S { vec4 a; vec4 b[2]; };
14686 in VSBlock { S s; } blockIn1;
14687 void main()
14688 {
14689     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14690 })";
14691 
14692     GLuint program = CompileProgram(kVS, kFS);
14693     EXPECT_EQ(0u, program);
14694 }
14695 
14696 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)14697 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
14698 {
14699     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14700 
14701     constexpr char kVS[] = R"(#version 310 es
14702 #extension GL_EXT_shader_io_blocks : require
14703 in highp vec4 position;
14704 struct S { vec4 a; vec4 b[2]; };
14705 out VSBlock { S s; } blockOut1;
14706 void main()
14707 {
14708     blockOut1.s.a = vec4(0);
14709     blockOut1.s.b[0] = vec4(0);
14710     blockOut1.s.b[1] = vec4(0);
14711     gl_Position = position;
14712 })";
14713 
14714     constexpr char kFS[] = R"(#version 310 es
14715 #extension GL_EXT_shader_io_blocks : require
14716 precision mediump float;
14717 layout(location = 0) out mediump vec4 color;
14718 struct S { vec3 a; vec4 b[2]; };
14719 in VSBlock { S s; } blockIn1;
14720 void main()
14721 {
14722     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14723 })";
14724 
14725     GLuint program = CompileProgram(kVS, kFS);
14726     EXPECT_EQ(0u, program);
14727 }
14728 
14729 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)14730 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
14731 {
14732     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14733 
14734     constexpr char kVS[] = R"(#version 310 es
14735 #extension GL_EXT_shader_io_blocks : require
14736 in highp vec4 position;
14737 struct S { vec4 a; vec4 b[3]; };
14738 out VSBlock { S s; } blockOut1;
14739 void main()
14740 {
14741     blockOut1.s.a = vec4(0);
14742     blockOut1.s.b[0] = vec4(0);
14743     blockOut1.s.b[1] = vec4(0);
14744     gl_Position = position;
14745 })";
14746 
14747     constexpr char kFS[] = R"(#version 310 es
14748 #extension GL_EXT_shader_io_blocks : require
14749 precision mediump float;
14750 layout(location = 0) out mediump vec4 color;
14751 struct S { vec4 a; vec4 b[2]; };
14752 in VSBlock { S s; } blockIn1;
14753 void main()
14754 {
14755     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14756 })";
14757 
14758     GLuint program = CompileProgram(kVS, kFS);
14759     EXPECT_EQ(0u, program);
14760 }
14761 
14762 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)14763 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
14764 {
14765     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14766 
14767     constexpr char kVS[] = R"(#version 310 es
14768 #extension GL_EXT_shader_io_blocks : require
14769 in highp vec4 position;
14770 struct S { vec4 a; vec4 b[2]; vec4 c; };
14771 out VSBlock { S s; } blockOut1;
14772 void main()
14773 {
14774     blockOut1.s.c = vec4(0);
14775     blockOut1.s.b[0] = vec4(0);
14776     blockOut1.s.b[1] = vec4(0);
14777     gl_Position = position;
14778 })";
14779 
14780     constexpr char kFS[] = R"(#version 310 es
14781 #extension GL_EXT_shader_io_blocks : require
14782 precision mediump float;
14783 layout(location = 0) out mediump vec4 color;
14784 struct S { vec4 a; vec4 b[2]; };
14785 in VSBlock { S s; } blockIn1;
14786 void main()
14787 {
14788     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14789 })";
14790 
14791     GLuint program = CompileProgram(kVS, kFS);
14792     EXPECT_EQ(0u, program);
14793 }
14794 
14795 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)14796 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
14797 {
14798     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14799 
14800     constexpr char kVS[] = R"(#version 310 es
14801 #extension GL_EXT_shader_io_blocks : require
14802 in highp vec4 position;
14803 struct S1 { vec4 c; vec4 b[2]; };
14804 struct S2 { S1 s; };
14805 struct S3 { S2 s; };
14806 out VSBlock { S3 s; } blockOut1;
14807 void main()
14808 {
14809     blockOut1.s.s.s.c = vec4(0);
14810     blockOut1.s.s.s.b[0] = vec4(0);
14811     blockOut1.s.s.s.b[1] = vec4(0);
14812     gl_Position = position;
14813 })";
14814 
14815     constexpr char kFS[] = R"(#version 310 es
14816 #extension GL_EXT_shader_io_blocks : require
14817 precision mediump float;
14818 layout(location = 0) out mediump vec4 color;
14819 struct S1 { vec4 a; vec4 b[2]; };
14820 struct S2 { S1 s; };
14821 struct S3 { S2 s; };
14822 in VSBlock { S3 s; } blockIn1;
14823 void main()
14824 {
14825     color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
14826 })";
14827 
14828     GLuint program = CompileProgram(kVS, kFS);
14829     EXPECT_EQ(0u, program);
14830 }
14831 
14832 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)14833 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
14834 {
14835     constexpr char kVS[] = R"(#version 310 es
14836 precision highp float;
14837 
14838 struct S
14839 {
14840     mat4 a;
14841     mat4 b;
14842 };
14843 
14844 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
14845 
14846 void main() {
14847     S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
14848 
14849     gl_Position = vec4(s3[1].a[0].x, s2[0][2].b[1].y, s4[1][0].a[2].z, s6[0].b[3].w);
14850 })";
14851 
14852     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14853 
14854     const char *sourceArray[1] = {kVS};
14855     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
14856     glShaderSource(shader, 1, sourceArray, lengths);
14857     glCompileShader(shader);
14858 
14859     GLint compileResult;
14860     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14861     EXPECT_NE(compileResult, 0);
14862 }
14863 
14864 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)14865 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
14866 {
14867     constexpr char kVS[] = R"(#version 310 es
14868 precision highp float;
14869 
14870 struct S
14871 {
14872     mat4 a;
14873     mat4 b;
14874 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
14875 
14876 void main() {
14877     struct T
14878     {
14879         mat4 a;
14880         mat4 b;
14881     } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
14882 
14883     float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
14884 
14885     gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
14886 })";
14887 
14888     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14889 
14890     const char *sourceArray[1] = {kVS};
14891     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
14892     glShaderSource(shader, 1, sourceArray, lengths);
14893     glCompileShader(shader);
14894 
14895     GLint compileResult;
14896     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14897     EXPECT_NE(compileResult, 0);
14898 }
14899 
14900 // Test that separating declarators works with structs that are simultaneously defined and that are
14901 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)14902 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
14903 {
14904     constexpr char kVS[] = R"(#version 310 es
14905 precision highp float;
14906 
14907 struct
14908 {
14909     mat4 a;
14910     mat4 b;
14911 } s1, s2[2][3], s3[2];
14912 
14913 void main() {
14914     struct
14915     {
14916         mat4 a;
14917         mat4 b;
14918     } s4[2][3], s5, s6[2], s7 = s5;
14919 
14920     float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
14921 
14922     gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
14923 })";
14924 
14925     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14926 
14927     const char *sourceArray[1] = {kVS};
14928     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
14929     glShaderSource(shader, 1, sourceArray, lengths);
14930     glCompileShader(shader);
14931 
14932     GLint compileResult;
14933     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14934     EXPECT_NE(compileResult, 0);
14935 }
14936 
14937 // Regression test for transformation bug which separates struct declarations from uniform
14938 // declarations.  The bug was that the uniform variable usage in the initializer of a new
14939 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)14940 TEST_P(GLSLTest, UniformStructBug)
14941 {
14942     constexpr char kVS[] = R"(precision highp float;
14943 
14944 uniform struct Global
14945 {
14946     float x;
14947 } u_global;
14948 
14949 void main() {
14950   float y = u_global.x;
14951 
14952   gl_Position = vec4(y);
14953 })";
14954 
14955     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14956 
14957     const char *sourceArray[1] = {kVS};
14958     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
14959     glShaderSource(shader, 1, sourceArray, lengths);
14960     glCompileShader(shader);
14961 
14962     GLint compileResult;
14963     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14964     EXPECT_NE(compileResult, 0);
14965 }
14966 
14967 // Regression test for transformation bug which separates struct declarations from uniform
14968 // declarations.  The bug was that the arrayness of the declaration was not being applied to the
14969 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)14970 TEST_P(GLSLTest_ES31, UniformStructBug2)
14971 {
14972     constexpr char kVS[] = R"(#version 310 es
14973 precision highp float;
14974 
14975 uniform struct Global
14976 {
14977     float x;
14978 } u_global[2][3];
14979 
14980 void main() {
14981   float y = u_global[0][0].x;
14982 
14983   gl_Position = vec4(y);
14984 })";
14985 
14986     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14987 
14988     const char *sourceArray[1] = {kVS};
14989     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
14990     glShaderSource(shader, 1, sourceArray, lengths);
14991     glCompileShader(shader);
14992 
14993     GLint compileResult;
14994     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14995     EXPECT_NE(compileResult, 0);
14996 }
14997 
14998 // Regression test based on fuzzer issue resulting in an AST validation failure.  Struct definition
14999 // was not found in the tree.  Tests that struct declaration in function return value is visible to
15000 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)15001 TEST_P(GLSLTest, MissingStructDeclarationBug)
15002 {
15003     constexpr char kVS[] = R"(
15004 struct S
15005 {
15006     vec4 i;
15007 } p();
15008 void main()
15009 {
15010     S s;
15011 })";
15012 
15013     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15014     EXPECT_NE(0u, shader);
15015     glDeleteShader(shader);
15016 }
15017 
15018 // Regression test based on fuzzer issue resulting in an AST validation failure.  Struct definition
15019 // was not found in the tree.  Tests that struct declaration in function return value is visible to
15020 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)15021 TEST_P(GLSLTest, MissingStructDeclarationBug2)
15022 {
15023     constexpr char kVS[] = R"(
15024 struct T
15025 {
15026     vec4 I;
15027 } p();
15028 struct
15029 {
15030     T c;
15031 };
15032 void main()
15033 {
15034 })";
15035 
15036     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15037     EXPECT_NE(0u, shader);
15038     glDeleteShader(shader);
15039 }
15040 
15041 // Regression test for bug in HLSL code generation where the for loop init expression was expected
15042 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)15043 TEST_P(GLSLTest, HandleExcessiveLoopBug)
15044 {
15045     constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
15046 
15047     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15048     EXPECT_NE(0u, shader);
15049     glDeleteShader(shader);
15050 }
15051 
15052 // Regression test for a validation bug in the translator where func(void, int) was accepted even
15053 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)15054 TEST_P(GLSLTest, NoParameterAfterVoid)
15055 {
15056     constexpr char kVS[] = R"(void f(void, int a){}
15057 void main(){f(1);})";
15058 
15059     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15060     EXPECT_EQ(0u, shader);
15061     glDeleteShader(shader);
15062 }
15063 
15064 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)15065 TEST_P(GLSLTest, NoParameterAfterVoid2)
15066 {
15067     constexpr char kVS[] = R"(void f(void, void){}
15068 void main(){f();})";
15069 
15070     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15071     EXPECT_EQ(0u, shader);
15072     glDeleteShader(shader);
15073 }
15074 
15075 // Test that providing more components to a matrix constructor than necessary works.  Based on a
15076 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)15077 TEST_P(GLSLTest, MatrixConstructor)
15078 {
15079     constexpr char kVS[] = R"(attribute vec4 aPosition;
15080 varying vec4 vColor;
15081 void main()
15082 {
15083     gl_Position = aPosition;
15084     vec4 color = vec4(aPosition.xy, 0, 1);
15085     mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
15086     vColor = m4[0];
15087 })";
15088 
15089     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15090     EXPECT_NE(0u, shader);
15091     glDeleteShader(shader);
15092 }
15093 
15094 // Test constructors without precision
TEST_P(GLSLTest,ConstructFromBoolVector)15095 TEST_P(GLSLTest, ConstructFromBoolVector)
15096 {
15097     constexpr char kFS[] = R"(precision mediump float;
15098 uniform float u;
15099 void main()
15100 {
15101     mat4 m = mat4(u);
15102     mat2(0, bvec3(m));
15103     gl_FragColor = vec4(m);
15104 })";
15105 
15106     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15107     EXPECT_NE(0u, shader);
15108     glDeleteShader(shader);
15109 }
15110 
15111 // Test constructing vector from matrix
TEST_P(GLSLTest,VectorConstructorFromMatrix)15112 TEST_P(GLSLTest, VectorConstructorFromMatrix)
15113 {
15114     constexpr char kFS[] = R"(precision mediump float;
15115 uniform mat2 umat2;
15116 void main()
15117 {
15118     gl_FragColor = vec4(umat2);
15119 })";
15120 
15121     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15122     EXPECT_NE(0u, shader);
15123     glDeleteShader(shader);
15124 }
15125 
15126 // Test constructing matrix from vectors
TEST_P(GLSLTest,MatrixConstructorFromVectors)15127 TEST_P(GLSLTest, MatrixConstructorFromVectors)
15128 {
15129     constexpr char kFS[] = R"(precision mediump float;
15130 uniform vec2 uvec2;
15131 void main()
15132 {
15133     mat2 m = mat2(uvec2, uvec2.yx);
15134     gl_FragColor = vec4(m * uvec2, uvec2);
15135 })";
15136 
15137     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15138     glUseProgram(program);
15139 
15140     GLint uloc = glGetUniformLocation(program, "uvec2");
15141     ASSERT_NE(uloc, -1);
15142     glUniform2f(uloc, 0.5, 0.8);
15143 
15144     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15145     EXPECT_GL_NO_ERROR();
15146 
15147     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(227, 204, 127, 204), 1);
15148 }
15149 
15150 // Test that constructing vector and matrix inside multiple declarations preserves the correct order
15151 // of operations.
TEST_P(GLSLTest,ConstructorinSequenceOperator)15152 TEST_P(GLSLTest, ConstructorinSequenceOperator)
15153 {
15154     constexpr char kFS[] = R"(precision mediump float;
15155 uniform vec2 u;
15156 void main()
15157 {
15158     vec2 v = u;
15159     mat2 m = (v[0] += 1.0, mat2(v, v[1], -v[0]));
15160     gl_FragColor = vec4(m[0], m[1]);
15161 })";
15162 
15163     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15164     glUseProgram(program);
15165 
15166     GLint uloc = glGetUniformLocation(program, "u");
15167     ASSERT_NE(uloc, -1);
15168     glUniform2f(uloc, -0.5, 1.0);
15169 
15170     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15171     EXPECT_GL_NO_ERROR();
15172 
15173     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 255, 255, 0), 1);
15174 }
15175 
15176 // Test that constructing vectors inside multiple declarations preserves the correct order
15177 // of operations.
TEST_P(GLSLTest,VectorConstructorsInMultiDeclaration)15178 TEST_P(GLSLTest, VectorConstructorsInMultiDeclaration)
15179 {
15180     constexpr char kFS[] = R"(precision mediump float;
15181 uniform vec2 u;
15182 void main()
15183 {
15184     vec2 v = vec2(u[0]),
15185          w = mat2(v, v) * u;
15186     gl_FragColor = vec4(v, w);
15187 })";
15188 
15189     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15190     glUseProgram(program);
15191 
15192     GLint uloc = glGetUniformLocation(program, "u");
15193     ASSERT_NE(uloc, -1);
15194     glUniform2f(uloc, 0.5, 0.8);
15195 
15196     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15197     EXPECT_GL_NO_ERROR();
15198 
15199     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 166, 166), 1);
15200 }
15201 
15202 // Test complex constructor usage.
TEST_P(GLSLTest_ES3,ComplexConstructor)15203 TEST_P(GLSLTest_ES3, ComplexConstructor)
15204 {
15205     constexpr char kFS[] = R"(#version 300 es
15206 precision mediump float;
15207 uniform vec2 u; // = vec2(0.5, 0.8)
15208 uniform vec2 v; // = vec2(-0.2, 1.0)
15209 
15210 out vec4 color;
15211 
15212 bool f(mat2 m)
15213 {
15214     return m[0][0] > 0.;
15215 }
15216 
15217 bool isEqual(float a, float b)
15218 {
15219     return abs(a - b) < 0.01;
15220 }
15221 
15222 void main()
15223 {
15224     int shouldRemainZero = 0;
15225 
15226     // Test side effects inside constructor args after short-circuit
15227     if (u.x < 0. && f(mat2(shouldRemainZero += 1, u, v)))
15228     {
15229         shouldRemainZero += 2;
15230     }
15231 
15232     int shouldBecomeFive = 0;
15233 
15234     // Test directly nested constructors
15235     mat4x3 m = mat4x3(mat2(shouldBecomeFive += 5, v, u));
15236 
15237     // Test indirectly nested constructors
15238     mat2 m2 = mat2(f(mat2(u, v)), f(mat2(v, u)), f(mat2(f(mat2(1.)))), -1.);
15239 
15240     // Verify
15241     bool sideEffectsOk = shouldRemainZero == 0 && shouldBecomeFive == 5;
15242 
15243     bool mOk = isEqual(m[0][0], 5.) && isEqual(m[0][1], -0.2) && isEqual(m[0][2], 0.) &&
15244                isEqual(m[1][0], 1.) && isEqual(m[1][1], 0.5) && isEqual(m[1][2], 0.) &&
15245                isEqual(m[2][0], 0.) && isEqual(m[2][1], 0.) && isEqual(m[2][2], 1.) &&
15246                isEqual(m[3][0], 0.) && isEqual(m[3][1], 0.) && isEqual(m[3][2], 0.);
15247 
15248     bool m2Ok = isEqual(m2[0][0], 1.) && isEqual(m2[0][1], 0.) &&
15249                isEqual(m2[1][0], 1.) && isEqual(m2[1][1], -1.);
15250 
15251     color = vec4(sideEffectsOk ? 1 : 0, mOk ? 1 : 0, m2Ok ? 1 : 0, 1);
15252 })";
15253 
15254     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15255     glUseProgram(program);
15256 
15257     GLint uloc = glGetUniformLocation(program, "u");
15258     GLint vloc = glGetUniformLocation(program, "v");
15259     ASSERT_NE(uloc, -1);
15260     ASSERT_NE(vloc, -1);
15261     glUniform2f(uloc, 0.5, 0.8);
15262     glUniform2f(vloc, -0.2, 1.0);
15263 
15264     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15265     EXPECT_GL_NO_ERROR();
15266 
15267     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15268 }
15269 
15270 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)15271 TEST_P(GLSLTest_ES3, ScalarConstructor)
15272 {
15273     constexpr char kFS[] = R"(#version 300 es
15274 precision mediump float;
15275 uniform vec4 u;
15276 out vec4 color;
15277 void main()
15278 {
15279     float f1 = float(u);
15280     mat3 m = mat3(u, u, u);
15281     int i = int(m);
15282     color = vec4(f1, float(i), 0, 1);
15283 })";
15284 
15285     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15286     glUseProgram(program);
15287 
15288     GLint uloc = glGetUniformLocation(program, "u");
15289     ASSERT_NE(uloc, -1);
15290     glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
15291 
15292     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15293     EXPECT_GL_NO_ERROR();
15294 
15295     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
15296 }
15297 
15298 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)15299 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
15300 {
15301     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
15302 
15303     constexpr char kVS[] = R"(#version 300 es
15304 #extension GL_EXT_shader_non_constant_global_initializers : require
15305 uniform vec4 u;
15306 out vec4 color;
15307 
15308 vec4 global1 = u;
15309 vec4 global2 = u + vec4(1);
15310 vec4 global3 = global1 * global2;
15311 void main()
15312 {
15313     color = global3;
15314 })";
15315 
15316     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15317     EXPECT_NE(0u, shader);
15318     glDeleteShader(shader);
15319 }
15320 
15321 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)15322 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
15323 {
15324     constexpr char kFS[] = R"(#version 300 es
15325 precision highp float;
15326 out vec4 color;
15327 
15328 struct T
15329 {
15330     float f;
15331 };
15332 
15333 struct S
15334 {
15335     vec4 v;
15336     mat3x4 m[2];
15337     T t;
15338 };
15339 
15340 S s = S(
15341         vec4(0, 1, 2, 3),
15342         mat3x4[2](
15343                   mat3x4(
15344                          vec4(4, 5, 6, 7),
15345                          vec4(8, 9, 10, 11),
15346                          vec4(12, 13, 14, 15)
15347                   ),
15348                   mat3x4(
15349                          vec4(16, 17, 18, 19),
15350                          vec4(20, 21, 22, 23),
15351                          vec4(24, 25, 26, 27)
15352                   )
15353         ),
15354         T(28.0)
15355        );
15356 
15357 void main()
15358 {
15359     vec4 result = vec4(0, 1, 0, 1);
15360 
15361     if (s.v != vec4(0, 1, 2, 3))
15362         result = vec4(1, 0, 0, 0);
15363 
15364     for (int index = 0; index < 2; ++index)
15365     {
15366         for (int column = 0; column < 3; ++column)
15367         {
15368             int expect = index * 12 + column * 4 + 4;
15369             if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
15370                 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
15371         }
15372     }
15373 
15374     if (s.t.f != 28.0)
15375         result = vec4(0, 0, 1, 0);
15376 
15377     color = result;
15378 })";
15379 
15380     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15381 
15382     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15383     EXPECT_GL_NO_ERROR();
15384 
15385     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15386 }
15387 
15388 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)15389 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
15390 {
15391     constexpr char kFS[] = R"(#version 310 es
15392 precision highp float;
15393 precision highp int;
15394 
15395 out vec4 color;
15396 
15397 uniform float f;    // = 3.41
15398 uniform uvec4 u1;   // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
15399 uniform uvec4 u2;   // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
15400 
15401 struct S
15402 {
15403     float fvalue;
15404     int ivalues[2];
15405     uvec4 uvalues[3];
15406 };
15407 
15408 struct T
15409 {
15410     S s[2];
15411 };
15412 
15413 void main()
15414 {
15415     float integer;
15416     float fraction = modf(f, integer);
15417 
15418     T t;
15419 
15420     t.s[0].fvalue     = frexp(f, t.s[0].ivalues[0]);
15421     float significand = t.s[0].fvalue;
15422     int exponent      = t.s[0].ivalues[0];
15423 
15424     t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
15425     uvec4 addResult   = t.s[0].uvalues[0];
15426     uvec4 addCarry    = t.s[0].uvalues[1].yxwz;
15427 
15428     t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
15429     uvec2 subResult      = t.s[0].uvalues[2].wx;
15430     uvec2 subBorrow      = t.s[1].uvalues[0].wx;
15431 
15432     umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
15433     uvec4 mulMsb = t.s[1].uvalues[1];
15434     uvec4 mulLsb = t.s[1].uvalues[2];
15435 
15436     ivec2 imulMsb, imulLsb;
15437     imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
15438 
15439     bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
15440     bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
15441     bool addPassed =
15442         addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
15443         addCarry == uvec4(1, 0, 1, 0);
15444     bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
15445     bool mulPassed =
15446         mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
15447         mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
15448     bool imulPassed =
15449         imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
15450         imulLsb == ivec2(0x35068740, 0x822E97E0);
15451 
15452     color = vec4(modfPassed ? 1 : 0,
15453                  frexpPassed ? 1 : 0,
15454                  (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
15455                  (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
15456 })";
15457 
15458     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
15459     glUseProgram(program);
15460 
15461     GLint floc  = glGetUniformLocation(program, "f");
15462     GLint u1loc = glGetUniformLocation(program, "u1");
15463     GLint u2loc = glGetUniformLocation(program, "u2");
15464     ASSERT_NE(floc, -1);
15465     ASSERT_NE(u1loc, -1);
15466     ASSERT_NE(u2loc, -1);
15467     glUniform1f(floc, 3.41);
15468     glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
15469     glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
15470 
15471     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
15472     EXPECT_GL_NO_ERROR();
15473 
15474     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15475 }
15476 
15477 // Test that interpolateAt* work with swizzle.  This test is disabled as swizzled interpolants are
15478 // only allowed in desktop GLSL.
TEST_P(GLSLTest_ES31,InterpolateAtWithSwizzle)15479 TEST_P(GLSLTest_ES31, InterpolateAtWithSwizzle)
15480 {
15481     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
15482 
15483     constexpr char kVS[] = R"(#version 310 es
15484 
15485 out vec4 interpolant;
15486 
15487 void main()
15488 {
15489     // The following triangle is being drawn over the framebuffer.
15490     //
15491     //   (-1,3) |\
15492     //          |   \
15493     //          |      \
15494     //          |         \
15495     //          |            \
15496     //          +--------------+
15497     //          |              | \
15498     //          |              |    \
15499     //          | Framebuffer  |       \
15500     //          |              |          \
15501     //          |              |             \
15502     //  (-1,-1) +--------------+--------------- (3,-1)
15503     //
15504     // Interpolant is set such that interpolateAtCentroid would produce the desired value for
15505     // position == (0, 0), and interpolateAtOffset(0.5, -0.5) for position == (1,-1)
15506     if (gl_VertexID == 0)
15507     {
15508         gl_Position = vec4(-1, -1, 0, 1);
15509         interpolant = vec4(1.5, 0.5, 0, 0);
15510     }
15511     else if (gl_VertexID == 1)
15512     {
15513         gl_Position = vec4(3, -1, 0, 1);
15514         interpolant = vec4(0, 0, 1, 2);
15515     }
15516     else
15517     {
15518         gl_Position = vec4(-1, 3, 0, 1);
15519         interpolant = vec4(0, 1, -1, 2);
15520     }
15521 })";
15522 
15523     constexpr char kFS[] = R"(#version 310 es
15524 #extension GL_OES_shader_multisample_interpolation : require
15525 precision highp float;
15526 
15527 in vec4 interpolant;
15528 out vec4 color;
15529 
15530 void main()
15531 {
15532     // Should result in (0.75, 1.0)
15533     vec2 atCentroid = interpolateAtCentroid(interpolant.xw);
15534     // Selecting the bottom-right corner, this should result in (0.5, 0.25), but interpolateAtOffset
15535     // doesn't make guarantees regarding the range and granularity of the offset.  The interpolant
15536     // is given values such that the bottom-left/top-right diagonal is interpolated to a constant
15537     // value of (0, 0.5).  The top-left corner has the value (-0.5, 0.75).  We therefore make a
15538     // coarse test to make sure that atOffset.x > 0 and atOffset.y < 0.5, thus ensuring at least
15539     // that the offset is in the correct half of the pixel.
15540     vec2 atOffset = interpolateAtOffset(interpolant.zy, vec2(0.5, -0.5));
15541 
15542     color = vec4(atCentroid, atOffset.x > 0.0 ? 1 : 0, atOffset.y < 0.5 ? 1 : 0);
15543 })";
15544 
15545     GLRenderbuffer rbo;
15546     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
15547     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
15548 
15549     GLFramebuffer fbo;
15550     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15551     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
15552     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
15553 
15554     ANGLE_GL_PROGRAM(program, kVS, kFS);
15555     glUseProgram(program);
15556 
15557     glViewport(0, 0, 1, 1);
15558     glDrawArrays(GL_TRIANGLES, 0, 3);
15559     EXPECT_GL_NO_ERROR();
15560 
15561     EXPECT_PIXEL_NEAR(0, 0, 191, 255, 255, 255, 1);
15562 }
15563 
15564 class GLSLTestLoops : public GLSLTest
15565 {
15566   protected:
runTest(const char * fs)15567     void runTest(const char *fs)
15568     {
15569         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
15570 
15571         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15572         EXPECT_GL_NO_ERROR();
15573 
15574         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15575     }
15576 };
15577 
15578 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)15579 TEST_P(GLSLTestLoops, BasicFor)
15580 {
15581     constexpr char kFS[] = R"(#version 300 es
15582 precision mediump float;
15583 out vec4 color;
15584 
15585 void main()
15586 {
15587     int result = 0;
15588     for (int i = 0; i < 10; ++i)
15589         for (int j = 0; j < 8; ++j)
15590         {
15591             for (int k = 0; k < 2; ++k, ++j) ++result;
15592             for (int k = 0; k < 3; ++k)      ++result;
15593             for (int k = 0; k < 0; ++k)      ++result;
15594         }
15595 
15596     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15597 })";
15598 
15599     runTest(kFS);
15600 }
15601 
15602 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)15603 TEST_P(GLSLTestLoops, ForNoCondition)
15604 {
15605     constexpr char kFS[] = R"(#version 300 es
15606 precision mediump float;
15607 out vec4 color;
15608 
15609 void main()
15610 {
15611     int result = 0;
15612     for (int i = 0; i < 10; ++i)
15613         for (int j = 0; ; ++j)
15614         {
15615             for (int k = 0; k < 2; ++k, ++j) ++result;
15616             for (int k = 0; k < 3; ++k)      ++result;
15617             for (int k = 0; k < 0; ++k)      ++result;
15618 
15619             if (j >= 8)
15620                 break;
15621         }
15622 
15623     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15624 })";
15625 
15626     runTest(kFS);
15627 }
15628 
15629 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)15630 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
15631 {
15632     constexpr char kFS[] = R"(#version 300 es
15633 precision mediump float;
15634 out vec4 color;
15635 
15636 void main()
15637 {
15638     int result = 0;
15639     for (int i = 0; i < 10; ++i)
15640     {
15641         int j = 0;
15642         for (;;)
15643         {
15644             for (int k = 0; k < 2; ++k, ++j) ++result;
15645             for (int k = 0; k < 3; ++k)      ++result;
15646             for (int k = 0; k < 0; ++k)      ++result;
15647 
15648             if (j >= 8)
15649                 break;
15650             ++j;
15651         }
15652     }
15653 
15654     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15655 })";
15656 
15657     runTest(kFS);
15658 }
15659 
15660 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)15661 TEST_P(GLSLTestLoops, ForContinue)
15662 {
15663     constexpr char kFS[] = R"(#version 300 es
15664 precision mediump float;
15665 out vec4 color;
15666 
15667 void main()
15668 {
15669     int result = 0;
15670     for (int i = 0; i < 10; ++i)
15671         for (int j = 0; j < 8; ++j)
15672         {
15673             for (int k = 0; k < 2; ++k, ++j) ++result;
15674             for (int k = 0; k < 3; ++k)      ++result;
15675             if (i > 3)
15676                 continue;
15677             for (int k = 0; k < 0; ++k)      ++result;
15678         }
15679 
15680     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15681 })";
15682 
15683     runTest(kFS);
15684 }
15685 
15686 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)15687 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
15688 {
15689     constexpr char kFS[] = R"(#version 300 es
15690 precision mediump float;
15691 out vec4 color;
15692 
15693 void main()
15694 {
15695     int result = 0;
15696     for (int i = 0; i < 10; ++i)
15697         for (int j = 0; j < 8; ++j)
15698         {
15699             for (int k = 0; k < 2; ++k, ++j) ++result;
15700             for (int k = 0; k < 3; ++k)      ++result;
15701             for (int k = 0; k < 0; ++k)      ++result;
15702             continue;
15703         }
15704 
15705     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15706 })";
15707 
15708     runTest(kFS);
15709 }
15710 
15711 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)15712 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
15713 {
15714     constexpr char kFS[] = R"(#version 300 es
15715 precision mediump float;
15716 out vec4 color;
15717 
15718 void main()
15719 {
15720     int result = 0;
15721     for (int i = 0; i < 10; ++i)
15722         for (int j = 0; j < 8; ++j)
15723         {
15724             for (int k = 0; k < 2; ++k, ++j) ++result;
15725             for (int k = 0; k < 3; ++k)      ++result;
15726             for (int k = 0; k < 0; ++k)      ++result;
15727             break;
15728         }
15729 
15730     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15731 })";
15732 
15733     runTest(kFS);
15734 }
15735 
15736 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)15737 TEST_P(GLSLTestLoops, ForBreakContinue)
15738 {
15739     constexpr char kFS[] = R"(#version 300 es
15740 precision mediump float;
15741 out vec4 color;
15742 
15743 void main()
15744 {
15745     int result = 0;
15746     for (int i = 0; i < 10; ++i)
15747         for (int j = 0; j < 8; ++j)
15748         {
15749             if (j < 2) continue;
15750             if (j > 6) break;
15751             if (i < 3) continue;
15752             if (i > 8) break;
15753             ++result;
15754         }
15755 
15756     color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15757 })";
15758 
15759     runTest(kFS);
15760 }
15761 
15762 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)15763 TEST_P(GLSLTestLoops, BasicWhile)
15764 {
15765     constexpr char kFS[] = R"(#version 300 es
15766 precision mediump float;
15767 out vec4 color;
15768 
15769 void main()
15770 {
15771     int result = 0;
15772     int i = 0;
15773     while (i < 10)
15774     {
15775         int j = 0;
15776         while (j < 8)
15777         {
15778             int k = 0;
15779             while (k < 2) { ++result; ++k; ++j; }
15780             while (k < 5) { ++result; ++k; }
15781             while (k < 4) { ++result; }
15782             ++j;
15783         }
15784         ++i;
15785     }
15786 
15787     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15788 })";
15789 
15790     runTest(kFS);
15791 }
15792 
15793 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)15794 TEST_P(GLSLTestLoops, WhileContinue)
15795 {
15796     constexpr char kFS[] = R"(#version 300 es
15797 precision mediump float;
15798 out vec4 color;
15799 
15800 void main()
15801 {
15802     int result = 0;
15803     int i = 0;
15804     while (i < 10)
15805     {
15806         int j = 0;
15807         while (j < 8)
15808         {
15809             int k = 0;
15810             while (k < 2) { ++result; ++k; ++j; }
15811             while (k < 5) { ++result; ++k; }
15812             if (i > 3)
15813             {
15814                 ++j;
15815                 continue;
15816             }
15817             while (k < 4) { ++result; }
15818             ++j;
15819         }
15820         ++i;
15821     }
15822 
15823     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15824 })";
15825 
15826     runTest(kFS);
15827 }
15828 
15829 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)15830 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
15831 {
15832     constexpr char kFS[] = R"(#version 300 es
15833 precision mediump float;
15834 out vec4 color;
15835 
15836 void main()
15837 {
15838     int result = 0;
15839     int i = 0;
15840     while (i < 10)
15841     {
15842         int j = 0;
15843         while (j < 8)
15844         {
15845             int k = 0;
15846             while (k < 2) { ++result; ++k; ++j; }
15847             while (k < 5) { ++result; ++k; }
15848             while (k < 4) { ++result; }
15849             ++j;
15850             continue;
15851         }
15852         ++i;
15853     }
15854 
15855     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15856 })";
15857 
15858     runTest(kFS);
15859 }
15860 
15861 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)15862 TEST_P(GLSLTestLoops, WhileBreak)
15863 {
15864     constexpr char kFS[] = R"(#version 300 es
15865 precision mediump float;
15866 out vec4 color;
15867 
15868 void main()
15869 {
15870     int result = 0;
15871     int i = 0;
15872     while (i < 10)
15873     {
15874         int j = 0;
15875         while (true)
15876         {
15877             int k = 0;
15878             while (k < 2) { ++result; ++k; ++j; }
15879             while (k < 5) { ++result; ++k; }
15880             while (k < 4) { ++result; }
15881             ++j;
15882             if (j >= 8)
15883                 break;
15884         }
15885         ++i;
15886     }
15887 
15888     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15889 })";
15890 
15891     runTest(kFS);
15892 }
15893 
15894 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)15895 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
15896 {
15897     constexpr char kFS[] = R"(#version 300 es
15898 precision mediump float;
15899 out vec4 color;
15900 
15901 void main()
15902 {
15903     int result = 0;
15904     int i = 0;
15905     while (i < 10)
15906     {
15907         int j = 0;
15908         while (j < 8)
15909         {
15910             int k = 0;
15911             while (k < 2) { ++result; ++k; ++j; }
15912             while (k < 5) { ++result; ++k; }
15913             while (k < 4) { ++result; }
15914             ++j;
15915             break;
15916         }
15917         ++i;
15918     }
15919 
15920     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15921 })";
15922 
15923     runTest(kFS);
15924 }
15925 
15926 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)15927 TEST_P(GLSLTestLoops, BasicDoWhile)
15928 {
15929     constexpr char kFS[] = R"(#version 300 es
15930 precision mediump float;
15931 out vec4 color;
15932 
15933 void main()
15934 {
15935     int result = 0;
15936     int i = 0;
15937     do
15938     {
15939         int j = 0;
15940         do
15941         {
15942             int k = 0;
15943             do { ++result; ++k; ++j; } while (k < 2);
15944             do { ++result; ++k;      } while (k < 5);
15945             do { ++result;           } while (k < 3);
15946             ++j;
15947         } while (j < 8);
15948         ++i;
15949     } while (i < 10);
15950 
15951     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15952 })";
15953 
15954     runTest(kFS);
15955 }
15956 
15957 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)15958 TEST_P(GLSLTestLoops, DoWhileContinue)
15959 {
15960     constexpr char kFS[] = R"(#version 300 es
15961 precision mediump float;
15962 out vec4 color;
15963 
15964 void main()
15965 {
15966     int result = 0;
15967     int i = 0;
15968     do
15969     {
15970         int j = 0;
15971         do
15972         {
15973             int k = 0;
15974             do { ++result; ++k; ++j; } while (k < 2);
15975             if (i > 3)
15976             {
15977                 ++j;
15978                 continue;
15979             }
15980             do { ++result; ++k;      } while (k < 5);
15981             do { ++result;           } while (k < 3);
15982             ++j;
15983         } while (j < 8);
15984         ++i;
15985     } while (i < 10);
15986 
15987     color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15988 })";
15989 
15990     runTest(kFS);
15991 }
15992 
15993 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)15994 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
15995 {
15996     constexpr char kFS[] = R"(#version 300 es
15997 precision mediump float;
15998 out vec4 color;
15999 
16000 void main()
16001 {
16002     int result = 0;
16003     int i = 0;
16004     do
16005     {
16006         int j = 0;
16007         do
16008         {
16009             int k = 0;
16010             do { ++result; ++k; ++j; continue; } while (k < 2);
16011             do { ++result; ++k;      continue; } while (k < 5);
16012             do { ++result;           continue; } while (k < 3);
16013             ++j;
16014         } while (j < 8);
16015         ++i;
16016     } while (i < 10);
16017 
16018     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16019 })";
16020 
16021     runTest(kFS);
16022 }
16023 
16024 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)16025 TEST_P(GLSLTestLoops, DoWhileBreak)
16026 {
16027     constexpr char kFS[] = R"(#version 300 es
16028 precision mediump float;
16029 out vec4 color;
16030 
16031 void main()
16032 {
16033     int result = 0;
16034     int i = 0;
16035     do
16036     {
16037         int j = 0;
16038         do
16039         {
16040             int k = 0;
16041             do { ++result; ++k; ++j; } while (k < 2);
16042             do { ++result; ++k;      } while (k < 5);
16043             do { ++result;           } while (k < 3);
16044             ++j;
16045             if (j >= 8)
16046                 break;
16047         } while (true);
16048         ++i;
16049     } while (i < 10);
16050 
16051     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16052 })";
16053 
16054     runTest(kFS);
16055 }
16056 
16057 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)16058 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
16059 {
16060     constexpr char kFS[] = R"(#version 300 es
16061 precision mediump float;
16062 out vec4 color;
16063 
16064 void main()
16065 {
16066     int result = 0;
16067     int i = 0;
16068     do
16069     {
16070         int j = 0;
16071         do
16072         {
16073             int k = 0;
16074             do { ++result; ++k; ++j; break; } while (k < 2);
16075             do { ++result; ++k;      break; } while (k < 5);
16076             do { ++result;           break; } while (k < 3);
16077             ++j;
16078         } while (j < 8);
16079         ++i;
16080     } while (i < 10);
16081 
16082     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16083 })";
16084 
16085     runTest(kFS);
16086 }
16087 
16088 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)16089 TEST_P(GLSLTestLoops, ForContinueInSwitch)
16090 {
16091     constexpr char kFS[] = R"(#version 300 es
16092 precision mediump float;
16093 out vec4 color;
16094 
16095 void main()
16096 {
16097     int result = 0;
16098     for (int i = 0; i < 10; ++i)
16099         for (int j = 0; j < 8; ++j)
16100         {
16101             switch (j)
16102             {
16103                 case 2:
16104                 case 3:
16105                 case 4:
16106                     ++result;
16107                     // fallthrough
16108                 case 5:
16109                 case 6:
16110                     ++result;
16111                     break;
16112                 default:
16113                     continue;
16114             }
16115         }
16116 
16117     color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16118 })";
16119 
16120     runTest(kFS);
16121 }
16122 
16123 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)16124 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
16125 {
16126     constexpr char kFS[] = R"(#version 300 es
16127 precision mediump float;
16128 out vec4 color;
16129 
16130 void main()
16131 {
16132     int result = 0;
16133     int i = 0;
16134     while (i < 10)
16135     {
16136         int j = 0;
16137         while (j < 8)
16138         {
16139             switch (j)
16140             {
16141                 case 2:
16142                 default:
16143                 case 3:
16144                 case 4:
16145                     ++j;
16146                     ++result;
16147                     continue;
16148                 case 0:
16149                 case 1:
16150                 case 7:
16151                     break;
16152             }
16153             ++j;
16154         }
16155         ++i;
16156     }
16157 
16158     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16159 })";
16160 
16161     runTest(kFS);
16162 }
16163 
16164 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)16165 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
16166 {
16167     constexpr char kFS[] = R"(#version 300 es
16168 precision mediump float;
16169 out vec4 color;
16170 
16171 void main()
16172 {
16173     int result = 0;
16174     int i = 0;
16175     do
16176     {
16177         int j = 0;
16178         do
16179         {
16180             switch (j)
16181             {
16182                 case 0:
16183                     ++j;
16184                     continue;
16185                 default:
16186                 case 2:
16187                 case 3:
16188                 case 4:
16189                     ++j;
16190                     ++result;
16191                     if (j >= 2 && j <= 6)
16192                         break;
16193                     else
16194                         continue;
16195             }
16196             ++result;
16197         } while (j < 8);
16198         ++i;
16199     } while (i < 10);
16200 
16201     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16202 })";
16203 
16204     runTest(kFS);
16205 }
16206 
16207 // Test prune-able loop with side effect in statements.
TEST_P(GLSLTestLoops,SideEffectsInPrunableFor)16208 TEST_P(GLSLTestLoops, SideEffectsInPrunableFor)
16209 {
16210     constexpr char kFS[] = R"(#version 300 es
16211 precision mediump float;
16212 out vec4 color;
16213 
16214 void main()
16215 {
16216     int a = 4;
16217     float b = 0.;
16218     for (int c = a++; (b += float(c) / 8.) < 0.; b += 0.3)
16219     {
16220         if (2 == 0);
16221     }
16222     int c = a - 4;
16223 
16224     // Expect c to be 1 and b to be 0.5
16225     color = c == 1 && abs(b - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16226 })";
16227 
16228     runTest(kFS);
16229 }
16230 
16231 // Test that precision is retained for constants (which are constant folded).  Adapted from a WebGL
16232 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)16233 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
16234 {
16235     constexpr char kFS[] = R"(
16236 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
16237 uniform mediump float uTest;
16238 void main() {
16239     // exact representation of 4096.5 requires 13 bits of relative precision.
16240     const highp float c = 4096.5;
16241     mediump float a = 0.0;
16242     // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
16243     // Thus fract should also be evaluated at highp.
16244     // See OpenGL ES Shading Language spec section 4.5.2.
16245     // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
16246     // (exceptions for operation precision are allowed for a small number of computationally
16247     // intensive built-in functions, but it is reasonable to think that fract is not one of those).
16248     // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
16249     // or at IEEE half float precision, the result is 0.0.
16250     a = fract(c + uTest);
16251     // Multiply by 2.0 to make the color green.
16252     gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
16253 })";
16254 
16255     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
16256 
16257     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16258     EXPECT_GL_NO_ERROR();
16259 
16260     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16261 }
16262 
16263 // Test that vector and matrix scalarization does not affect rendering.
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)16264 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
16265 {
16266     constexpr char kFS[] = R"(
16267 precision mediump float;
16268 
16269 varying vec2 v_texCoord;
16270 
16271 float a = 0.;
16272 #define A 0.
16273 
16274 #define r(a)    mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
16275 vec2 c;
16276 #define f(U,a)  ( c = (U) * r(a) , sin(10.*c.x) )
16277 
16278 void main() {
16279     vec2 U = v_texCoord;
16280 
16281     gl_FragColor = U.y > .5
16282         ? vec4( f(U,a) , f(U*4.,a) , 0,1.0)   // top
16283         : vec4( f(U,A) , f(U*4.,A) , 0,1.0);  // bottom
16284 }
16285 
16286 )";
16287 
16288     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
16289     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16290 
16291     // Make sure we rendered something.
16292     EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
16293 
16294     // Comapare one line in top half to one line in bottom half.
16295     int compareWidth  = getWindowWidth();
16296     int compareHeight = getWindowHeight() / 4;
16297 
16298     ASSERT_GE(compareWidth, 2);
16299     ASSERT_GE(compareHeight, 2);
16300 
16301     GLubyte pixelValue[4];
16302     constexpr int tolerance = 12;
16303 
16304     for (int x = 0; x < compareWidth; ++x)
16305     {
16306         glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
16307         EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
16308                           pixelValue[2], pixelValue[3], tolerance);
16309     }
16310     EXPECT_GL_NO_ERROR();
16311 }
16312 
16313 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)16314 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
16315 {
16316     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16317 
16318     const char kVS[] = R"(#version 310 es
16319 #extension GL_EXT_shader_io_blocks : require
16320 in vec4 position;
16321 out BlockType {
16322     vec4 blockMember;
16323 } BlockTypeOut;
16324 
16325 void main()
16326 {
16327     gl_Position = position;
16328 })";
16329 
16330     const char kFS[] = R"(#version 310 es
16331 #extension GL_EXT_shader_io_blocks : require
16332 precision mediump float;
16333 out vec4 colorOut;
16334 in BlockType {
16335     vec4 blockMember;
16336 } BlockTypeOut;
16337 
16338 void main()
16339 {
16340     if (BlockTypeOut.blockMember == vec4(0)) {
16341         colorOut = vec4(0, 1, 0, 1);
16342     } else {
16343         colorOut = vec4(1, 0, 0, 1);
16344     }
16345 })";
16346 
16347     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16348     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16349     ASSERT_GL_NO_ERROR();
16350     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16351 }
16352 
16353 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)16354 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
16355 {
16356     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16357 
16358     const char kVS[] = R"(#version 310 es
16359 #extension GL_EXT_shader_io_blocks : require
16360 in vec4 position;
16361 out BlockType {
16362     vec4 blockMember;
16363 };
16364 
16365 void main()
16366 {
16367     gl_Position = position;
16368 })";
16369 
16370     const char kFS[] = R"(#version 310 es
16371 #extension GL_EXT_shader_io_blocks : require
16372 precision mediump float;
16373 out vec4 colorOut;
16374 in BlockType {
16375     vec4 blockMember;
16376 };
16377 
16378 void main()
16379 {
16380     if (blockMember == vec4(0)) {
16381         colorOut = vec4(0, 1, 0, 1);
16382     } else {
16383         colorOut = vec4(1, 0, 0, 1);
16384     }
16385 })";
16386 
16387     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16388     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16389     ASSERT_GL_NO_ERROR();
16390     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16391 }
16392 
16393 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)16394 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
16395 {
16396     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16397 
16398     const char kVS[] = R"(#version 310 es
16399 #extension GL_EXT_shader_io_blocks : require
16400 in vec4 position;
16401 out BlockType {
16402     vec4 blockMember[2];
16403 } BlockTypeOut;
16404 
16405 void main()
16406 {
16407     gl_Position = position;
16408 })";
16409 
16410     const char kFS[] = R"(#version 310 es
16411 #extension GL_EXT_shader_io_blocks : require
16412 precision mediump float;
16413 out vec4 colorOut;
16414 in BlockType {
16415     vec4 blockMember[2];
16416 } BlockTypeOut;
16417 
16418 void main()
16419 {
16420     if (BlockTypeOut.blockMember[0] == vec4(0) &&
16421         BlockTypeOut.blockMember[1] == vec4(0)) {
16422         colorOut = vec4(0, 1, 0, 1);
16423     } else {
16424         colorOut = vec4(1, 0, 0, 1);
16425     }
16426 })";
16427 
16428     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16429     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16430     ASSERT_GL_NO_ERROR();
16431     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16432 }
16433 
16434 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)16435 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
16436 {
16437     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16438 
16439     const char kVS[] = R"(#version 310 es
16440 #extension GL_EXT_shader_io_blocks : require
16441 in vec4 position;
16442 out BlockType {
16443     vec4 blockMember;
16444 } BlockTypeOut[2];
16445 
16446 void main()
16447 {
16448     gl_Position = position;
16449 })";
16450 
16451     const char kFS[] = R"(#version 310 es
16452 #extension GL_EXT_shader_io_blocks : require
16453 precision mediump float;
16454 out vec4 colorOut;
16455 in BlockType {
16456     vec4 blockMember;
16457 } BlockTypeOut[2];
16458 
16459 void main()
16460 {
16461     if (BlockTypeOut[0].blockMember == vec4(0) &&
16462         BlockTypeOut[1].blockMember == vec4(0)) {
16463         colorOut = vec4(0, 1, 0, 1);
16464     } else {
16465         colorOut = vec4(1, 0, 0, 1);
16466     }
16467 })";
16468 
16469     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16470     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16471     ASSERT_GL_NO_ERROR();
16472     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16473 }
16474 
16475 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)16476 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
16477 {
16478     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16479 
16480     const char kVS[] = R"(#version 310 es
16481 #extension GL_EXT_shader_io_blocks : require
16482 in vec4 position;
16483 struct s {
16484     float f;
16485     vec2 v;
16486 };
16487 out BlockType {
16488     s blockMember;
16489 } BlockTypeOut;
16490 
16491 void main()
16492 {
16493     gl_Position = position;
16494 })";
16495 
16496     const char kFS[] = R"(#version 310 es
16497 #extension GL_EXT_shader_io_blocks : require
16498 precision mediump float;
16499 out vec4 colorOut;
16500 struct s {
16501     float f;
16502     vec2 v;
16503 };
16504 in BlockType {
16505     s blockMember;
16506 } BlockTypeOut;
16507 
16508 void main()
16509 {
16510     if (BlockTypeOut.blockMember.f == 0.0 &&
16511         BlockTypeOut.blockMember.v == vec2(0)) {
16512         colorOut = vec4(0, 1, 0, 1);
16513     } else {
16514         colorOut = vec4(1, 0, 0, 1);
16515     }
16516 })";
16517 
16518     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16519     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16520     ASSERT_GL_NO_ERROR();
16521     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16522 }
16523 
16524 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)16525 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
16526 {
16527     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16528 
16529     const char kVS[] = R"(#version 310 es
16530 #extension GL_EXT_shader_io_blocks : require
16531 in vec4 position;
16532 struct s {
16533     float f;
16534     vec2 v;
16535 };
16536 out BlockType {
16537     vec4 v;
16538     s s1;
16539     s s2[2];
16540 } BlockTypeOut;
16541 
16542 void main()
16543 {
16544     gl_Position = position;
16545 })";
16546 
16547     const char kFS[] = R"(#version 310 es
16548 #extension GL_EXT_shader_io_blocks : require
16549 precision mediump float;
16550 out vec4 colorOut;
16551 struct s {
16552     float f;
16553     vec2 v;
16554 };
16555 in BlockType {
16556     vec4 v;
16557     s s1;
16558     s s2[2];
16559 } BlockTypeOut;
16560 
16561 void main()
16562 {
16563     s sz = s(0.0, vec2(0));
16564     if (BlockTypeOut.v == vec4(0) &&
16565         BlockTypeOut.s1 == sz &&
16566         BlockTypeOut.s2[0] == sz &&
16567         BlockTypeOut.s2[1] == sz) {
16568         colorOut = vec4(0, 1, 0, 1);
16569     } else {
16570         colorOut = vec4(1, 0, 0, 1);
16571     }
16572 })";
16573 
16574     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16575     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16576     ASSERT_GL_NO_ERROR();
16577     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16578 }
16579 
16580 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)16581 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
16582 {
16583     // Make a simple program.
16584     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
16585 
16586     // Install the executable.
16587     glUseProgram(testProgram);
16588 
16589     // Re-link with a bad XFB varying and a bound attrib location.
16590     const char *tfVaryings = "gl_FragColor";
16591     glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
16592     glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
16593     glLinkProgram(testProgram);
16594     GLint linkStatus = 999;
16595     glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
16596     ASSERT_GL_NO_ERROR();
16597     ASSERT_EQ(linkStatus, GL_FALSE);
16598 
16599     // Under normal GL this is not an error.
16600     glDrawArrays(GL_TRIANGLES, 79, 16);
16601     EXPECT_GL_NO_ERROR();
16602 }
16603 
16604 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)16605 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
16606 {
16607     // Make a simple program.
16608     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
16609 
16610     // Install the executable.
16611     glUseProgram(testProgram);
16612 
16613     // Re-link with a bad XFB varying and a bound attrib location.
16614     const char *tfVaryings = "gl_FragColor";
16615     glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
16616     glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
16617     glLinkProgram(testProgram);
16618     GLint linkStatus = 999;
16619     glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
16620     ASSERT_GL_NO_ERROR();
16621     ASSERT_EQ(linkStatus, GL_FALSE);
16622 
16623     // Under WebGL this is an error.
16624     glDrawArrays(GL_TRIANGLES, 79, 16);
16625     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
16626 }
16627 
16628 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)16629 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
16630 {
16631     constexpr char kFS[] = R"(#version 300 es
16632 precision mediump float;
16633 vec3 a = vec3(0.0);
16634 out vec4 color;
16635 void main()
16636 {
16637     cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
16638 })";
16639 
16640     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
16641     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16642     ASSERT_GL_NO_ERROR();
16643 }
16644 
16645 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)16646 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
16647 {
16648     constexpr char kFS[] = R"(#version 300 es
16649 struct S {
16650     int foo;
16651 };
16652 void main() {
16653     S a[3];
16654     a = S[3](S(0), S(1), S(2));
16655 })";
16656 
16657     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16658 
16659     const char *sourceArray[1] = {kFS};
16660     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16661     glShaderSource(shader, 1, sourceArray, lengths);
16662     glCompileShader(shader);
16663 
16664     GLint compileResult;
16665     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16666     EXPECT_NE(compileResult, 0);
16667 }
16668 
16669 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)16670 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
16671 {
16672     constexpr char kFS[] = R"(#version 300 es
16673 
16674 precision mediump float;
16675 
16676 layout(location=0) out vec4 color;
16677 
16678 uniform float f;
16679 
16680 void main()
16681 {
16682     mat3x2 m = f + mat3x2(0);
16683     color = vec4(m[0][0]);
16684 })";
16685 
16686     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16687 
16688     const char *sourceArray[1] = {kFS};
16689     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16690     glShaderSource(shader, 1, sourceArray, lengths);
16691     glCompileShader(shader);
16692 
16693     GLint compileResult;
16694     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16695     EXPECT_NE(compileResult, 0);
16696 }
16697 
16698 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
16699 // folding it into a TIntermConstantUnion.  This transformation is clamping non-constant indices in
16700 // WebGL.  The |false ? i : 5| as index caused the transformation to consider this a non-constant
16701 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)16702 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
16703 {
16704     constexpr char kFS[] = R"(#version 300 es
16705 precision highp float;
16706 
16707 layout(location=0) out float f;
16708 
16709 uniform int i;
16710 
16711 void main()
16712 {
16713     float data[10];
16714     f = data[false ? i : 5];
16715 })";
16716 
16717     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16718 
16719     const char *sourceArray[1] = {kFS};
16720     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16721     glShaderSource(shader, 1, sourceArray, lengths);
16722     glCompileShader(shader);
16723 
16724     GLint compileResult;
16725     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16726     EXPECT_NE(compileResult, 0);
16727 }
16728 
16729 // Test robustness of out-of-bounds lod in texelFetch
TEST_P(WebGL2GLSLTest,TexelFetchLodOutOfBounds)16730 TEST_P(WebGL2GLSLTest, TexelFetchLodOutOfBounds)
16731 {
16732     constexpr char kVS[] = R"(#version 300 es
16733 in vec4 vertexPosition;
16734 void main() {
16735     gl_Position = vertexPosition;
16736 })";
16737 
16738     constexpr char kFS[] = R"(#version 300 es
16739 precision highp float;
16740 uniform highp sampler2DArray textureArray;
16741 uniform int textureLod;
16742 out vec4 fragColor;
16743 void main() {
16744     fragColor = texelFetch(textureArray, ivec3(gl_FragCoord.xy, 0), textureLod);
16745 })";
16746 
16747     ANGLE_GL_PROGRAM(program, kVS, kFS);
16748     glUseProgram(program);
16749     const GLint lodLoc = glGetUniformLocation(program, "textureLod");
16750     EXPECT_NE(lodLoc, -1);
16751     const GLint textureLoc = glGetUniformLocation(program, "textureArray");
16752     EXPECT_NE(textureLoc, -1);
16753 
16754     const GLint attribLocation = glGetAttribLocation(program, "vertexPosition");
16755     GLBuffer buffer;
16756     glBindBuffer(GL_ARRAY_BUFFER, buffer);
16757     constexpr float vertices[12] = {
16758         -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
16759     };
16760     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
16761     glEnableVertexAttribArray(attribLocation);
16762     glVertexAttribPointer(attribLocation, 2, GL_FLOAT, false, 0, 0);
16763 
16764     GLTexture texture;
16765     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
16766     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
16767     glUniform1i(textureLoc, 0);
16768 
16769     // Test LOD too large
16770     glUniform1i(lodLoc, 0x7FFF);
16771     glDrawArrays(GL_TRIANGLES, 0, 6);
16772 
16773     // Test LOD negative
16774     glUniform1i(lodLoc, -1);
16775     glDrawArrays(GL_TRIANGLES, 0, 6);
16776 }
16777 
16778 // Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without
16779 // failing validation (adapted from a Chromium test, see anglebug.com/6951)
TEST_P(GLSLTest,FramebufferFetchWithLastFragData)16780 TEST_P(GLSLTest, FramebufferFetchWithLastFragData)
16781 {
16782     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
16783 
16784     constexpr char kFS[] = R"(#version 100
16785 
16786 #extension GL_EXT_shader_framebuffer_fetch : require
16787 varying mediump vec4 color;
16788 void main() {
16789     gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0];
16790 })";
16791 
16792     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16793 
16794     const char *sourceArray[1] = {kFS};
16795     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16796     glShaderSource(shader, 1, sourceArray, lengths);
16797     glCompileShader(shader);
16798 
16799     GLint compileResult;
16800     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16801     EXPECT_NE(compileResult, 0);
16802 }
16803 
16804 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch1)16805 TEST_P(GLSLTest, LoopBodyEndingInBranch1)
16806 {
16807     constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})";
16808 
16809     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16810 
16811     const char *sourceArray[1] = {kFS};
16812     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16813     glShaderSource(shader, 1, sourceArray, lengths);
16814     glCompileShader(shader);
16815 
16816     GLint compileResult;
16817     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16818     EXPECT_NE(compileResult, 0);
16819 }
16820 
16821 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch2)16822 TEST_P(GLSLTest, LoopBodyEndingInBranch2)
16823 {
16824     constexpr char kFS[] =
16825         R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})";
16826 
16827     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16828 
16829     const char *sourceArray[1] = {kFS};
16830     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16831     glShaderSource(shader, 1, sourceArray, lengths);
16832     glCompileShader(shader);
16833 
16834     GLint compileResult;
16835     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16836     EXPECT_NE(compileResult, 0);
16837 }
16838 
16839 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch3)16840 TEST_P(GLSLTest, LoopBodyEndingInBranch3)
16841 {
16842     constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})";
16843 
16844     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16845 
16846     const char *sourceArray[1] = {kFS};
16847     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16848     glShaderSource(shader, 1, sourceArray, lengths);
16849     glCompileShader(shader);
16850 
16851     GLint compileResult;
16852     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16853     EXPECT_NE(compileResult, 0);
16854 }
16855 
16856 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch4)16857 TEST_P(GLSLTest, LoopBodyEndingInBranch4)
16858 {
16859     constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})";
16860 
16861     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16862 
16863     const char *sourceArray[1] = {kFS};
16864     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16865     glShaderSource(shader, 1, sourceArray, lengths);
16866     glCompileShader(shader);
16867 
16868     GLint compileResult;
16869     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16870     EXPECT_NE(compileResult, 0);
16871 }
16872 
16873 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch5)16874 TEST_P(GLSLTest, LoopBodyEndingInBranch5)
16875 {
16876     constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})";
16877 
16878     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16879 
16880     const char *sourceArray[1] = {kFS};
16881     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16882     glShaderSource(shader, 1, sourceArray, lengths);
16883     glCompileShader(shader);
16884 
16885     GLint compileResult;
16886     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16887     EXPECT_NE(compileResult, 0);
16888 }
16889 
16890 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch6)16891 TEST_P(GLSLTest, LoopBodyEndingInBranch6)
16892 {
16893     constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})";
16894 
16895     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16896 
16897     const char *sourceArray[1] = {kFS};
16898     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
16899     glShaderSource(shader, 1, sourceArray, lengths);
16900     glCompileShader(shader);
16901 
16902     GLint compileResult;
16903     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16904     EXPECT_NE(compileResult, 0);
16905 }
16906 
16907 // Test that aliasing function out parameters work.  The GLSL spec says:
16908 //
16909 // > Because the function works with local copies of parameters, there are no issues regarding
16910 // > aliasing of variables within a function.
16911 //
16912 // In the test below, while the value of x is unknown after the function call, the result of the
16913 // function must deterministically be true.
TEST_P(GLSLTest,AliasingFunctionOutParams)16914 TEST_P(GLSLTest, AliasingFunctionOutParams)
16915 {
16916     constexpr char kFS[] = R"(precision highp float;
16917 
16918 const vec4 colorGreen = vec4(0.,1.,0.,1.);
16919 const vec4 colorRed   = vec4(1.,0.,0.,1.);
16920 
16921 bool outParametersAreDistinct(out float x, out float y) {
16922     x = 1.0;
16923     y = 2.0;
16924     return x == 1.0 && y == 2.0;
16925 }
16926 void main() {
16927     float x = 0.0;
16928     gl_FragColor = outParametersAreDistinct(x, x) ? colorGreen : colorRed;
16929 }
16930 )";
16931 
16932     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
16933     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16934     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16935     ASSERT_GL_NO_ERROR();
16936 }
16937 
16938 // Test that aliasing function out parameters work even when multiple params are aliased.
TEST_P(GLSLTest,AliasingFunctionOutParamsMultiple)16939 TEST_P(GLSLTest, AliasingFunctionOutParamsMultiple)
16940 {
16941     constexpr char kFS[] = R"(precision highp float;
16942 
16943 const vec4 colorGreen = vec4(0.,1.,0.,1.);
16944 const vec4 colorRed   = vec4(1.,0.,0.,1.);
16945 
16946 bool outParametersAreDistinct(out float x, out float y, out float z, out float a) {
16947     x = 1.0;
16948     y = 2.0;
16949     z = 3.0;
16950     a = 4.0;
16951     return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
16952 }
16953 void main() {
16954     float x = 0.0;
16955     float y = 0.0;
16956     gl_FragColor = outParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
16957 }
16958 )";
16959 
16960     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
16961     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16962     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16963     ASSERT_GL_NO_ERROR();
16964 }
16965 
16966 // Test that aliasing function inout parameters work.
TEST_P(GLSLTest,AliasingFunctionInOutParams)16967 TEST_P(GLSLTest, AliasingFunctionInOutParams)
16968 {
16969     constexpr char kFS[] = R"(precision highp float;
16970 
16971 const vec4 colorGreen = vec4(0.,1.,0.,1.);
16972 const vec4 colorRed   = vec4(1.,0.,0.,1.);
16973 
16974 bool inoutParametersAreDistinct(inout float x, inout float y) {
16975     x = 1.0;
16976     y = 2.0;
16977     return x == 1.0 && y == 2.0;
16978 }
16979 void main() {
16980     float x = 0.0;
16981     gl_FragColor = inoutParametersAreDistinct(x, x) ? colorGreen : colorRed;
16982 }
16983 )";
16984 
16985     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
16986     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16987     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16988     ASSERT_GL_NO_ERROR();
16989 }
16990 
16991 // Test coverage of some matrix/scalar ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixScalarOps)16992 TEST_P(GLSLTest, MatrixScalarOps)
16993 {
16994     constexpr char kFS[] = R"(precision highp float;
16995 void main() {
16996     float scalar = 0.5;
16997     mat3 matrix = mat3(vec3(0.1), vec3(0.1), vec3(0.1));
16998 
16999     mat3 m0 = scalar / matrix;
17000     mat3 m1 = scalar * matrix;
17001     mat3 m2 = scalar + matrix;
17002     mat3 m3 = scalar - matrix;
17003 
17004     gl_FragColor = vec4(m0[0][0], m1[0][0], m2[0][0], m3[0][0]);
17005 }
17006 )";
17007 
17008     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17009     ASSERT_GL_NO_ERROR();
17010 
17011     drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17012     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 13, 153, 102), 1.0);
17013     ASSERT_GL_NO_ERROR();
17014 }
17015 
17016 // Test coverage of some matrix ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixNegate)17017 TEST_P(GLSLTest, MatrixNegate)
17018 {
17019     constexpr char kFS[] = R"(precision highp float;
17020 void main() {
17021     mat3 matrix = mat3(vec3(-0.1), vec3(-0.1), vec3(-0.1));
17022 
17023     mat3 m0 = -matrix;
17024 
17025     gl_FragColor = vec4(m0[0][0], 0, 0, 1);
17026 }
17027 )";
17028 
17029     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17030     ASSERT_GL_NO_ERROR();
17031 
17032     drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17033     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(26, 0, 0, 255), 1.0);
17034     ASSERT_GL_NO_ERROR();
17035 }
17036 
17037 // Test coverage of the mix(float, float, bool) overload which was missing in Metal translation
TEST_P(GLSLTest_ES3,MixFloatFloatBool)17038 TEST_P(GLSLTest_ES3, MixFloatFloatBool)
17039 {
17040     constexpr char kFS[] = R"(#version 300 es
17041 precision highp float;
17042 out vec4 fragColor;
17043 void main() {
17044     vec4 testData = vec4(0.0, 1.0, 0.5, 0.25);
17045     float scalar = mix(testData.x, testData.y, testData.x < 0.5);
17046     vec2 vector = mix(testData.xy, testData.xw, bvec2(testData.x < 0.5, testData.y < 0.5));
17047     fragColor = vec4(scalar, vector.x, vector.y, 1);
17048 }
17049 )";
17050 
17051     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17052     ASSERT_GL_NO_ERROR();
17053 
17054     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17055     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 255, 255));
17056     ASSERT_GL_NO_ERROR();
17057 }
17058 
17059 // Test that aliasing function inout parameters work when more than one param is aliased.
TEST_P(GLSLTest,AliasingFunctionInOutParamsMultiple)17060 TEST_P(GLSLTest, AliasingFunctionInOutParamsMultiple)
17061 {
17062     constexpr char kFS[] = R"(precision highp float;
17063 
17064 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17065 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17066 
17067 bool inoutParametersAreDistinct(inout float x, inout float y, inout float z, inout float a) {
17068     x = 1.0;
17069     y = 2.0;
17070     z = 3.0;
17071     a = 4.0;
17072     return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17073 }
17074 void main() {
17075     float x = 0.0;
17076     float y = 0.0;
17077     gl_FragColor = inoutParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17078 }
17079 )";
17080 
17081     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17082     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17083     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17084     ASSERT_GL_NO_ERROR();
17085 }
17086 
17087 // Test that aliasing function out parameter with a global works.
TEST_P(GLSLTest,AliasingFunctionOutParamAndGlobal)17088 TEST_P(GLSLTest, AliasingFunctionOutParamAndGlobal)
17089 {
17090     constexpr char kFS[] = R"(precision highp float;
17091 
17092 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17093 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17094 
17095 float x = 1.0;
17096 bool outParametersAreDistinctFromGlobal(out float y) {
17097     y = 2.0;
17098     return x == 1.0 && y == 2.0;
17099 }
17100 void main() {
17101     gl_FragColor = outParametersAreDistinctFromGlobal(x) ? colorGreen : colorRed;
17102 }
17103 )";
17104 
17105     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17106     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17107     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17108     ASSERT_GL_NO_ERROR();
17109 }
17110 
17111 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstSamplerParameter)17112 TEST_P(GLSLTest, ConstSamplerParameter)
17113 {
17114     constexpr char kFS[] = R"(precision mediump float;
17115 uniform sampler2D samp;
17116 
17117 vec4 sampleConstSampler(const sampler2D s) {
17118     return texture2D(s, vec2(0));
17119 }
17120 
17121 void main() {
17122     gl_FragColor = sampleConstSampler(samp);
17123 }
17124 )";
17125     CompileShader(GL_FRAGMENT_SHADER, kFS);
17126     ASSERT_GL_NO_ERROR();
17127 }
17128 
17129 // Make sure passing const sampler parameters to another function work.
TEST_P(GLSLTest,ConstSamplerParameterAsArgument)17130 TEST_P(GLSLTest, ConstSamplerParameterAsArgument)
17131 {
17132     constexpr char kFS[] = R"(precision mediump float;
17133 
17134 uniform sampler2D samp;
17135 
17136 vec4 sampleSampler(sampler2D s) {
17137     return texture2D(s, vec2(0));
17138 }
17139 
17140 vec4 sampleConstSampler(const sampler2D s) {
17141     return sampleSampler(s);
17142 }
17143 
17144 void main() {
17145     gl_FragColor = sampleConstSampler(samp);
17146 }
17147 )";
17148     CompileShader(GL_FRAGMENT_SHADER, kFS);
17149     ASSERT_GL_NO_ERROR();
17150 }
17151 
17152 // Test for a driver bug with matrix multiplication in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixMultiplicationBug)17153 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixMultiplicationBug)
17154 {
17155     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17156 
17157     constexpr char kTCS[] = R"(#version 310 es
17158 #extension GL_EXT_tessellation_shader : enable
17159 layout(vertices = 1) out;
17160 precision highp float;
17161 
17162 patch out mat4 x;
17163 
17164 void main()
17165 {
17166     x = mat4(
17167         0.53455, 0.47307, 0.34935, 0.28717,
17168         0.67195, 0.59992, 0.48213, 0.43678,
17169         0.76376, 0.6772, 0.55361, 0.5165,
17170         0.77996, 0.68862, 0.56187, 0.52611
17171     );
17172 
17173     const mat4 m = mat4(
17174         vec4( -1.0, 3.0,-3.0, 1.0),
17175         vec4(  3.0,-6.0, 3.0, 0.0),
17176         vec4( -3.0, 3.0, 0.0, 0.0),
17177         vec4(  1.0, 0.0, 0.0, 0.0)
17178     );
17179 
17180     x = m * x;
17181 
17182     gl_TessLevelInner[0u] = 1.;
17183     gl_TessLevelInner[1u] = 1.;
17184     gl_TessLevelOuter[0u] = 1.;
17185     gl_TessLevelOuter[1u] = 1.;
17186     gl_TessLevelOuter[2u] = 1.;
17187     gl_TessLevelOuter[3u] = 1.;
17188 })";
17189 
17190     constexpr char kTES[] = R"(#version 310 es
17191 #extension GL_EXT_tessellation_shader : enable
17192 layout(quads, cw, fractional_odd_spacing) in;
17193 precision highp float;
17194 
17195 patch in mat4 x;
17196 
17197 out mat4 x_fs;
17198 
17199 void main()
17200 {
17201     x_fs = x;
17202     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17203 })";
17204 
17205     constexpr char kFS[] = R"(#version 310 es
17206 precision highp float;
17207 
17208 in mat4 x_fs;
17209 out vec4 color;
17210 
17211 void main()
17212 {
17213     // Note: on the failing driver, .w of every column has the same value as .x of the same column.
17214 
17215     const mat4 expect = mat4(
17216         0.12378, -0.18672, -0.18444, 0.53455,
17217         0.1182, -0.13728, -0.21609, 0.67195,
17218         0.12351, -0.11109, -0.25968, 0.76376,
17219         0.1264, -0.10623, -0.27402, 0.77996
17220     );
17221 
17222     color = vec4(all(lessThan(abs(x_fs[0] - expect[0]), vec4(0.01))),
17223                  all(lessThan(abs(x_fs[1] - expect[1]), vec4(0.01))),
17224                  all(lessThan(abs(x_fs[2] - expect[2]), vec4(0.01))),
17225                  all(lessThan(abs(x_fs[3] - expect[3]), vec4(0.01))));
17226 })";
17227 
17228     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
17229     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
17230     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
17231     ASSERT_GL_NO_ERROR();
17232 }
17233 
17234 // Test for a driver bug with matrix copy in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixCopyBug)17235 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixCopyBug)
17236 {
17237     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17238 
17239     constexpr char kTCS[] = R"(#version 310 es
17240 #extension GL_EXT_tessellation_shader : enable
17241 layout(vertices = 1) out;
17242 precision highp float;
17243 
17244 patch out mat4 x;
17245 patch out vec4 col0;
17246 
17247 void main()
17248 {
17249     // Note: if |x| is not an |out| varying, the test passes.
17250     x = mat4(
17251         0.53455, 0.47307, 0.34935, 0.28717,
17252         0.67195, 0.59992, 0.48213, 0.43678,
17253         0.76376, 0.6772, 0.55361, 0.5165,
17254         0.77996, 0.68862, 0.56187, 0.52611
17255     );
17256 
17257     const mat4 m = mat4(
17258         vec4( -1.0, 3.0,-3.0, 1.0),
17259         vec4(  3.0,-6.0, 3.0, 0.0),
17260         vec4( -3.0, 3.0, 0.0, 0.0),
17261         vec4(  1.0, 0.0, 0.0, 0.0)
17262     );
17263 
17264     mat4 temp = x;
17265 
17266     // Note: On the failing driver, commenting this line makes the test pass.
17267     // However, the output being tested is |temp|, assigned above, not |x|.
17268     x = m * x;
17269 
17270     col0 = temp[0];
17271 
17272     gl_TessLevelInner[0u] = 1.;
17273     gl_TessLevelInner[1u] = 1.;
17274     gl_TessLevelOuter[0u] = 1.;
17275     gl_TessLevelOuter[1u] = 1.;
17276     gl_TessLevelOuter[2u] = 1.;
17277     gl_TessLevelOuter[3u] = 1.;
17278 })";
17279 
17280     constexpr char kTES[] = R"(#version 310 es
17281 #extension GL_EXT_tessellation_shader : enable
17282 layout(quads, cw, fractional_odd_spacing) in;
17283 precision highp float;
17284 
17285 patch in vec4 col0;
17286 
17287 out vec4 col0_fs;
17288 
17289 void main()
17290 {
17291     col0_fs = col0;
17292     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17293 })";
17294 
17295     constexpr char kFS[] = R"(#version 310 es
17296 precision highp float;
17297 
17298 in vec4 col0_fs;
17299 out vec4 color;
17300 
17301 void main()
17302 {
17303     // Note: on the failing driver, |col0| has the value of |m * x|, not |temp|.
17304     color = vec4(abs(col0_fs.x - 0.53455) < 0.01,
17305                 abs(col0_fs.y - 0.47307) < 0.01,
17306                 abs(col0_fs.z - 0.34935) < 0.01,
17307                 abs(col0_fs.w - 0.28717) < 0.01);
17308 })";
17309 
17310     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
17311     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
17312     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
17313     ASSERT_GL_NO_ERROR();
17314 }
17315 
17316 // Tests the generation of HLSL functions with uint/int parameters that may be ambiguous.
TEST_P(GLSLTest_ES3,AmbiguousHLSLIntegerFunctionParameters)17317 TEST_P(GLSLTest_ES3, AmbiguousHLSLIntegerFunctionParameters)
17318 {
17319     const char kVS[] = R"(#version 300 es
17320 precision highp float;
17321 void main()
17322 {
17323     gl_Position = vec4(0, 0, 0, 0);
17324 })";
17325 
17326     const char kFS[] = R"(#version 300 es
17327 precision highp float;
17328 out vec4 color;
17329 void main()
17330 {
17331     // Ensure that both uint and int to float constructors are generated before the ambiguous usage.
17332     int i = int(gl_FragCoord.x);
17333     float f1 = float(i);
17334     color.r = f1;
17335 
17336     uint ui = uint(gl_FragCoord.x);
17337     float f2 = float(i);
17338     color.g = f2;
17339 
17340     // Ambiguous call
17341     float f3 = float(1u << (2u * ui));
17342     color.b = f3;
17343 })";
17344 
17345     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17346 }
17347 
17348 // Tests adding a struct definition inline in a shader.
17349 // Metal backend contains a pass that separates struct definition and declaration.
TEST_P(GLSLTest_ES3,StructInShader)17350 TEST_P(GLSLTest_ES3, StructInShader)
17351 {
17352     const char kVS[] = R"(#version 300 es
17353 precision highp float;
17354 void main(void)
17355 {
17356     struct structMain {
17357         float i;
17358     } testStruct;
17359 
17360     testStruct.i = 5.0 ;
17361     gl_Position = vec4(testStruct.i - 4.0, 0, 0, 1);
17362 })";
17363 
17364     const char kFS[] = R"(#version 300 es
17365 precision highp float;
17366 out vec4 color;
17367 void main()
17368 {
17369     color = vec4(0,1,0,0);
17370 })";
17371 
17372     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17373 }
17374 
17375 // Issue: A while loop's expression, and a branch
17376 // condition with EOpContinue were being deep
17377 // copied as part of monomorphize functions,
17378 // causing a crash, as they were not null-checked.
17379 // Tests transforming a function that will be monomorphized.
TEST_P(GLSLTest_ES3,MonomorphizeForAndContinue)17380 TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue)
17381 {
17382 
17383     constexpr char kFS[] =
17384         R"(#version 300 es
17385 
17386         precision mediump float;
17387         out vec4 fragOut;
17388         struct aParam
17389         {
17390             sampler2D sampler;
17391         };
17392         uniform aParam theParam;
17393 
17394         float monomorphizedFunction(aParam a)
17395         {
17396             int i = 0;
17397             vec4 j = vec4(0);
17398             for(;;)
17399             {
17400                 if(i++ < 10)
17401                 {
17402                     j += texture(a.sampler, vec2(0.0f,0.0f));
17403                     continue;
17404                 }
17405                 break;
17406             }
17407             return j.a;
17408         }
17409         void main()
17410         {
17411             fragOut.a = monomorphizedFunction(theParam);
17412         }
17413 )";
17414     CompileShader(GL_FRAGMENT_SHADER, kFS);
17415     ASSERT_GL_NO_ERROR();
17416 }
17417 
17418 // Tests inout parameters with array references.
TEST_P(GLSLTest_ES3,InoutWithArrayRefs)17419 TEST_P(GLSLTest_ES3, InoutWithArrayRefs)
17420 {
17421     const char kVS[] = R"(#version 300 es
17422 precision highp float;
17423 void swap(inout float a, inout float b)
17424 {
17425     float tmp = a;
17426     a = b;
17427     b = tmp;
17428 }
17429 
17430 void main(void)
17431 {
17432     vec3 testVec = vec3(0.0, 1.0, 1.0);
17433     swap(testVec[0], testVec[1]);
17434     gl_Position = vec4(testVec[0], testVec[1], testVec[2], 1.0);
17435 })";
17436 
17437     const char kFS[] = R"(#version 300 es
17438 precision highp float;
17439 out vec4 color;
17440 void main()
17441 {
17442     color = vec4(0,1,0,0);
17443 })";
17444 
17445     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17446 }
17447 
17448 // Test that sample variables compile.
TEST_P(GLSLTest_ES3,SampleVariables)17449 TEST_P(GLSLTest_ES3, SampleVariables)
17450 {
17451     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
17452 
17453     const char kFS[] = R"(#version 300 es
17454 #extension GL_OES_sample_variables : require
17455 precision highp float;
17456 out vec4 color;
17457 void main()
17458 {
17459     gl_SampleMask[0] = gl_SampleMaskIn[0] & 0x55555555;
17460     color = vec4(gl_SamplePosition.yx, float(gl_SampleID), float(gl_MaxSamples + gl_NumSamples));
17461 })";
17462 
17463     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17464 }
17465 
17466 // Test that shader caching maintains uniforms across compute shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniform)17467 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniform)
17468 {
17469     ANGLE_SKIP_TEST_IF(!IsVulkan());
17470     constexpr char kCS[] = R"(#version 310 es
17471 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
17472 
17473 uniform uint inputs[6];
17474 
17475 layout (binding = 0, std430) buffer OutputBuffer {
17476     uint outputs[6];
17477 };
17478 
17479 void main() {
17480     outputs[gl_LocalInvocationIndex] = inputs[gl_LocalInvocationIndex];
17481 }
17482 )";
17483 
17484     ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
17485     ASSERT_GL_NO_ERROR();
17486     // Delete the shader and recompile to fetch from cache.
17487     glDeleteProgram(unusedProgram);
17488     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
17489     ASSERT_GL_NO_ERROR();
17490     glUseProgram(program);
17491 
17492     constexpr std::array<GLuint, 6> kInputUniform = {1, 2, 3, 4, 5, 6};
17493     for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
17494     {
17495         const std::string uniformName =
17496             std::string("inputs[") + std::to_string(i) + std::string("]");
17497         int inputLocation =
17498             glGetUniformLocation(program, static_cast<const GLchar *>(uniformName.c_str()));
17499         glUniform1ui(inputLocation, kInputUniform[i]);
17500         ASSERT_GL_NO_ERROR();
17501     }
17502 
17503     constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
17504     GLBuffer outputBuffer;
17505     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
17506     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
17507                  kOutputInitData.data(), GL_STATIC_READ);
17508     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
17509 
17510     glDispatchCompute(1, 1, 1);
17511     glDeleteProgram(program);
17512     ASSERT_GL_NO_ERROR();
17513     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
17514 
17515     auto outputData = static_cast<const GLuint *>(glMapBufferRange(
17516         GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
17517     for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
17518     {
17519         EXPECT_EQ(kInputUniform[i], outputData[i]);
17520     }
17521 }
17522 
17523 // Test that shader caching maintains uniform blocks across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniformBlocks)17524 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniformBlocks)
17525 {
17526     ANGLE_SKIP_TEST_IF(!IsVulkan());
17527     constexpr char kCS[] = R"(#version 310 es
17528 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
17529 
17530 layout (std140) uniform Input1 {
17531     uint input1;
17532 };
17533 
17534 layout (std140) uniform Input2 {
17535     uint input2;
17536 };
17537 
17538 layout (binding = 0, std430) buffer OutputBuffer {
17539     uint outputs[6];
17540 };
17541 
17542 void main() {
17543     if (gl_LocalInvocationIndex < uint(3))
17544     {
17545         outputs[gl_LocalInvocationIndex] = input1;
17546     }
17547     else
17548     {
17549         outputs[gl_LocalInvocationIndex] = input2;
17550     }
17551 }
17552 )";
17553 
17554     ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
17555     ASSERT_GL_NO_ERROR();
17556     // Delete the shader and recompile to fetch from cache.
17557     glDeleteProgram(unusedProgram);
17558     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
17559     ASSERT_GL_NO_ERROR();
17560     glUseProgram(program);
17561 
17562     constexpr GLuint kInput1Data = 1;
17563     GLBuffer input1;
17564     glBindBuffer(GL_UNIFORM_BUFFER, input1);
17565     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput1Data, GL_STATIC_COPY);
17566     const GLuint kInput1Index = glGetUniformBlockIndex(program, "Input1");
17567     glUniformBlockBinding(program, kInput1Index, 1);
17568     glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
17569     glBindBuffer(GL_UNIFORM_BUFFER, 0);
17570     ASSERT_GL_NO_ERROR();
17571 
17572     constexpr GLuint kInput2Data = 2;
17573     GLBuffer input2;
17574     glBindBuffer(GL_UNIFORM_BUFFER, input2);
17575     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput2Data, GL_STATIC_COPY);
17576     const GLuint kInput2Index = glGetUniformBlockIndex(program, "Input2");
17577     glUniformBlockBinding(program, kInput2Index, 2);
17578     glBindBufferBase(GL_UNIFORM_BUFFER, 2, input2);
17579     glBindBuffer(GL_UNIFORM_BUFFER, 0);
17580     ASSERT_GL_NO_ERROR();
17581 
17582     constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
17583     GLBuffer outputBuffer;
17584     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
17585     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
17586                  kOutputInitData.data(), GL_STATIC_READ);
17587     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
17588     ASSERT_GL_NO_ERROR();
17589 
17590     glDispatchCompute(1, 1, 1);
17591     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
17592     glDeleteProgram(program);
17593     ASSERT_GL_NO_ERROR();
17594 
17595     auto outputData                       = static_cast<const GLuint *>(glMapBufferRange(
17596         GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
17597     constexpr std::array<GLuint, 6> kWant = {kInput1Data, kInput1Data, kInput1Data,
17598                                              kInput2Data, kInput2Data, kInput2Data};
17599     for (int i = 0; i < static_cast<int>(kWant.size()); ++i)
17600     {
17601         EXPECT_EQ(kWant[i], outputData[i]);
17602     }
17603 }
17604 
17605 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniform)17606 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniform)
17607 {
17608     ANGLE_SKIP_TEST_IF(!IsVulkan());
17609     constexpr char kVS[] = R"(#version 310 es
17610 
17611 precision mediump float;
17612 
17613 layout (location = 0) in vec4 a_position;
17614 
17615 uniform float redInput;
17616 
17617 out float redValue;
17618 
17619 void main() {
17620     gl_Position = a_position;
17621     redValue = redInput;
17622 })";
17623 
17624     constexpr char kFS[] = R"(#version 310 es
17625 
17626 precision mediump float;
17627 
17628 in float redValue;
17629 
17630 out vec4 fragColor;
17631 
17632 void main()
17633 {
17634     fragColor = vec4(redValue, 0., 0., 1.);
17635 })";
17636 
17637     ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
17638     ASSERT_GL_NO_ERROR();
17639     // Delete the shader and recompile to fetch from cache.
17640     glDeleteProgram(unusedProgram);
17641     ANGLE_GL_PROGRAM(program, kVS, kFS);
17642     ASSERT_GL_NO_ERROR();
17643     glUseProgram(program);
17644 
17645     constexpr GLfloat kRedValue = 1.0f;
17646     int redInputLocation        = glGetUniformLocation(program, "redInput");
17647     glUniform1f(redInputLocation, kRedValue);
17648     ASSERT_GL_NO_ERROR();
17649 
17650     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17651     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17652 }
17653 
17654 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniformBlock)17655 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniformBlock)
17656 {
17657     ANGLE_SKIP_TEST_IF(!IsVulkan());
17658     constexpr char kVS[] = R"(#version 310 es
17659 
17660 precision mediump float;
17661 
17662 layout (location = 0) in vec4 a_position;
17663 
17664 layout (std140) uniform Input {
17665     float redInput;
17666 };
17667 
17668 out float redValue;
17669 
17670 void main() {
17671     gl_Position = a_position;
17672     redValue = redInput;
17673 })";
17674 
17675     constexpr char kFS[] = R"(#version 310 es
17676 
17677 precision mediump float;
17678 
17679 in float redValue;
17680 
17681 out vec4 fragColor;
17682 
17683 void main()
17684 {
17685     fragColor = vec4(redValue, 0., 0., 1.);
17686 })";
17687 
17688     ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
17689     ASSERT_GL_NO_ERROR();
17690     // Delete the shader and recompile to fetch from cache.
17691     glDeleteProgram(unusedProgram);
17692     ANGLE_GL_PROGRAM(program, kVS, kFS);
17693     ASSERT_GL_NO_ERROR();
17694     glUseProgram(program);
17695 
17696     constexpr GLfloat kInputData = 1.0f;
17697     GLBuffer input;
17698     glBindBuffer(GL_UNIFORM_BUFFER, input);
17699     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17700     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
17701     glUniformBlockBinding(program, kInputIndex, 0);
17702     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
17703     glBindBuffer(GL_UNIFORM_BUFFER, 0);
17704     ASSERT_GL_NO_ERROR();
17705 
17706     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17707     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17708 }
17709 
17710 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithSSBO)17711 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithSSBO)
17712 {
17713     ANGLE_SKIP_TEST_IF(!IsVulkan());
17714 
17715     // Check that GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS is at least 1.
17716     GLint maxVertexShaderStorageBlocks;
17717     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
17718     ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks == 0);
17719     constexpr char kVS[] = R"(#version 310 es
17720 
17721 precision mediump float;
17722 
17723 layout (location = 0) in vec4 a_position;
17724 
17725 layout (binding = 0, std430) buffer Input {
17726     float redInput;
17727 };
17728 
17729 out float redValue;
17730 
17731 void main() {
17732     gl_Position = a_position;
17733     redValue = redInput;
17734 })";
17735 
17736     constexpr char kFS[] = R"(#version 310 es
17737 
17738 precision mediump float;
17739 
17740 in float redValue;
17741 
17742 out vec4 fragColor;
17743 
17744 void main()
17745 {
17746     fragColor = vec4(redValue, 0., 0., 1.);
17747 })";
17748 
17749     ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
17750     ASSERT_GL_NO_ERROR();
17751     // Delete the shader and recompile to fetch from cache.
17752     glDeleteProgram(unusedProgram);
17753     ANGLE_GL_PROGRAM(program, kVS, kFS);
17754     ASSERT_GL_NO_ERROR();
17755     glUseProgram(program);
17756 
17757     constexpr GLfloat kInputData = 1.0f;
17758     GLBuffer input;
17759     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
17760     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17761     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
17762     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
17763     ASSERT_GL_NO_ERROR();
17764 
17765     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17766     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17767 }
17768 
17769 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniform)17770 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniform)
17771 {
17772     ANGLE_SKIP_TEST_IF(!IsVulkan());
17773     constexpr char kFS[] = R"(#version 310 es
17774 
17775 precision mediump float;
17776 
17777 uniform float redValue;
17778 
17779 out vec4 fragColor;
17780 
17781 void main()
17782 {
17783     fragColor = vec4(redValue, 0., 0., 1.);
17784 })";
17785 
17786     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17787     ASSERT_GL_NO_ERROR();
17788     // Delete the shader and recompile to fetch from cache.
17789     glDeleteProgram(unusedProgram);
17790     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17791     ASSERT_GL_NO_ERROR();
17792     glUseProgram(program);
17793 
17794     GLfloat redValue     = 1.0f;
17795     int redInputLocation = glGetUniformLocation(program, "redValue");
17796     glUniform1f(redInputLocation, redValue);
17797     ASSERT_GL_NO_ERROR();
17798 
17799     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17800     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17801 }
17802 
17803 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniformBlock)17804 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniformBlock)
17805 {
17806     ANGLE_SKIP_TEST_IF(!IsVulkan());
17807     constexpr char kFS[] = R"(#version 310 es
17808 
17809 precision mediump float;
17810 
17811 layout (std140) uniform Input {
17812     float redValue;
17813 };
17814 
17815 out vec4 fragColor;
17816 
17817 void main()
17818 {
17819     fragColor = vec4(redValue, 0., 0., 1.);
17820 })";
17821 
17822     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17823     ASSERT_GL_NO_ERROR();
17824     // Delete the shader and recompile to fetch from cache.
17825     glDeleteProgram(unusedProgram);
17826     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17827     ASSERT_GL_NO_ERROR();
17828     glUseProgram(program);
17829 
17830     constexpr GLfloat kInputData = 1.0f;
17831     GLBuffer input;
17832     glBindBuffer(GL_UNIFORM_BUFFER, input);
17833     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17834     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
17835     glUniformBlockBinding(program, kInputIndex, 0);
17836     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
17837     glBindBuffer(GL_UNIFORM_BUFFER, 0);
17838     ASSERT_GL_NO_ERROR();
17839 
17840     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17841     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17842 }
17843 
17844 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithSSBO)17845 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithSSBO)
17846 {
17847     ANGLE_SKIP_TEST_IF(!IsVulkan());
17848     constexpr char kFS[] = R"(#version 310 es
17849 
17850 precision mediump float;
17851 
17852 layout (binding = 0, std430) buffer Input {
17853     float redValue;
17854 };
17855 
17856 out vec4 fragColor;
17857 
17858 void main()
17859 {
17860     fragColor = vec4(redValue, 0., 0., 1.);
17861 })";
17862 
17863     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17864     ASSERT_GL_NO_ERROR();
17865     // Delete the shader and recompile to fetch from cache.
17866     glDeleteProgram(unusedProgram);
17867     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17868     ASSERT_GL_NO_ERROR();
17869     glUseProgram(program);
17870 
17871     constexpr GLfloat kInputData = 1.0f;
17872     GLBuffer input;
17873     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
17874     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17875     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
17876     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
17877     ASSERT_GL_NO_ERROR();
17878 
17879     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17880     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17881 }
17882 
17883 // Test that shader caching maintains whether GL_ARB_sample_shading is enabled across shader
17884 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithARBSampleShading)17885 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithARBSampleShading)
17886 {
17887     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARB_sample_shading"));
17888     ANGLE_SKIP_TEST_IF(!IsVulkan());
17889 
17890     constexpr char kFS[] = R"(#version 310 es
17891 #extension GL_ARB_sample_shading : enable
17892 
17893 precision mediump float;
17894 
17895 out vec4 fragColor;
17896 
17897 void main()
17898 {
17899 #ifdef GL_ARB_sample_shading
17900     fragColor = vec4(1., 0., 0., 1.);
17901 #else
17902     fragColor = vec4(0.);
17903 #endif
17904 })";
17905 
17906     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17907     ASSERT_GL_NO_ERROR();
17908     // Delete the shader and recompile to fetch from cache.
17909     glDeleteProgram(unusedProgram);
17910     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17911     ASSERT_GL_NO_ERROR();
17912     glUseProgram(program);
17913 
17914     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17915     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17916 }
17917 
17918 // Test that shader caching maintains which advanced blending equations (provided by
17919 // GL_KHR_blend_equation_advanced) are used across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithKHRAdvancedBlendEquations)17920 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithKHRAdvancedBlendEquations)
17921 {
17922     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
17923     ANGLE_SKIP_TEST_IF(!IsVulkan());
17924 
17925     constexpr char kFS[] = R"(#version 310 es
17926 #extension GL_KHR_blend_equation_advanced : require
17927 
17928 layout (blend_support_multiply) out;
17929 
17930 precision mediump float;
17931 
17932 out vec4 fragColor;
17933 
17934 void main()
17935 {
17936     fragColor = vec4(1., 0., 0., 1.);
17937 })";
17938 
17939     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17940     ASSERT_GL_NO_ERROR();
17941     // Delete the shader and recompile to fetch from cache.
17942     glDeleteProgram(unusedProgram);
17943     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17944     ASSERT_GL_NO_ERROR();
17945     glUseProgram(program);
17946 
17947     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17948     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17949 }
17950 
17951 // Test that shader caching maintains uniforms in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniform)17952 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniform)
17953 {
17954     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
17955     ANGLE_SKIP_TEST_IF(!IsVulkan());
17956 
17957     constexpr char kGS[] = R"(#version 310 es
17958 #extension GL_EXT_geometry_shader : require
17959 precision mediump float;
17960 
17961 layout (triangles) in;
17962 layout (triangle_strip, max_vertices = 3) out;
17963 
17964 uniform float redInput;
17965 
17966 out float redValue;
17967 
17968 void main() {
17969     gl_Position = gl_in[0].gl_Position;
17970     redValue = redInput;
17971     EmitVertex();
17972 
17973     gl_Position = gl_in[1].gl_Position;
17974     redValue = redInput;
17975     EmitVertex();
17976 
17977     gl_Position = gl_in[2].gl_Position;
17978     redValue = redInput;
17979     EmitVertex();
17980 
17981     EndPrimitive();
17982 }
17983 )";
17984 
17985     constexpr char kFS[] = R"(#version 310 es
17986 precision mediump float;
17987 
17988 out vec4 fragColor;
17989 
17990 in float redValue;
17991 
17992 void main()
17993 {
17994     fragColor = vec4(redValue, 0., 0., 1.);
17995 })";
17996 
17997     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
17998     ASSERT_GL_NO_ERROR();
17999     // Delete the shader and recompile to fetch from cache.
18000     glDeleteProgram(unusedProgram);
18001     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18002     ASSERT_GL_NO_ERROR();
18003     glUseProgram(program);
18004 
18005     constexpr GLfloat kRedValue = 1.0f;
18006     int redInputLocation        = glGetUniformLocation(program, "redInput");
18007     glUniform1f(redInputLocation, kRedValue);
18008     ASSERT_GL_NO_ERROR();
18009 
18010     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18011     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18012 }
18013 
18014 // Test that shader caching maintains uniform blocks in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniformBlock)18015 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniformBlock)
18016 {
18017     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18018     ANGLE_SKIP_TEST_IF(!IsVulkan());
18019 
18020     constexpr char kGS[] = R"(#version 310 es
18021 #extension GL_EXT_geometry_shader : require
18022 precision mediump float;
18023 
18024 layout (triangles) in;
18025 layout (triangle_strip, max_vertices = 3) out;
18026 
18027 layout (std140) uniform Input {
18028     float redInput;
18029 };
18030 
18031 out float redValue;
18032 
18033 void main() {
18034     gl_Position = gl_in[0].gl_Position;
18035     redValue = redInput;
18036     EmitVertex();
18037 
18038     gl_Position = gl_in[1].gl_Position;
18039     redValue = redInput;
18040     EmitVertex();
18041 
18042     gl_Position = gl_in[2].gl_Position;
18043     redValue = redInput;
18044     EmitVertex();
18045 
18046     EndPrimitive();
18047 }
18048 )";
18049 
18050     constexpr char kFS[] = R"(#version 310 es
18051 precision mediump float;
18052 
18053 out vec4 fragColor;
18054 
18055 in float redValue;
18056 
18057 void main()
18058 {
18059     fragColor = vec4(redValue, 0., 0., 1.);
18060 })";
18061 
18062     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18063     ASSERT_GL_NO_ERROR();
18064     // Delete the shader and recompile to fetch from cache.
18065     glDeleteProgram(unusedProgram);
18066     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18067     ASSERT_GL_NO_ERROR();
18068     glUseProgram(program);
18069 
18070     constexpr GLfloat kInputData = 1.0f;
18071     GLBuffer input;
18072     glBindBuffer(GL_UNIFORM_BUFFER, input);
18073     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18074     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18075     glUniformBlockBinding(program, kInputIndex, 0);
18076     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18077     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18078     ASSERT_GL_NO_ERROR();
18079 
18080     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18081     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18082 }
18083 
18084 // Test that shader caching maintains SSBO in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithSSBO)18085 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithSSBO)
18086 {
18087     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18088     ANGLE_SKIP_TEST_IF(!IsVulkan());
18089     GLint maxGeometryShaderStorageBlocks = 0;
18090     glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
18091     ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
18092 
18093     constexpr char kGS[] = R"(#version 310 es
18094 #extension GL_EXT_geometry_shader : require
18095 precision mediump float;
18096 
18097 layout (triangles) in;
18098 layout (triangle_strip, max_vertices = 3) out;
18099 
18100 layout (binding = 0, std430) buffer Input {
18101     float redInput;
18102 };
18103 
18104 out float redValue;
18105 
18106 void main() {
18107     gl_Position = gl_in[0].gl_Position;
18108     redValue = redInput;
18109     EmitVertex();
18110 
18111     gl_Position = gl_in[1].gl_Position;
18112     redValue = redInput;
18113     EmitVertex();
18114 
18115     gl_Position = gl_in[2].gl_Position;
18116     redValue = redInput;
18117     EmitVertex();
18118 
18119     EndPrimitive();
18120 }
18121 )";
18122 
18123     constexpr char kFS[] = R"(#version 310 es
18124 precision mediump float;
18125 
18126 out vec4 fragColor;
18127 
18128 in float redValue;
18129 
18130 void main()
18131 {
18132     fragColor = vec4(redValue, 0., 0., 1.);
18133 })";
18134 
18135     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18136     ASSERT_GL_NO_ERROR();
18137     // Delete the shader and recompile to fetch from cache.
18138     glDeleteProgram(unusedProgram);
18139     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18140     ASSERT_GL_NO_ERROR();
18141     glUseProgram(program);
18142 
18143     constexpr GLfloat kInputData = 1.0f;
18144     GLBuffer input;
18145     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18146     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18147     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18148     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18149     ASSERT_GL_NO_ERROR();
18150 
18151     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18152     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18153 }
18154 
18155 // Test that shader caching maintains the number of invocations in geometry shaders across shader
18156 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithInvocations)18157 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithInvocations)
18158 {
18159     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18160     ANGLE_SKIP_TEST_IF(!IsVulkan());
18161 
18162     constexpr char kGS[] = R"(#version 310 es
18163 #extension GL_EXT_geometry_shader : require
18164 precision mediump float;
18165 
18166 layout (triangles, invocations = 2) in;
18167 layout (triangle_strip, max_vertices = 3) out;
18168 
18169 out float redValue;
18170 
18171 void main() {
18172     float redOut = 0.;
18173     if (gl_InvocationID == 1) {
18174         redOut = 1.;
18175     }
18176 
18177     gl_Position = gl_in[0].gl_Position;
18178     redValue = redOut;
18179     EmitVertex();
18180 
18181     gl_Position = gl_in[1].gl_Position;
18182     redValue = redOut;
18183     EmitVertex();
18184 
18185     gl_Position = gl_in[2].gl_Position;
18186     redValue = redOut;
18187     EmitVertex();
18188 
18189     EndPrimitive();
18190 }
18191 )";
18192 
18193     constexpr char kFS[] = R"(#version 310 es
18194 precision mediump float;
18195 
18196 out vec4 fragColor;
18197 
18198 in float redValue;
18199 
18200 void main()
18201 {
18202     fragColor = vec4(redValue, 0., 0., 1.);
18203 })";
18204 
18205     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18206     ASSERT_GL_NO_ERROR();
18207     // Delete the shader and recompile to fetch from cache.
18208     glDeleteProgram(unusedProgram);
18209     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18210     ASSERT_GL_NO_ERROR();
18211     glUseProgram(program);
18212 
18213     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18214     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18215 }
18216 
18217 // Test that shader caching maintains uniforms in tessellation control shaders across shader
18218 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniform)18219 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniform)
18220 {
18221     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18222     ANGLE_SKIP_TEST_IF(!IsVulkan());
18223 
18224     constexpr char kTCS[] = R"(#version 310 es
18225 #extension GL_EXT_tessellation_shader : require
18226 precision mediump float;
18227 
18228 layout (vertices = 1) out;
18229 
18230 uniform float redInput;
18231 
18232 patch out float redValueCS;
18233 
18234 void main()
18235 {
18236     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18237     gl_TessLevelInner[0] = 1.0;
18238     gl_TessLevelInner[1] = 1.0;
18239     gl_TessLevelOuter[0] = 1.0;
18240     gl_TessLevelOuter[1] = 1.0;
18241     gl_TessLevelOuter[2] = 1.0;
18242     gl_TessLevelOuter[3] = 1.0;
18243 
18244     redValueCS = redInput;
18245 }
18246 
18247 )";
18248 
18249     constexpr char kTES[] = R"(#version 310 es
18250 #extension GL_EXT_tessellation_shader : require
18251 precision mediump float;
18252 
18253 layout (quads, cw, fractional_odd_spacing) in;
18254 
18255 patch in float redValueCS;
18256 
18257 out float redValue;
18258 
18259 void main()
18260 {
18261     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18262 
18263     redValue = redValueCS;
18264 }
18265 )";
18266 
18267     constexpr char kFS[] = R"(#version 310 es
18268 precision mediump float;
18269 
18270 out vec4 fragColor;
18271 
18272 in float redValue;
18273 
18274 void main()
18275 {
18276     fragColor = vec4(redValue, 0., 0., 1.);
18277 })";
18278 
18279     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18280     ASSERT_GL_NO_ERROR();
18281     // Delete the shader and recompile to fetch from cache.
18282     glDeleteProgram(unusedProgram);
18283     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18284     ASSERT_GL_NO_ERROR();
18285     glUseProgram(program);
18286 
18287     constexpr GLfloat kRedValue = 1.0f;
18288     int redInputLocation        = glGetUniformLocation(program, "redInput");
18289     glUniform1f(redInputLocation, kRedValue);
18290     ASSERT_GL_NO_ERROR();
18291 
18292     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18293     ASSERT_GL_NO_ERROR();
18294 
18295     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18296 }
18297 
18298 // Test that shader caching maintains uniform blocks in tessellation control shaders across shader
18299 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniformBlock)18300 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniformBlock)
18301 {
18302     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18303     ANGLE_SKIP_TEST_IF(!IsVulkan());
18304 
18305     constexpr char kTCS[] = R"(#version 310 es
18306 #extension GL_EXT_tessellation_shader : require
18307 precision mediump float;
18308 
18309 layout (vertices = 1) out;
18310 
18311 layout (std140) uniform Input {
18312     float redInput;
18313 };
18314 
18315 patch out float redValueCS;
18316 
18317 void main()
18318 {
18319     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18320     gl_TessLevelInner[0] = 1.0;
18321     gl_TessLevelInner[1] = 1.0;
18322     gl_TessLevelOuter[0] = 1.0;
18323     gl_TessLevelOuter[1] = 1.0;
18324     gl_TessLevelOuter[2] = 1.0;
18325     gl_TessLevelOuter[3] = 1.0;
18326 
18327     redValueCS = redInput;
18328 }
18329 
18330 )";
18331 
18332     constexpr char kTES[] = R"(#version 310 es
18333 #extension GL_EXT_tessellation_shader : require
18334 precision mediump float;
18335 
18336 layout (quads, cw, fractional_odd_spacing) in;
18337 
18338 patch in float redValueCS;
18339 
18340 out float redValue;
18341 
18342 void main()
18343 {
18344     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18345 
18346     redValue = redValueCS;
18347 }
18348 )";
18349 
18350     constexpr char kFS[] = R"(#version 310 es
18351 precision mediump float;
18352 
18353 out vec4 fragColor;
18354 
18355 in float redValue;
18356 
18357 void main()
18358 {
18359     fragColor = vec4(redValue, 0., 0., 1.);
18360 })";
18361 
18362     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18363     ASSERT_GL_NO_ERROR();
18364     // Delete the shader and recompile to fetch from cache.
18365     glDeleteProgram(unusedProgram);
18366     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18367     ASSERT_GL_NO_ERROR();
18368     glUseProgram(program);
18369 
18370     constexpr GLfloat kInputData = 1.0f;
18371     GLBuffer input;
18372     glBindBuffer(GL_UNIFORM_BUFFER, input);
18373     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18374     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18375     glUniformBlockBinding(program, kInputIndex, 0);
18376     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18377     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18378     ASSERT_GL_NO_ERROR();
18379 
18380     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18381     ASSERT_GL_NO_ERROR();
18382 
18383     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18384 }
18385 
18386 // Test that shader caching maintains SSBOs in tessellation control shaders across shader
18387 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithSSBO)18388 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithSSBO)
18389 {
18390     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18391     ANGLE_SKIP_TEST_IF(!IsVulkan());
18392     GLint maxTessControlShaderStorageBlocks;
18393     glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT,
18394                   &maxTessControlShaderStorageBlocks);
18395     ANGLE_SKIP_TEST_IF(maxTessControlShaderStorageBlocks == 0);
18396 
18397     constexpr char kTCS[] = R"(#version 310 es
18398 #extension GL_EXT_tessellation_shader : require
18399 precision mediump float;
18400 
18401 layout (vertices = 1) out;
18402 
18403 layout (binding = 0, std430) buffer Input {
18404     float redInput;
18405 };
18406 
18407 patch out float redValueCS;
18408 
18409 void main()
18410 {
18411     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18412     gl_TessLevelInner[0] = 1.0;
18413     gl_TessLevelInner[1] = 1.0;
18414     gl_TessLevelOuter[0] = 1.0;
18415     gl_TessLevelOuter[1] = 1.0;
18416     gl_TessLevelOuter[2] = 1.0;
18417     gl_TessLevelOuter[3] = 1.0;
18418 
18419     redValueCS = redInput;
18420 }
18421 
18422 )";
18423 
18424     constexpr char kTES[] = R"(#version 310 es
18425 #extension GL_EXT_tessellation_shader : require
18426 precision mediump float;
18427 
18428 layout (quads, cw, fractional_odd_spacing) in;
18429 
18430 patch in float redValueCS;
18431 
18432 out float redValue;
18433 
18434 void main()
18435 {
18436     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18437 
18438     redValue = redValueCS;
18439 }
18440 )";
18441 
18442     constexpr char kFS[] = R"(#version 310 es
18443 precision mediump float;
18444 
18445 out vec4 fragColor;
18446 
18447 in float redValue;
18448 
18449 void main()
18450 {
18451     fragColor = vec4(redValue, 0., 0., 1.);
18452 })";
18453 
18454     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18455     ASSERT_GL_NO_ERROR();
18456     // Delete the shader and recompile to fetch from cache.
18457     glDeleteProgram(unusedProgram);
18458     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18459     ASSERT_GL_NO_ERROR();
18460     glUseProgram(program);
18461 
18462     constexpr GLfloat kInputData = 1.0f;
18463     GLBuffer input;
18464     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18465     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18466     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18467     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18468     ASSERT_GL_NO_ERROR();
18469 
18470     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18471     ASSERT_GL_NO_ERROR();
18472 
18473     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18474 }
18475 
18476 // Test that shader caching maintains uniforms in tessellation evaluation shaders across shader
18477 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniform)18478 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniform)
18479 {
18480     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18481     ANGLE_SKIP_TEST_IF(!IsVulkan());
18482 
18483     constexpr char kTCS[] = R"(#version 310 es
18484 #extension GL_EXT_tessellation_shader : require
18485 precision mediump float;
18486 
18487 layout (vertices = 1) out;
18488 
18489 void main()
18490 {
18491     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18492     gl_TessLevelInner[0] = 1.0;
18493     gl_TessLevelInner[1] = 1.0;
18494     gl_TessLevelOuter[0] = 1.0;
18495     gl_TessLevelOuter[1] = 1.0;
18496     gl_TessLevelOuter[2] = 1.0;
18497     gl_TessLevelOuter[3] = 1.0;
18498 }
18499 
18500 )";
18501 
18502     constexpr char kTES[] = R"(#version 310 es
18503 #extension GL_EXT_tessellation_shader : require
18504 precision mediump float;
18505 
18506 layout (quads, cw, fractional_odd_spacing) in;
18507 
18508 uniform float redInput;
18509 
18510 out float redValue;
18511 
18512 void main()
18513 {
18514     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18515 
18516     redValue = redInput;
18517 }
18518 )";
18519 
18520     constexpr char kFS[] = R"(#version 310 es
18521 precision mediump float;
18522 
18523 out vec4 fragColor;
18524 
18525 in float redValue;
18526 
18527 void main()
18528 {
18529     fragColor = vec4(redValue, 0., 0., 1.);
18530 })";
18531 
18532     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18533     ASSERT_GL_NO_ERROR();
18534     // Delete the shader and recompile to fetch from cache.
18535     glDeleteProgram(unusedProgram);
18536     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18537     ASSERT_GL_NO_ERROR();
18538     glUseProgram(program);
18539 
18540     constexpr GLfloat kRedValue = 1.0f;
18541     int redInputLocation        = glGetUniformLocation(program, "redInput");
18542     glUniform1f(redInputLocation, kRedValue);
18543     ASSERT_GL_NO_ERROR();
18544 
18545     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18546     ASSERT_GL_NO_ERROR();
18547 
18548     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18549 }
18550 
18551 // Test that shader caching maintains uniform blocks in tessellation evaluation shaders across
18552 // shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniformBlock)18553 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniformBlock)
18554 {
18555     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18556     ANGLE_SKIP_TEST_IF(!IsVulkan());
18557 
18558     constexpr char kTCS[] = R"(#version 310 es
18559 #extension GL_EXT_tessellation_shader : require
18560 precision mediump float;
18561 
18562 layout (vertices = 1) out;
18563 
18564 void main()
18565 {
18566     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18567     gl_TessLevelInner[0] = 1.0;
18568     gl_TessLevelInner[1] = 1.0;
18569     gl_TessLevelOuter[0] = 1.0;
18570     gl_TessLevelOuter[1] = 1.0;
18571     gl_TessLevelOuter[2] = 1.0;
18572     gl_TessLevelOuter[3] = 1.0;
18573 }
18574 
18575 )";
18576 
18577     constexpr char kTES[] = R"(#version 310 es
18578 #extension GL_EXT_tessellation_shader : require
18579 precision mediump float;
18580 
18581 layout (quads, cw, fractional_odd_spacing) in;
18582 
18583 layout (std140) uniform Input {
18584     float redInput;
18585 };
18586 
18587 out float redValue;
18588 
18589 void main()
18590 {
18591     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18592 
18593     redValue = redInput;
18594 }
18595 )";
18596 
18597     constexpr char kFS[] = R"(#version 310 es
18598 precision mediump float;
18599 
18600 out vec4 fragColor;
18601 
18602 in float redValue;
18603 
18604 void main()
18605 {
18606     fragColor = vec4(redValue, 0., 0., 1.);
18607 })";
18608 
18609     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18610     ASSERT_GL_NO_ERROR();
18611     // Delete the shader and recompile to fetch from cache.
18612     glDeleteProgram(unusedProgram);
18613     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18614     ASSERT_GL_NO_ERROR();
18615     glUseProgram(program);
18616 
18617     constexpr GLfloat kInputData = 1.0f;
18618     GLBuffer input;
18619     glBindBuffer(GL_UNIFORM_BUFFER, input);
18620     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18621     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18622     glUniformBlockBinding(program, kInputIndex, 0);
18623     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18624     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18625     ASSERT_GL_NO_ERROR();
18626 
18627     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18628     ASSERT_GL_NO_ERROR();
18629 
18630     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18631 }
18632 
18633 // Test that shader caching maintains SSBOs in tessellation evaluation shaders across shader
18634 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithSSBO)18635 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithSSBO)
18636 {
18637     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18638     ANGLE_SKIP_TEST_IF(!IsVulkan());
18639     GLint maxTessEvalShaderStorageBlocks;
18640     glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT,
18641                   &maxTessEvalShaderStorageBlocks);
18642     ANGLE_SKIP_TEST_IF(maxTessEvalShaderStorageBlocks == 0);
18643 
18644     constexpr char kTCS[] = R"(#version 310 es
18645 #extension GL_EXT_tessellation_shader : require
18646 precision mediump float;
18647 
18648 layout (vertices = 1) out;
18649 
18650 void main()
18651 {
18652     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18653     gl_TessLevelInner[0] = 1.0;
18654     gl_TessLevelInner[1] = 1.0;
18655     gl_TessLevelOuter[0] = 1.0;
18656     gl_TessLevelOuter[1] = 1.0;
18657     gl_TessLevelOuter[2] = 1.0;
18658     gl_TessLevelOuter[3] = 1.0;
18659 }
18660 
18661 )";
18662 
18663     constexpr char kTES[] = R"(#version 310 es
18664 #extension GL_EXT_tessellation_shader : require
18665 precision mediump float;
18666 
18667 layout (quads, cw, fractional_odd_spacing) in;
18668 
18669 layout (binding = 0, std430) buffer Input {
18670     float redInput;
18671 };
18672 
18673 out float redValue;
18674 
18675 void main()
18676 {
18677     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18678 
18679     redValue = redInput;
18680 }
18681 )";
18682 
18683     constexpr char kFS[] = R"(#version 310 es
18684 precision mediump float;
18685 
18686 out vec4 fragColor;
18687 
18688 in float redValue;
18689 
18690 void main()
18691 {
18692     fragColor = vec4(redValue, 0., 0., 1.);
18693 })";
18694 
18695     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18696     ASSERT_GL_NO_ERROR();
18697     // Delete the shader and recompile to fetch from cache.
18698     glDeleteProgram(unusedProgram);
18699     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18700     ASSERT_GL_NO_ERROR();
18701     glUseProgram(program);
18702 
18703     constexpr GLfloat kInputData = 1.0f;
18704     GLBuffer input;
18705     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18706     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18707     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18708     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18709     ASSERT_GL_NO_ERROR();
18710 
18711     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18712     ASSERT_GL_NO_ERROR();
18713 
18714     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18715 }
18716 
18717 // Test that only macros for ESSL 1.0 compatible extensions are defined
TEST_P(GLSLTest,ESSL1ExtensionMacros)18718 TEST_P(GLSLTest, ESSL1ExtensionMacros)
18719 {
18720     std::string fs = essl1_shaders::fs::Red();
18721     fs += ExpectedExtensionMacros({
18722         "GL_ANGLE_multi_draw",
18723         "GL_APPLE_clip_distance",
18724         "GL_ARB_texture_rectangle",
18725         "GL_ARM_shader_framebuffer_fetch",
18726         "GL_EXT_blend_func_extended",
18727         "GL_EXT_draw_buffers",
18728         "GL_EXT_frag_depth",
18729         "GL_EXT_separate_shader_objects",
18730         "GL_EXT_shader_framebuffer_fetch_non_coherent",
18731         "GL_EXT_shader_framebuffer_fetch",
18732         "GL_EXT_shader_non_constant_global_initializers",
18733         "GL_EXT_shader_texture_lod",
18734         "GL_EXT_shadow_samplers",
18735         "GL_KHR_blend_equation_advanced",
18736         "GL_NV_EGL_stream_consumer_external",
18737         "GL_NV_shader_framebuffer_fetch",
18738         "GL_OES_EGL_image_external",
18739         "GL_OES_standard_derivatives",
18740         "GL_OES_texture_3D",
18741         "GL_WEBGL_video_texture",
18742     });
18743     fs += UnexpectedExtensionMacros({
18744         "GL_ANDROID_extension_pack_es31a",
18745         "GL_ANGLE_base_vertex_base_instance_shader_builtin",
18746         "GL_ANGLE_clip_cull_distance",
18747         "GL_ANGLE_shader_pixel_local_storage",
18748         "GL_ANGLE_texture_multisample",
18749         "GL_EXT_clip_cull_distance",
18750         "GL_EXT_geometry_shader",
18751         "GL_EXT_gpu_shader5",
18752         "GL_EXT_primitive_bounding_box",
18753         "GL_EXT_shader_io_blocks",
18754         "GL_EXT_tessellation_shader",
18755         "GL_EXT_texture_buffer",
18756         "GL_EXT_texture_cube_map_array",
18757         "GL_EXT_YUV_target",
18758         "GL_NV_shader_noperspective_interpolation",
18759         "GL_OES_EGL_image_external_essl3",
18760         "GL_OES_geometry_shader",
18761         "GL_OES_primitive_bounding_box",
18762         "GL_OES_sample_variables",
18763         "GL_OES_shader_image_atomic",
18764         "GL_OES_shader_io_blocks",
18765         "GL_OES_shader_multisample_interpolation",
18766         "GL_OES_texture_buffer",
18767         "GL_OES_texture_cube_map_array",
18768         "GL_OES_texture_storage_multisample_2d_array",
18769         "GL_OVR_multiview",
18770         "GL_OVR_multiview2",
18771     });
18772     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs.c_str());
18773     ASSERT_GL_NO_ERROR();
18774 }
18775 
18776 // Test that only macros for ESSL 3.0 compatible extensions are defined
TEST_P(GLSLTest_ES3,ESSL3ExtensionMacros)18777 TEST_P(GLSLTest_ES3, ESSL3ExtensionMacros)
18778 {
18779     std::string fs = essl3_shaders::fs::Red();
18780     fs += ExpectedExtensionMacros({
18781         "GL_ANGLE_base_vertex_base_instance_shader_builtin",
18782         "GL_ANGLE_clip_cull_distance",
18783         "GL_ANGLE_multi_draw",
18784         "GL_ANGLE_shader_pixel_local_storage",
18785         "GL_ANGLE_texture_multisample",
18786         "GL_APPLE_clip_distance",
18787         "GL_ARB_texture_rectangle",
18788         "GL_ARM_shader_framebuffer_fetch",
18789         "GL_EXT_blend_func_extended",
18790         "GL_EXT_clip_cull_distance",
18791         "GL_EXT_separate_shader_objects",
18792         "GL_EXT_shader_framebuffer_fetch_non_coherent",
18793         "GL_EXT_shader_framebuffer_fetch",
18794         "GL_EXT_shader_non_constant_global_initializers",
18795         "GL_EXT_YUV_target",
18796         "GL_KHR_blend_equation_advanced",
18797         "GL_NV_EGL_stream_consumer_external",
18798         "GL_NV_shader_noperspective_interpolation",
18799         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18800         "GL_OES_EGL_image_external",
18801         "GL_OES_EGL_image_external_essl3",
18802         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18803         "GL_OES_texture_3D",
18804         "GL_OES_sample_variables",
18805         "GL_OES_shader_multisample_interpolation",
18806         "GL_OVR_multiview",
18807         "GL_OVR_multiview2",
18808         "GL_WEBGL_video_texture",
18809     });
18810     fs += UnexpectedExtensionMacros({
18811         "GL_ANDROID_extension_pack_es31a",
18812         "GL_EXT_draw_buffers",
18813         "GL_EXT_frag_depth",
18814         "GL_EXT_geometry_shader",
18815         "GL_EXT_gpu_shader5",
18816         "GL_EXT_primitive_bounding_box",
18817         "GL_EXT_shader_io_blocks",
18818         "GL_EXT_shader_texture_lod",
18819         "GL_EXT_shadow_samplers",
18820         "GL_EXT_tessellation_shader",
18821         "GL_EXT_texture_buffer",
18822         "GL_EXT_texture_cube_map_array",
18823         "GL_NV_shader_framebuffer_fetch",
18824         "GL_OES_geometry_shader",
18825         "GL_OES_primitive_bounding_box",
18826         "GL_OES_shader_image_atomic",
18827         "GL_OES_shader_io_blocks",
18828         "GL_OES_standard_derivatives",
18829         "GL_OES_texture_buffer",
18830         "GL_OES_texture_cube_map_array",
18831         "GL_OES_texture_storage_multisample_2d_array",
18832     });
18833     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.c_str());
18834     ASSERT_GL_NO_ERROR();
18835 }
18836 
18837 // Test that only macros for ESSL 3.1 compatible extensions are defined
TEST_P(GLSLTest_ES31,ESSL31ExtensionMacros)18838 TEST_P(GLSLTest_ES31, ESSL31ExtensionMacros)
18839 {
18840     std::string fs = essl31_shaders::fs::Red();
18841     fs += ExpectedExtensionMacros({
18842         "GL_ANDROID_extension_pack_es31a",
18843         "GL_ANGLE_base_vertex_base_instance_shader_builtin",
18844         "GL_ANGLE_clip_cull_distance",
18845         "GL_ANGLE_multi_draw",
18846         "GL_ANGLE_shader_pixel_local_storage",
18847         "GL_ANGLE_texture_multisample",
18848         "GL_APPLE_clip_distance",
18849         "GL_ARB_texture_rectangle",
18850         "GL_ARM_shader_framebuffer_fetch",
18851         "GL_EXT_blend_func_extended",
18852         "GL_EXT_clip_cull_distance",
18853         "GL_EXT_geometry_shader",
18854         "GL_EXT_gpu_shader5",
18855         "GL_EXT_primitive_bounding_box",
18856         "GL_EXT_separate_shader_objects",
18857         "GL_EXT_shader_framebuffer_fetch_non_coherent",
18858         "GL_EXT_shader_framebuffer_fetch",
18859         "GL_EXT_shader_io_blocks",
18860         "GL_EXT_shader_non_constant_global_initializers",
18861         "GL_EXT_tessellation_shader",
18862         "GL_EXT_texture_buffer",
18863         "GL_EXT_texture_cube_map_array",
18864         "GL_EXT_YUV_target",
18865         "GL_KHR_blend_equation_advanced",
18866         "GL_NV_EGL_stream_consumer_external",
18867         "GL_NV_shader_noperspective_interpolation",
18868         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18869         "GL_OES_EGL_image_external",
18870         "GL_OES_EGL_image_external_essl3",
18871         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18872         "GL_OES_texture_3D",
18873         "GL_OES_geometry_shader",
18874         "GL_OES_primitive_bounding_box",
18875         "GL_OES_sample_variables",
18876         "GL_OES_shader_image_atomic",
18877         "GL_OES_shader_io_blocks",
18878         "GL_OES_shader_multisample_interpolation",
18879         "GL_OES_texture_buffer",
18880         "GL_OES_texture_cube_map_array",
18881         "GL_OES_texture_storage_multisample_2d_array",
18882         "GL_OVR_multiview",
18883         "GL_OVR_multiview2",
18884         "GL_WEBGL_video_texture",
18885     });
18886     fs += UnexpectedExtensionMacros({
18887         "GL_EXT_draw_buffers",
18888         "GL_EXT_frag_depth",
18889         "GL_EXT_shader_texture_lod",
18890         "GL_EXT_shadow_samplers",
18891         "GL_NV_shader_framebuffer_fetch",
18892         "GL_OES_standard_derivatives",
18893     });
18894     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fs.c_str());
18895     ASSERT_GL_NO_ERROR();
18896 }
18897 
18898 // Make sure names starting with webgl_ work.
TEST_P(GLSLTest_ES3,NameWithWebgl)18899 TEST_P(GLSLTest_ES3, NameWithWebgl)
18900 {
18901     constexpr char kFS[] = R"(#version 300 es
18902 out highp vec4 webgl_color;
18903 void main()
18904 {
18905   webgl_color = vec4(0, 1, 0, 1);
18906 })";
18907 
18908     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
18909     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18910     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
18911 }
18912 
18913 // Make sure webgl_FragColor works.
TEST_P(GLSLTest_ES3,NameWithWebglFragColor)18914 TEST_P(GLSLTest_ES3, NameWithWebglFragColor)
18915 {
18916     constexpr char kFS[] = R"(#version 300 es
18917 out highp vec4 webgl_FragColor;
18918 void main()
18919 {
18920   webgl_FragColor = vec4(0, 1, 0, 1);
18921 })";
18922 
18923     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
18924     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18925     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
18926 }
18927 
18928 // Test that the ScalarizeVecAndMatConstructorArgs workaround works correctly with constructors that
18929 // have no precision.  Regression test for a bug where the generated helper has no precision
18930 // specified on the parameters and return value.
TEST_P(GLSLTest,ScalarizeVectorWorkaroundVsPrecisionlessConstructor)18931 TEST_P(GLSLTest, ScalarizeVectorWorkaroundVsPrecisionlessConstructor)
18932 {
18933     constexpr char kFS[] = R"(precision highp float;
18934 void main() {
18935     bool b1 = true;
18936     float f1 = dot(vec4(b1 ? 1.0 : 0.0, 0.0, 0.0, 0.0), vec4(1.0));
18937     gl_FragColor = vec4(f1,0.0,0.0, 1.0);
18938 })";
18939 
18940     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
18941     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18942     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18943 }
18944 
18945 // Test that Metal compiler doesn't inline non-const globals
TEST_P(WebGLGLSLTest,InvalidGlobalsNotInlined)18946 TEST_P(WebGLGLSLTest, InvalidGlobalsNotInlined)
18947 {
18948     constexpr char kFS[] = R"(#version 100
18949   precision highp float;
18950   float v1 = 0.5;
18951   float v2 = v1;
18952 
18953   float f1() {
18954     return v2;
18955   }
18956 
18957   void main() {
18958     gl_FragColor = vec4(v1 + f1(),0.0,0.0, 1.0);
18959   })";
18960     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
18961     ASSERT_GL_NO_ERROR();
18962 }
18963 
18964 // Test that a struct can have lots of fields.  Regression test for an inefficient O(n^2) check for
18965 // fields having unique names.
TEST_P(GLSLTest_ES3,LotsOfFieldsInStruct)18966 TEST_P(GLSLTest_ES3, LotsOfFieldsInStruct)
18967 {
18968     std::ostringstream fs;
18969     fs << R"(#version 300 es
18970 precision highp float;
18971 struct LotsOfFields
18972 {
18973 )";
18974     // Note: 16383 is the SPIR-V limit for struct member count.
18975     for (uint32_t i = 0; i < 16383; ++i)
18976     {
18977         fs << "    float field" << i << ";\n";
18978     }
18979     fs << R"(};
18980 uniform B { LotsOfFields s; };
18981 out vec4 color;
18982 void main() {
18983     color = vec4(s.field0, 0.0, 0.0, 1.0);
18984 })";
18985 
18986     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.str().c_str());
18987 }
18988 
18989 // Test that structs with too many fields are rejected.  In SPIR-V, the instruction that defines the
18990 // struct lists the fields which means the length of the instruction is a function of the field
18991 // count.  Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be
18992 // represented.
TEST_P(GLSLTest_ES3,TooManyFieldsInStruct)18993 TEST_P(GLSLTest_ES3, TooManyFieldsInStruct)
18994 {
18995     std::ostringstream fs;
18996     fs << R"(#version 300 es
18997 precision highp float;
18998 struct TooManyFields
18999 {
19000 )";
19001     for (uint32_t i = 0; i < (1 << 16); ++i)
19002     {
19003         fs << "    float field" << i << ";\n";
19004     }
19005     fs << R"(};
19006 uniform B { TooManyFields s; };
19007 out vec4 color;
19008 void main() {
19009     color = vec4(s.field0, 0.0, 0.0, 1.0);
19010 })";
19011 
19012     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19013     EXPECT_EQ(0u, shader);
19014 }
19015 
19016 // Same as TooManyFieldsInStruct, but with samplers in the struct.
TEST_P(GLSLTest_ES3,TooManySamplerFieldsInStruct)19017 TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct)
19018 {
19019     std::ostringstream fs;
19020     fs << R"(#version 300 es
19021 precision highp float;
19022 struct TooManyFields
19023 {
19024 )";
19025     for (uint32_t i = 0; i < (1 << 16); ++i)
19026     {
19027         fs << "    sampler2D field" << i << ";\n";
19028     }
19029     fs << R"(};
19030 uniform TooManyFields s;
19031 out vec4 color;
19032 void main() {
19033     color = texture(s.field0, vec2(0));
19034 })";
19035 
19036     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19037     EXPECT_EQ(0u, shader);
19038 }
19039 
19040 // More complex variation of ManySamplerFieldsInStruct.  This one compiles fine.
TEST_P(GLSLTest_ES3,ManySamplerFieldsInStructComplex)19041 TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex)
19042 {
19043     // D3D and OpenGL may be more restrictive about this many samplers.
19044     ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19045 
19046     std::ostringstream fs;
19047     fs << R"(#version 300 es
19048 precision highp float;
19049 
19050 struct X {
19051     mediump sampler2D a[0xf00];
19052     mediump sampler2D b[0xf00];
19053     mediump sampler2D c[0xf000];
19054     mediump sampler2D d[0xf00];
19055 };
19056 
19057 struct Y {
19058   X s1;
19059   mediump sampler2D a[0xf00];
19060   mediump sampler2D b[0xf000];
19061   mediump sampler2D c[0x14000];
19062 };
19063 
19064 struct S {
19065     Y s1;
19066 };
19067 
19068 struct structBuffer { S s; };
19069 
19070 uniform structBuffer b;
19071 
19072 out vec4 color;
19073 void main()
19074 {
19075     color = texture(b.s.s1.s1.c[0], vec2(0));
19076 })";
19077 
19078     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19079     EXPECT_NE(0u, shader);
19080 }
19081 
19082 // Make sure a large array of samplers works.
TEST_P(GLSLTest,ManySamplers)19083 TEST_P(GLSLTest, ManySamplers)
19084 {
19085     // D3D and OpenGL may be more restrictive about this many samplers.
19086     ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19087 
19088     std::ostringstream fs;
19089     fs << R"(precision highp float;
19090 
19091 uniform mediump sampler2D c[0x12000];
19092 
19093 void main()
19094 {
19095     gl_FragColor = texture2D(c[0], vec2(0));
19096 })";
19097 
19098     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19099     EXPECT_NE(0u, shader);
19100 }
19101 
19102 // Make sure a large array of samplers works when declared in a struct.
TEST_P(GLSLTest,ManySamplersInStruct)19103 TEST_P(GLSLTest, ManySamplersInStruct)
19104 {
19105     // D3D and OpenGL may be more restrictive about this many samplers.
19106     ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19107 
19108     std::ostringstream fs;
19109     fs << R"(precision highp float;
19110 
19111 struct X {
19112     mediump sampler2D c[0x12000];
19113 };
19114 
19115 uniform X x;
19116 
19117 void main()
19118 {
19119     gl_FragColor = texture2D(x.c[0], vec2(0));
19120 })";
19121 
19122     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19123     EXPECT_NE(0u, shader);
19124 }
19125 
19126 // Test that passing large arrays to functions are compiled correctly.  Regression test for the
19127 // SPIR-V generator that made a copy of the array to pass to the function, by decomposing and
19128 // reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a
19129 // length higher than can fit in SPIR-V.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayPassedToFunction)19130 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayPassedToFunction)
19131 {
19132     constexpr char kFS[] = R"(#version 300 es
19133 precision highp float;
19134 uniform Large { float a[65536]; };
19135 float f(float b[65536])
19136 {
19137     b[0] = 1.0;
19138     return b[0] + b[1];
19139 }
19140 out vec4 color;
19141 void main() {
19142     color = vec4(f(a), 0.0, 0.0, 1.0);
19143 })";
19144 
19145     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19146     EXPECT_EQ(0u, shader);
19147 }
19148 
19149 // Make sure the shader in LargeInterfaceBlockArrayPassedToFunction works if the large local is
19150 // avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArray)19151 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArray)
19152 {
19153     int maxUniformBlockSize = 0;
19154     glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19155     ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19156 
19157     constexpr char kFS[] = R"(#version 300 es
19158 precision highp float;
19159 uniform Large { float a[16384]; };
19160 out vec4 color;
19161 void main() {
19162     color = vec4(a[0], 0.0, 0.0, 1.0);
19163 })";
19164 
19165     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19166 }
19167 
19168 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayPassedToFunction)19169 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayPassedToFunction)
19170 {
19171     constexpr char kFS[] = R"(#version 300 es
19172 precision highp float;
19173 struct S { float a[65536]; };
19174 uniform Large { S s; };
19175 float f(float b[65536])
19176 {
19177     b[0] = 1.0;
19178     return b[0] + b[1];
19179 }
19180 out vec4 color;
19181 void main() {
19182     color = vec4(f(s.a), 0.0, 0.0, 1.0);
19183 })";
19184 
19185     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19186     EXPECT_EQ(0u, shader);
19187 }
19188 
19189 // Make sure the shader in LargeInterfaceBlockNestedArrayPassedToFunction works if the large local
19190 // is avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArray)19191 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArray)
19192 {
19193     int maxUniformBlockSize = 0;
19194     glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19195     ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19196 
19197     constexpr char kFS[] = R"(#version 300 es
19198 precision highp float;
19199 struct S { float a[16384]; };
19200 uniform Large { S s; };
19201 out vec4 color;
19202 void main() {
19203     color = vec4(s.a[0], 0.0, 0.0, 1.0);
19204 })";
19205 
19206     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19207 }
19208 
19209 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local
19210 // variable instead.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayCopiedToLocal)19211 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayCopiedToLocal)
19212 {
19213     constexpr char kFS[] = R"(#version 300 es
19214 precision highp float;
19215 uniform Large { float a[65536]; };
19216 out vec4 color;
19217 void main() {
19218     float b[65536] = a;
19219     color = vec4(b[0], 0.0, 0.0, 1.0);
19220 })";
19221 
19222     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19223     EXPECT_EQ(0u, shader);
19224 }
19225 
19226 // Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayCopiedToLocal)19227 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayCopiedToLocal)
19228 {
19229     constexpr char kFS[] = R"(#version 300 es
19230 precision highp float;
19231 struct S { float a[65536]; };
19232 uniform Large { S s; };
19233 out vec4 color;
19234 void main() {
19235     S s2 = s;
19236     color = vec4(s2.a[0], 0.0, 0.0, 1.0);
19237 })";
19238 
19239     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19240     EXPECT_EQ(0u, shader);
19241 }
19242 
19243 // Test that too large varyings are rejected.
TEST_P(GLSLTest_ES3,LargeArrayVarying)19244 TEST_P(GLSLTest_ES3, LargeArrayVarying)
19245 {
19246     constexpr char kFS[] = R"(#version 300 es
19247 precision highp float;
19248 in float a[65536];
19249 out vec4 color;
19250 void main() {
19251     color = vec4(a[0], 0.0, 0.0, 1.0);
19252 })";
19253 
19254     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19255     EXPECT_EQ(0u, shader);
19256 }
19257 
19258 // Regression test for const globals losing const qualifiers during MSL
19259 // translation and exceeding available temporary registers on Apple GPUs.
TEST_P(GLSLTest_ES3,LargeConstGlobalArraysOfStructs)19260 TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs)
19261 {
19262     const int n = 128;
19263     std::stringstream fragmentShader;
19264     fragmentShader << "#version 300 es\n"
19265                    << "precision mediump float;\n"
19266                    << "uniform mediump int zero;\n"
19267                    << "out vec4 color;\n"
19268                    << "struct S { vec3 A; vec3 B; float C; };\n";
19269     for (int i = 0; i < 3; ++i)
19270     {
19271         fragmentShader << "const S s" << i << "[" << n << "] = S[" << n << "](\n";
19272         for (int j = 0; j < n; ++j)
19273         {
19274             fragmentShader << "  S(vec3(0., 1., 0.), vec3(" << j << "), 0.)"
19275                            << (j != n - 1 ? ",\n" : "\n");
19276         }
19277         fragmentShader << ");\n";
19278     }
19279     // To ensure that the array is not rescoped, it must be accessed from two functions.
19280     // To ensure that the array is not optimized out, it must be accessed with a dynamic index.
19281     fragmentShader << "vec4 foo() {\n"
19282                    << "  return vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
19283                    << "}\n"
19284                    << "void main() {\n"
19285                    << "  color = foo() * vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
19286                    << "}\n";
19287     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader.str().c_str());
19288 
19289     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
19290     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19291     ASSERT_GL_NO_ERROR();
19292 }
19293 
19294 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest,FramebufferFetchDoesNotAddUniforms)19295 TEST_P(GLSLTest, FramebufferFetchDoesNotAddUniforms)
19296 {
19297     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
19298     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers"));
19299 
19300     static constexpr char kFS[] = R"(#version 100
19301 #extension GL_EXT_shader_framebuffer_fetch : require
19302 #extension GL_EXT_draw_buffers : require
19303 uniform highp vec4 u_color;
19304 
19305 void main (void)
19306 {
19307     gl_FragData[0] = gl_LastFragData[0] + u_color;
19308     gl_FragData[1] = gl_LastFragData[1] + u_color;
19309     gl_FragData[2] = gl_LastFragData[2] + u_color;
19310     gl_FragData[3] = gl_LastFragData[3] + u_color;
19311 })";
19312 
19313     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19314     glUseProgram(program);
19315 
19316     GLint activeUniforms = 0, uniformsMaxLength = 0;
19317     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
19318     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
19319 
19320     // There should be only one active uniform
19321     EXPECT_EQ(activeUniforms, 1);
19322 
19323     // And that is u_color
19324     GLsizei nameLen = uniformsMaxLength;
19325     std::vector<char> name(uniformsMaxLength);
19326 
19327     GLint size;
19328     GLenum type;
19329 
19330     glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
19331     EXPECT_EQ(std::string(name.data()), "u_color");
19332     EXPECT_EQ(size, 1);
19333     EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
19334 }
19335 
19336 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,FramebufferFetchDoesNotAddUniforms)19337 TEST_P(GLSLTest_ES31, FramebufferFetchDoesNotAddUniforms)
19338 {
19339     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
19340 
19341     static constexpr char kFS[] = R"(#version 310 es
19342 #extension GL_EXT_shader_framebuffer_fetch : require
19343 layout(location = 0) inout highp vec4 o_color;
19344 
19345 layout(std140, binding = 0) buffer outBlock {
19346     highp vec4 data[256];
19347 };
19348 
19349 uniform highp vec4 u_color;
19350 void main (void)
19351 {
19352     uint index = uint(gl_FragCoord.y) * 16u + uint(gl_FragCoord.x);
19353     data[index] = o_color;
19354     o_color += u_color;
19355 })";
19356 
19357     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
19358     glUseProgram(program);
19359 
19360     GLint activeUniforms = 0, uniformsMaxLength = 0;
19361     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
19362     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
19363 
19364     // There should be only one active uniform
19365     EXPECT_EQ(activeUniforms, 1);
19366 
19367     // And that is u_color
19368     GLsizei nameLen = uniformsMaxLength;
19369     std::vector<char> name(uniformsMaxLength);
19370 
19371     GLint size;
19372     GLenum type;
19373 
19374     glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
19375     EXPECT_EQ(std::string(name.data()), "u_color");
19376     EXPECT_EQ(size, 1);
19377     EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
19378 }
19379 
19380 // Test that advanced blend emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,AdvancedBlendEquationsDoesNotAddUniforms)19381 TEST_P(GLSLTest_ES31, AdvancedBlendEquationsDoesNotAddUniforms)
19382 {
19383     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
19384 
19385     static constexpr char kFS[] = R"(#version 310 es
19386 #extension GL_KHR_blend_equation_advanced : require
19387 
19388 layout (blend_support_multiply) out;
19389 
19390 out highp vec4 o_color;
19391 
19392 layout(std140, binding = 0) buffer outBlock {
19393     highp vec4 data[256];
19394 };
19395 
19396 uniform highp vec4 u_color;
19397 void main (void)
19398 {
19399     o_color = u_color;
19400 })";
19401 
19402     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
19403     glUseProgram(program);
19404 
19405     GLint activeUniforms = 0, uniformsMaxLength = 0;
19406     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
19407     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
19408 
19409     // There should be only one active uniform
19410     EXPECT_EQ(activeUniforms, 1);
19411 
19412     // And that is u_color
19413     GLsizei nameLen = uniformsMaxLength;
19414     std::vector<char> name(uniformsMaxLength);
19415 
19416     GLint size;
19417     GLenum type;
19418 
19419     glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
19420     EXPECT_EQ(std::string(name.data()), "u_color");
19421     EXPECT_EQ(size, 1);
19422     EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
19423 }
19424 
19425 // Tests struct in function return type.
TEST_P(GLSLTest,StructInFunctionDefinition)19426 TEST_P(GLSLTest, StructInFunctionDefinition)
19427 {
19428     const char kFragmentShader[] = R"(precision mediump float;
19429 struct Foo
19430 {
19431     float v;
19432 };
19433 
19434 Foo foo()
19435 {
19436     Foo f;
19437     f.v = 0.5;
19438     return f;
19439 }
19440 
19441 void main()
19442 {
19443     gl_FragColor = vec4(1, 0, 0, 1);
19444     Foo f = foo();
19445     if (f.v == 0.5)
19446     {
19447         gl_FragColor = vec4(0, 1, 0, 1);
19448     }
19449 })";
19450 
19451     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19452     glUseProgram(program);
19453 
19454     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19455     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19456 }
19457 
19458 // Tests struct definition in function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionDefinition)19459 TEST_P(GLSLTest, StructDefinitionInFunctionDefinition)
19460 {
19461     const char kFragmentShader[] = R"(precision mediump float;
19462 struct Foo { float v; } foo()
19463 {
19464     Foo f;
19465     f.v = 0.5;
19466     return f;
19467 }
19468 
19469 void main()
19470 {
19471     gl_FragColor = vec4(1, 0, 0, 1);
19472     Foo f = foo();
19473     if (f.v == 0.5)
19474     {
19475         gl_FragColor = vec4(0, 1, 0, 1);
19476     }
19477 })";
19478 
19479     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19480     glUseProgram(program);
19481 
19482     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19483     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19484 }
19485 
19486 // Test struct definition in forward declaration of function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototype)19487 TEST_P(GLSLTest, StructDefinitionInFunctionPrototype)
19488 {
19489     const char kFragmentShader[] = R"(precision mediump float;
19490 struct Foo { float v; } foo();
19491 
19492 void main()
19493 {
19494     gl_FragColor = vec4(1, 0, 0, 1);
19495     Foo f = foo();
19496     if (f.v == 0.5)
19497     {
19498         gl_FragColor = vec4(0, 1, 0, 1);
19499     }
19500 }
19501 
19502 Foo foo()
19503 {
19504     Foo f;
19505     f.v = 0.5;
19506     return f;
19507 })";
19508 
19509     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19510     glUseProgram(program);
19511 
19512     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19513     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19514 }
19515 
19516 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototypeScope)19517 TEST_P(GLSLTest, StructDefinitionInFunctionPrototypeScope)
19518 {
19519     const char kFragmentShader[] = R"(precision mediump float;
19520 
19521 struct Foo { float v; } foo()
19522 {
19523     Foo f;
19524     f.v = 0.5;
19525     return f;
19526 }
19527 
19528 struct Bar { Foo f; } bar()
19529 {
19530     Bar b;
19531     b.f = foo();
19532     return b;
19533 }
19534 
19535 void main()
19536 {
19537     gl_FragColor = vec4(1, 0, 0, 1);
19538     Bar b = bar();
19539     if (b.f.v == 0.5)
19540     {
19541         gl_FragColor = vec4(0, 1, 0, 1);
19542     }
19543 })";
19544 
19545     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19546     glUseProgram(program);
19547 
19548     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19549     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19550 }
19551 
19552 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,NestedReturnedStructs)19553 TEST_P(GLSLTest, NestedReturnedStructs)
19554 {
19555     const char kFragmentShader[] = R"(precision mediump float;
19556 struct Foo { float v; } foo(float bar);
19557 
19558 void main()
19559 {
19560     gl_FragColor = vec4(1, 0, 0, 1);
19561     float v = foo(foo(0.5).v).v;
19562     if (v == 0.5)
19563     {
19564         gl_FragColor = vec4(0, 1, 0, 1);
19565     }
19566 }
19567 
19568 Foo foo(float bar)
19569 {
19570     Foo f;
19571     f.v = bar;
19572     return f;
19573 })";
19574 
19575     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19576     glUseProgram(program);
19577 
19578     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19579     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19580 }
19581 
19582 // Test that double underscores user defined name is allowed
TEST_P(GLSLTest_ES3,DoubleUnderscoresName)19583 TEST_P(GLSLTest_ES3, DoubleUnderscoresName)
19584 {
19585     constexpr char kFS[] = R"(#version 300 es
19586 precision mediump float;
19587 out vec4 oColor;
19588 uniform struct __Data {float red;} data;
19589 void main() {oColor=vec4(data.red,0,1,1);})";
19590 
19591     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19592     glUseProgram(program);
19593     // populate uniform
19594     GLint uniformLocation = glGetUniformLocation(program, "data.red");
19595     EXPECT_NE(uniformLocation, -1);
19596     glUniform1f(uniformLocation, 0);
19597 
19598     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
19599     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
19600     ASSERT_GL_NO_ERROR();
19601 }
19602 
19603 // Test that user defined name starts with "ANGLE" or "ANGLE_"
TEST_P(GLSLTest_ES3,VariableNameStartsWithANGLE)19604 TEST_P(GLSLTest_ES3, VariableNameStartsWithANGLE)
19605 {
19606     constexpr char kFS[] = R"(#version 300 es
19607 precision mediump float;
19608 out vec4 oColor;
19609 uniform struct ANGLEData{float red;} data;
19610 uniform struct ANGLE_Data{float green;} _data;
19611 void main() {oColor=vec4(data.red,_data.green,1,1);})";
19612 
19613     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19614     glUseProgram(program);
19615     // populate uniform
19616     GLint uniformRedLocation   = glGetUniformLocation(program, "data.red");
19617     GLint uniformGreenLocation = glGetUniformLocation(program, "_data.green");
19618     EXPECT_NE(uniformRedLocation, -1);
19619     EXPECT_NE(uniformGreenLocation, -1);
19620     glUniform1f(uniformRedLocation, 0);
19621     glUniform1f(uniformGreenLocation, 0);
19622 
19623     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
19624     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
19625     ASSERT_GL_NO_ERROR();
19626 }
19627 
19628 // Test that underscores in array names work with out arrays.
TEST_P(GLSLTest_ES3,UnderscoresWorkWithOutArrays)19629 TEST_P(GLSLTest_ES3, UnderscoresWorkWithOutArrays)
19630 {
19631     GLuint fbo;
19632     glGenFramebuffers(1, &fbo);
19633     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
19634 
19635     GLuint textures[4];
19636     glGenTextures(4, textures);
19637 
19638     for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
19639     {
19640         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
19641         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
19642                      GL_UNSIGNED_BYTE, nullptr);
19643     }
19644 
19645     GLint maxDrawBuffers;
19646     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
19647     ASSERT_GE(maxDrawBuffers, 4);
19648 
19649     GLuint readFramebuffer;
19650     glGenFramebuffers(1, &readFramebuffer);
19651     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
19652 
19653     constexpr char kFS[] = R"(#version 300 es
19654 precision highp float;
19655 out vec4 _e[4];
19656 void main()
19657 {
19658     _e[0] = vec4(1.0, 0.0, 0.0, 1.0);
19659     _e[1] = vec4(0.0, 1.0, 0.0, 1.0);
19660     _e[2] = vec4(0.0, 0.0, 1.0, 1.0);
19661     _e[3] = vec4(1.0, 1.0, 1.0, 1.0);
19662 }
19663 )";
19664     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19665     GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
19666                          GL_COLOR_ATTACHMENT3};
19667     constexpr GLuint kMaxBuffers = 4;
19668     // Enable all draw buffers.
19669     for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
19670     {
19671         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
19672         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
19673                                textures[texIndex], 0);
19674         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
19675                                textures[texIndex], 0);
19676     }
19677     glDrawBuffers(kMaxBuffers, allBufs);
19678 
19679     // Draw with simple program.
19680     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19681     ASSERT_GL_NO_ERROR();
19682     verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
19683     verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
19684     verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
19685     verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
19686 }
19687 
19688 }  // anonymous namespace
19689 
19690 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
19691     GLSLTest,
19692     ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
19693     ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19694     ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19695     ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
19696     ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
19697     ES3_VULKAN().disable(Feature::SupportsSPIRV14));
19698 
19699 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
19700 
19701 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
19702 ANGLE_INSTANTIATE_TEST_ES3_AND(
19703     GLSLTest_ES3,
19704     ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
19705     ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19706     ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19707     ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
19708     ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
19709     ES3_VULKAN().disable(Feature::SupportsSPIRV14));
19710 
19711 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
19712 ANGLE_INSTANTIATE_TEST_ES3(GLSLTestLoops);
19713 
19714 ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
19715 
19716 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
19717 ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest);
19718 
19719 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
19720 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31,
19721                                 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
19722                                 ES31_VULKAN().disable(Feature::SupportsSPIRV14));
19723 
19724 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
19725 ANGLE_INSTANTIATE_TEST(
19726     GLSLTest_ES31_InitShaderVariables,
19727     ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
19728     ES31_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
19729