• 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 
11 using namespace angle;
12 
13 namespace
14 {
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             sprintf(varyingType, "float");
36         }
37         else
38         {
39             sprintf(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             sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
52         }
53         else
54         {
55             sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id,
56                     arraySize);
57         }
58 
59         return std::string(buff);
60     }
61 
GenerateVectorVaryingSettingCode(GLint vectorSize,GLint arraySize,GLint id)62     std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
63     {
64         std::string returnString;
65         char buff[100];
66 
67         if (arraySize == 1)
68         {
69             sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
70             returnString += buff;
71         }
72         else
73         {
74             for (int i = 0; i < arraySize; i++)
75             {
76                 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i,
77                         GenerateVaryingType(vectorSize).c_str());
78                 returnString += buff;
79             }
80         }
81 
82         return returnString;
83     }
84 
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)85     std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
86     {
87         if (arraySize == 1)
88         {
89             char buff[100];
90             sprintf(buff, "v%d + ", id);
91             return std::string(buff);
92         }
93         else
94         {
95             std::string returnString;
96             for (int i = 0; i < arraySize; i++)
97             {
98                 char buff[100];
99                 sprintf(buff, "v%d[%d] + ", id, i);
100                 returnString += buff;
101             }
102             return returnString;
103         }
104     }
105 
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)106     void GenerateGLSLWithVaryings(GLint floatCount,
107                                   GLint floatArrayCount,
108                                   GLint vec2Count,
109                                   GLint vec2ArrayCount,
110                                   GLint vec3Count,
111                                   GLint vec3ArrayCount,
112                                   GLint vec4Count,
113                                   GLint vec4ArrayCount,
114                                   bool useFragCoord,
115                                   bool usePointCoord,
116                                   bool usePointSize,
117                                   std::string *fragmentShader,
118                                   std::string *vertexShader)
119     {
120         // Generate a string declaring the varyings, to share between the fragment shader and the
121         // vertex shader.
122         std::string varyingDeclaration;
123 
124         unsigned int varyingCount = 0;
125 
126         for (GLint i = 0; i < floatCount; i++)
127         {
128             varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
129             varyingCount += 1;
130         }
131 
132         for (GLint i = 0; i < floatArrayCount; i++)
133         {
134             varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
135             varyingCount += 1;
136         }
137 
138         for (GLint i = 0; i < vec2Count; i++)
139         {
140             varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
141             varyingCount += 1;
142         }
143 
144         for (GLint i = 0; i < vec2ArrayCount; i++)
145         {
146             varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
147             varyingCount += 1;
148         }
149 
150         for (GLint i = 0; i < vec3Count; i++)
151         {
152             varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
153             varyingCount += 1;
154         }
155 
156         for (GLint i = 0; i < vec3ArrayCount; i++)
157         {
158             varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
159             varyingCount += 1;
160         }
161 
162         for (GLint i = 0; i < vec4Count; i++)
163         {
164             varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
165             varyingCount += 1;
166         }
167 
168         for (GLint i = 0; i < vec4ArrayCount; i++)
169         {
170             varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
171             varyingCount += 1;
172         }
173 
174         // Generate the vertex shader
175         vertexShader->clear();
176         vertexShader->append(varyingDeclaration);
177         vertexShader->append("\nvoid main()\n{\n");
178 
179         unsigned int currentVSVarying = 0;
180 
181         for (GLint i = 0; i < floatCount; i++)
182         {
183             vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
184             currentVSVarying += 1;
185         }
186 
187         for (GLint i = 0; i < floatArrayCount; i++)
188         {
189             vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
190             currentVSVarying += 1;
191         }
192 
193         for (GLint i = 0; i < vec2Count; i++)
194         {
195             vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
196             currentVSVarying += 1;
197         }
198 
199         for (GLint i = 0; i < vec2ArrayCount; i++)
200         {
201             vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
202             currentVSVarying += 1;
203         }
204 
205         for (GLint i = 0; i < vec3Count; i++)
206         {
207             vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
208             currentVSVarying += 1;
209         }
210 
211         for (GLint i = 0; i < vec3ArrayCount; i++)
212         {
213             vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
214             currentVSVarying += 1;
215         }
216 
217         for (GLint i = 0; i < vec4Count; i++)
218         {
219             vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
220             currentVSVarying += 1;
221         }
222 
223         for (GLint i = 0; i < vec4ArrayCount; i++)
224         {
225             vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
226             currentVSVarying += 1;
227         }
228 
229         if (usePointSize)
230         {
231             vertexShader->append("gl_PointSize = 1.0;\n");
232         }
233 
234         vertexShader->append("}\n");
235 
236         // Generate the fragment shader
237         fragmentShader->clear();
238         fragmentShader->append("precision highp float;\n");
239         fragmentShader->append(varyingDeclaration);
240         fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
241 
242         unsigned int currentFSVarying = 0;
243 
244         // Make use of the float varyings
245         fragmentShader->append("\tretColor += vec4(");
246 
247         for (GLint i = 0; i < floatCount; i++)
248         {
249             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
250             currentFSVarying += 1;
251         }
252 
253         for (GLint i = 0; i < floatArrayCount; i++)
254         {
255             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
256             currentFSVarying += 1;
257         }
258 
259         fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
260 
261         // Make use of the vec2 varyings
262         fragmentShader->append("\tretColor += vec4(");
263 
264         for (GLint i = 0; i < vec2Count; i++)
265         {
266             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
267             currentFSVarying += 1;
268         }
269 
270         for (GLint i = 0; i < vec2ArrayCount; i++)
271         {
272             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
273             currentFSVarying += 1;
274         }
275 
276         fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
277 
278         // Make use of the vec3 varyings
279         fragmentShader->append("\tretColor += vec4(");
280 
281         for (GLint i = 0; i < vec3Count; i++)
282         {
283             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
284             currentFSVarying += 1;
285         }
286 
287         for (GLint i = 0; i < vec3ArrayCount; i++)
288         {
289             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
290             currentFSVarying += 1;
291         }
292 
293         fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
294 
295         // Make use of the vec4 varyings
296         fragmentShader->append("\tretColor += ");
297 
298         for (GLint i = 0; i < vec4Count; i++)
299         {
300             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
301             currentFSVarying += 1;
302         }
303 
304         for (GLint i = 0; i < vec4ArrayCount; i++)
305         {
306             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
307             currentFSVarying += 1;
308         }
309 
310         fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
311 
312         // Set gl_FragColor, and use special variables if requested
313         fragmentShader->append("\tgl_FragColor = retColor");
314 
315         if (useFragCoord)
316         {
317             fragmentShader->append(" + gl_FragCoord");
318         }
319 
320         if (usePointCoord)
321         {
322             fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
323         }
324 
325         fragmentShader->append(";\n}");
326     }
327 
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)328     void VaryingTestBase(GLint floatCount,
329                          GLint floatArrayCount,
330                          GLint vec2Count,
331                          GLint vec2ArrayCount,
332                          GLint vec3Count,
333                          GLint vec3ArrayCount,
334                          GLint vec4Count,
335                          GLint vec4ArrayCount,
336                          bool useFragCoord,
337                          bool usePointCoord,
338                          bool usePointSize,
339                          bool expectSuccess)
340     {
341         std::string fragmentShaderSource;
342         std::string vertexShaderSource;
343 
344         GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
345                                  vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
346                                  usePointCoord, usePointSize, &fragmentShaderSource,
347                                  &vertexShaderSource);
348 
349         GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
350 
351         if (expectSuccess)
352         {
353             EXPECT_NE(0u, program);
354         }
355         else
356         {
357             EXPECT_EQ(0u, program);
358         }
359     }
360 
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)361     void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
362                                             GLint fragmentUniformCount,
363                                             GLint vertexSamplersCount,
364                                             GLint fragmentSamplersCount,
365                                             bool expectSuccess)
366     {
367         std::stringstream vertexShader;
368         std::stringstream fragmentShader;
369 
370         // Generate the vertex shader
371         vertexShader << "precision mediump float;\n";
372 
373         for (int i = 0; i < vertexUniformCount; i++)
374         {
375             vertexShader << "uniform vec4 v" << i << ";\n";
376         }
377 
378         for (int i = 0; i < vertexSamplersCount; i++)
379         {
380             vertexShader << "uniform sampler2D s" << i << ";\n";
381         }
382 
383         vertexShader << "void main()\n{\n";
384 
385         for (int i = 0; i < vertexUniformCount; i++)
386         {
387             vertexShader << "    gl_Position +=  v" << i << ";\n";
388         }
389 
390         for (int i = 0; i < vertexSamplersCount; i++)
391         {
392             vertexShader << "    gl_Position +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
393         }
394 
395         if (vertexUniformCount == 0 && vertexSamplersCount == 0)
396         {
397             vertexShader << "   gl_Position = vec4(0.0);\n";
398         }
399 
400         vertexShader << "}\n";
401 
402         // Generate the fragment shader
403         fragmentShader << "precision mediump float;\n";
404 
405         for (int i = 0; i < fragmentUniformCount; i++)
406         {
407             fragmentShader << "uniform vec4 v" << i << ";\n";
408         }
409 
410         for (int i = 0; i < fragmentSamplersCount; i++)
411         {
412             fragmentShader << "uniform sampler2D s" << i << ";\n";
413         }
414 
415         fragmentShader << "void main()\n{\n";
416 
417         for (int i = 0; i < fragmentUniformCount; i++)
418         {
419             fragmentShader << "    gl_FragColor +=  v" << i << ";\n";
420         }
421 
422         for (int i = 0; i < fragmentSamplersCount; i++)
423         {
424             fragmentShader << "    gl_FragColor +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
425         }
426 
427         if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
428         {
429             fragmentShader << "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
430         }
431 
432         fragmentShader << "}\n";
433 
434         GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
435 
436         if (expectSuccess)
437         {
438             EXPECT_NE(0u, program);
439         }
440         else
441         {
442             EXPECT_EQ(0u, program);
443         }
444     }
445 
QueryErrorMessage(GLuint program)446     std::string QueryErrorMessage(GLuint program)
447     {
448         GLint infoLogLength;
449         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
450         EXPECT_GL_NO_ERROR();
451 
452         if (infoLogLength >= 1)
453         {
454             std::vector<GLchar> infoLog(infoLogLength);
455             glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
456                                 infoLog.data());
457             EXPECT_GL_NO_ERROR();
458             return infoLog.data();
459         }
460 
461         return "";
462     }
463 
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)464     void validateComponentsInErrorMessage(const char *vertexShader,
465                                           const char *fragmentShader,
466                                           const char *expectedErrorType,
467                                           const char *expectedVariableFullName)
468     {
469         GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
470         GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
471 
472         GLuint program = glCreateProgram();
473         glAttachShader(program, vs);
474         glAttachShader(program, fs);
475         glLinkProgram(program);
476 
477         glDetachShader(program, vs);
478         glDetachShader(program, fs);
479         glDeleteShader(vs);
480         glDeleteShader(fs);
481 
482         const std::string &errorMessage = QueryErrorMessage(program);
483         printf("%s\n", errorMessage.c_str());
484 
485         EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
486         EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
487 
488         glDeleteProgram(program);
489         ASSERT_GL_NO_ERROR();
490     }
491 
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)492     void verifyAttachment2DColor(unsigned int index,
493                                  GLuint textureName,
494                                  GLenum target,
495                                  GLint level,
496                                  GLColor color)
497     {
498         glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
499         ASSERT_GL_NO_ERROR();
500 
501         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
502             << "index " << index;
503     }
504 };
505 
506 class GLSLTestNoValidation : public GLSLTest
507 {
508   public:
GLSLTestNoValidation()509     GLSLTestNoValidation() { setNoErrorEnabled(true); }
510 };
511 
512 class GLSLTest_ES3 : public GLSLTest
513 {};
514 
515 class GLSLTest_ES31 : public GLSLTest
516 {};
517 
BuillBigInitialStackShader(int length)518 std::string BuillBigInitialStackShader(int length)
519 {
520     std::string result;
521     result += "void main() { \n";
522     for (int i = 0; i < length; i++)
523     {
524         result += "  if (true) { \n";
525     }
526     result += "  int temp; \n";
527     for (int i = 0; i <= length; i++)
528     {
529         result += "} \n";
530     }
531     return result;
532 }
533 
TEST_P(GLSLTest,NamelessScopedStructs)534 TEST_P(GLSLTest, NamelessScopedStructs)
535 {
536     constexpr char kFS[] = R"(precision mediump float;
537 void main()
538 {
539     struct
540     {
541         float q;
542     } b;
543 
544     gl_FragColor = vec4(1, 0, 0, 1);
545     gl_FragColor.a += b.q;
546 })";
547 
548     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
549 }
550 
551 // Test that array of fragment shader outputs is processed properly and draws
552 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)553 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
554 {
555     GLuint fbo;
556     glGenFramebuffers(1, &fbo);
557     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
558 
559     GLuint textures[4];
560     glGenTextures(4, textures);
561 
562     for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
563     {
564         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
565         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
566                      GL_UNSIGNED_BYTE, nullptr);
567     }
568 
569     GLint maxDrawBuffers;
570     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
571     ASSERT_GE(maxDrawBuffers, 4);
572 
573     GLuint readFramebuffer;
574     glGenFramebuffers(1, &readFramebuffer);
575     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
576 
577     constexpr char kFS[] = R"(#version 300 es
578 precision highp float;
579 
580 out vec4 frag_color[4];
581 
582 void main()
583 {
584     frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
585     frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
586     frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
587     frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
588 }
589 )";
590 
591     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
592 
593     GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
594                          GL_COLOR_ATTACHMENT3};
595 
596     constexpr GLuint kMaxBuffers = 4;
597 
598     // Enable all draw buffers.
599     for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
600     {
601         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
602         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
603                                textures[texIndex], 0);
604         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
605                                textures[texIndex], 0);
606     }
607     glDrawBuffers(kMaxBuffers, allBufs);
608 
609     // Draw with simple program.
610     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
611     ASSERT_GL_NO_ERROR();
612 
613     verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
614     verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
615     verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
616     verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
617 }
618 
619 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)620 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
621 {
622     constexpr char kFS[] = R"(#version 300 es
623 precision highp float;
624 
625 // Make color0 inactive but specify color1 first.  The Vulkan backend assigns bogus locations when
626 // compiling and fixes it up in SPIR-V.  If color0's location is not fixed, it will return location
627 // 1 (aliasing color1).  This will lead to a Vulkan validation warning about attachment 0 not being
628 // written to, which shouldn't be fatal.
629 layout(location = 1) out vec4 color1;
630 layout(location = 0) out vec4 color0;
631 
632 void main()
633 {
634     color1 = vec4(0.0, 1.0, 0.0, 1.0);
635 }
636 )";
637 
638     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
639 
640     constexpr GLint kDrawBufferCount = 2;
641 
642     GLint maxDrawBuffers;
643     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
644     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
645 
646     GLTexture textures[kDrawBufferCount];
647 
648     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
649     {
650         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
651         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
652                      GL_UNSIGNED_BYTE, nullptr);
653     }
654 
655     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
656 
657     GLFramebuffer fbo;
658     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
659 
660     // Enable all draw buffers.
661     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
662     {
663         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
664         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
665                                textures[texIndex], 0);
666     }
667     glDrawBuffers(kDrawBufferCount, allBufs);
668 
669     // Draw with simple program.
670     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
671     ASSERT_GL_NO_ERROR();
672 }
673 
TEST_P(GLSLTest,ScopedStructsOrderBug)674 TEST_P(GLSLTest, ScopedStructsOrderBug)
675 {
676     // TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
677     // (http://anglebug.com/1292)
678     // TODO(geofflang): Find out why this doesn't compile on AMD OpenGL drivers
679     // (http://anglebug.com/1291)
680     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()));
681 
682     constexpr char kFS[] = R"(precision mediump float;
683 
684 struct T
685 {
686     float f;
687 };
688 
689 void main()
690 {
691     T a;
692 
693     struct T
694     {
695         float q;
696     };
697 
698     T b;
699 
700     gl_FragColor = vec4(1, 0, 0, 1);
701     gl_FragColor.a += a.f;
702     gl_FragColor.a += b.q;
703 })";
704 
705     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
706 }
707 
TEST_P(GLSLTest,ScopedStructsBug)708 TEST_P(GLSLTest, ScopedStructsBug)
709 {
710     constexpr char kFS[] = R"(precision mediump float;
711 
712 struct T_0
713 {
714     float f;
715 };
716 
717 void main()
718 {
719     gl_FragColor = vec4(1, 0, 0, 1);
720 
721     struct T
722     {
723         vec2 v;
724     };
725 
726     T_0 a;
727     T b;
728 
729     gl_FragColor.a += a.f;
730     gl_FragColor.a += b.v.x;
731 })";
732 
733     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
734 }
735 
TEST_P(GLSLTest,DxPositionBug)736 TEST_P(GLSLTest, DxPositionBug)
737 {
738     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
739 varying float dx_Position;
740 void main()
741 {
742     gl_Position = vec4(inputAttribute);
743     dx_Position = 0.0;
744 })";
745 
746     constexpr char kFS[] = R"(precision mediump float;
747 
748 varying float dx_Position;
749 
750 void main()
751 {
752     gl_FragColor = vec4(dx_Position, 0, 0, 1);
753 })";
754 
755     ANGLE_GL_PROGRAM(program, kVS, kFS);
756 }
757 
758 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)759 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
760 {
761     // http://anglebug.com/4092
762     ANGLE_SKIP_TEST_IF(isSwiftshader());
763     constexpr int kStartIndex  = 0;
764     constexpr int kArrayLength = 5;
765     constexpr char kVS[]       = R"(#version 300 es
766 precision highp float;
767 void main() {
768     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
769     gl_PointSize = 3.0;
770 })";
771 
772     constexpr char kFS[] = R"(#version 300 es
773 precision highp float;
774 out vec4 outColor;
775 void main() {
776     outColor = vec4(1.0, 0.0, 0.0, 1.0);
777 })";
778 
779     ANGLE_GL_PROGRAM(program, kVS, kFS);
780 
781     glUseProgram(program);
782     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
783 
784     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
785     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
786     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
787     {
788         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
789         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
790                               static_cast<int>(pointCenterY), GLColor::red);
791     }
792 }
793 
794 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)795 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
796 {
797     glDrawArrays(GL_POINTS, first, count);
798 
799     int pixel[4];
800     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
801     // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
802     // pixels.
803     if (err == static_cast<GLenum>(GL_NO_ERROR))
804     {
805         EXPECT_GL_NO_ERROR();
806         EXPECT_EQ(pixel[0], first + count - 1);
807     }
808     else
809     {
810         // If we call this function with err set, we will allow the error, but check the pixels if
811         // the error hasn't occurred.
812         GLenum glError = glGetError();
813         if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
814         {
815             EXPECT_EQ(pixel[0], first + count - 1);
816         }
817     }
818 }
819 
820 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
821 // is based off the WebGL test:
822 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)823 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
824 {
825     // http://anglebug.com/4092
826     ANGLE_SKIP_TEST_IF(isSwiftshader());
827     // Have to set a large point size because the window size is much larger than the texture
828     constexpr char kVS[] = R"(#version 300 es
829 flat out highp int vVertexID;
830 void main() {
831     vVertexID = gl_VertexID;
832     gl_Position = vec4(0,0,0,1);
833     gl_PointSize = 1000.0;
834 })";
835 
836     constexpr char kFS[] = R"(#version 300 es
837 flat in highp int vVertexID;
838 out highp int oVertexID;
839 void main() {
840     oVertexID = vVertexID;
841 })";
842 
843     ANGLE_GL_PROGRAM(program, kVS, kFS);
844     glUseProgram(program);
845 
846     GLTexture texture;
847     glBindTexture(GL_TEXTURE_2D, texture);
848     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
849     GLFramebuffer fbo;
850     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
851     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
852     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
853     EXPECT_GL_NO_ERROR();
854 
855     // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
856     GLint val[4] = {42};
857     glClearBufferiv(GL_COLOR, 0, val);
858     int pixel[4];
859     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
860     EXPECT_EQ(pixel[0], val[0]);
861 
862     GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
863     GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
864     GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
865     GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
866     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
867     GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
868     GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
869     GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
870     GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
871     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
872 
873     int32_t int32Max = 0x7FFFFFFF;
874     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
875     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
876     GLVertexIDIntegerTextureDrawArrays_helper(int32Max, 1, GL_OUT_OF_MEMORY);
877 }
878 
879 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)880 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
881 {
882     // http://anglebug.com/4092
883     ANGLE_SKIP_TEST_IF(isSwiftshader());
884     // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
885     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
886 
887     constexpr int kStartIndex  = 5;
888     constexpr int kArrayLength = 5;
889     constexpr char kVS[]       = R"(#version 300 es
890 precision highp float;
891 void main() {
892     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
893     gl_PointSize = 3.0;
894 })";
895 
896     constexpr char kFS[] = R"(#version 300 es
897 precision highp float;
898 out vec4 outColor;
899 void main() {
900     outColor = vec4(1.0, 0.0, 0.0, 1.0);
901 })";
902 
903     ANGLE_GL_PROGRAM(program, kVS, kFS);
904 
905     glUseProgram(program);
906     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
907 
908     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
909     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
910     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
911     {
912         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
913         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
914                               static_cast<int>(pointCenterY), GLColor::red);
915     }
916 }
917 
TEST_P(GLSLTest,ElseIfRewriting)918 TEST_P(GLSLTest, ElseIfRewriting)
919 {
920     constexpr char kVS[] =
921         "attribute vec4 a_position;\n"
922         "varying float v;\n"
923         "void main() {\n"
924         "  gl_Position = a_position;\n"
925         "  v = 1.0;\n"
926         "  if (a_position.x <= 0.5) {\n"
927         "    v = 0.0;\n"
928         "  } else if (a_position.x >= 0.5) {\n"
929         "    v = 2.0;\n"
930         "  }\n"
931         "}\n";
932 
933     constexpr char kFS[] =
934         "precision highp float;\n"
935         "varying float v;\n"
936         "void main() {\n"
937         "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
938         "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
939         "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
940         "  gl_FragColor = color;\n"
941         "}\n";
942 
943     ANGLE_GL_PROGRAM(program, kVS, kFS);
944 
945     drawQuad(program, "a_position", 0.5f);
946 
947     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
948     EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
949 }
950 
TEST_P(GLSLTest,TwoElseIfRewriting)951 TEST_P(GLSLTest, TwoElseIfRewriting)
952 {
953     constexpr char kVS[] =
954         "attribute vec4 a_position;\n"
955         "varying float v;\n"
956         "void main() {\n"
957         "  gl_Position = a_position;\n"
958         "  if (a_position.x == 0.0) {\n"
959         "    v = 1.0;\n"
960         "  } else if (a_position.x > 0.5) {\n"
961         "    v = 0.0;\n"
962         "  } else if (a_position.x > 0.75) {\n"
963         "    v = 0.5;\n"
964         "  }\n"
965         "}\n";
966 
967     constexpr char kFS[] =
968         "precision highp float;\n"
969         "varying float v;\n"
970         "void main() {\n"
971         "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
972         "}\n";
973 
974     ANGLE_GL_PROGRAM(program, kVS, kFS);
975 }
976 
TEST_P(GLSLTest,FrontFacingAndVarying)977 TEST_P(GLSLTest, FrontFacingAndVarying)
978 {
979     EGLPlatformParameters platform = GetParam().eglParameters;
980 
981     constexpr char kVS[] = R"(attribute vec4 a_position;
982 varying float v_varying;
983 void main()
984 {
985     v_varying = a_position.x;
986     gl_Position = a_position;
987 })";
988 
989     constexpr char kFS[] = R"(precision mediump float;
990 varying float v_varying;
991 void main()
992 {
993     vec4 c;
994 
995     if (gl_FrontFacing)
996     {
997         c = vec4(v_varying, 0, 0, 1.0);
998     }
999     else
1000     {
1001         c = vec4(0, v_varying, 0, 1.0);
1002     }
1003     gl_FragColor = c;
1004 })";
1005 
1006     GLuint program = CompileProgram(kVS, kFS);
1007 
1008     // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1009     if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1010     {
1011         if (platform.majorVersion == 9 && platform.minorVersion == 3)
1012         {
1013             EXPECT_EQ(0u, program);
1014             return;
1015         }
1016     }
1017 
1018     // Otherwise, compilation should succeed
1019     EXPECT_NE(0u, program);
1020 }
1021 
1022 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1023 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1024 {
1025     // Draw with the first program.
1026     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1027     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1028     ASSERT_GL_NO_ERROR();
1029     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1030 
1031     // Clear and release shader compiler.
1032     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1033     glClear(GL_COLOR_BUFFER_BIT);
1034     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1035     glReleaseShaderCompiler();
1036     ASSERT_GL_NO_ERROR();
1037 
1038     // Draw with a second program.
1039     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1040     drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1041     ASSERT_GL_NO_ERROR();
1042     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1043 }
1044 
1045 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1046 TEST_P(GLSLTest_ES3, VersionMismatch)
1047 {
1048     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1049     EXPECT_EQ(0u, program);
1050 
1051     program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1052     EXPECT_EQ(0u, program);
1053 }
1054 
1055 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1056 TEST_P(GLSLTest, InvariantVaryingOut)
1057 {
1058     constexpr char kFS[] =
1059         "precision mediump float;\n"
1060         "varying float v_varying;\n"
1061         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1062 
1063     constexpr char kVS[] =
1064         "attribute vec4 a_position;\n"
1065         "invariant varying float v_varying;\n"
1066         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1067 
1068     GLuint program = CompileProgram(kVS, kFS);
1069     EXPECT_EQ(0u, program);
1070 }
1071 
1072 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1073 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1074 {
1075     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1076     // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1077     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1078 
1079     constexpr char kFS[] =
1080         "#version 300 es\n"
1081         "precision mediump float;\n"
1082         "in float v_varying;\n"
1083         "out vec4 my_FragColor;\n"
1084         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1085 
1086     constexpr char kVS[] =
1087         "#version 300 es\n"
1088         "in vec4 a_position;\n"
1089         "invariant out float v_varying;\n"
1090         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1091 
1092     GLuint program = CompileProgram(kVS, kFS);
1093     EXPECT_NE(0u, program);
1094 }
1095 
1096 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1097 TEST_P(GLSLTest, InvariantVaryingIn)
1098 {
1099     constexpr char kFS[] =
1100         "precision mediump float;\n"
1101         "invariant varying float v_varying;\n"
1102         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1103 
1104     constexpr char kVS[] =
1105         "attribute vec4 a_position;\n"
1106         "varying float v_varying;\n"
1107         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1108 
1109     GLuint program = CompileProgram(kVS, kFS);
1110     EXPECT_EQ(0u, program);
1111 }
1112 
1113 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1114 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1115 {
1116     constexpr char kFS[] =
1117         "#version 300 es\n"
1118         "precision mediump float;\n"
1119         "invariant in float v_varying;\n"
1120         "out vec4 my_FragColor;\n"
1121         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1122 
1123     constexpr char kVS[] =
1124         "#version 300 es\n"
1125         "in vec4 a_position;\n"
1126         "out float v_varying;\n"
1127         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1128 
1129     GLuint program = CompileProgram(kVS, kFS);
1130     EXPECT_EQ(0u, program);
1131 }
1132 
1133 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1134 TEST_P(GLSLTest, InvariantVaryingBoth)
1135 {
1136     constexpr char kFS[] =
1137         "precision mediump float;\n"
1138         "invariant varying float v_varying;\n"
1139         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1140 
1141     constexpr char kVS[] =
1142         "attribute vec4 a_position;\n"
1143         "invariant varying float v_varying;\n"
1144         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1145 
1146     GLuint program = CompileProgram(kVS, kFS);
1147     EXPECT_NE(0u, program);
1148 }
1149 
1150 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1151 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1152 {
1153     constexpr char kFS[] =
1154         "#version 300 es\n"
1155         "precision mediump float;\n"
1156         "invariant in float v_varying;\n"
1157         "out vec4 my_FragColor;\n"
1158         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1159 
1160     constexpr char kVS[] =
1161         "#version 300 es\n"
1162         "in vec4 a_position;\n"
1163         "invariant out float v_varying;\n"
1164         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1165 
1166     GLuint program = CompileProgram(kVS, kFS);
1167     EXPECT_EQ(0u, program);
1168 }
1169 
1170 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1171 TEST_P(GLSLTest, InvariantGLPosition)
1172 {
1173     constexpr char kFS[] =
1174         "precision mediump float;\n"
1175         "varying float v_varying;\n"
1176         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1177 
1178     constexpr char kVS[] =
1179         "attribute vec4 a_position;\n"
1180         "invariant gl_Position;\n"
1181         "varying float v_varying;\n"
1182         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1183 
1184     GLuint program = CompileProgram(kVS, kFS);
1185     EXPECT_NE(0u, program);
1186 }
1187 
1188 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1189 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1190 {
1191     constexpr char kFS[] =
1192         "#version 300 es\n"
1193         "precision mediump float;\n"
1194         "in float v_varying;\n"
1195         "out vec4 my_FragColor;\n"
1196         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1197 
1198     constexpr char kVS[] =
1199         "#version 300 es\n"
1200         "in vec4 a_position;\n"
1201         "invariant gl_Position;\n"
1202         "out float v_varying;\n"
1203         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1204 
1205     GLuint program = CompileProgram(kVS, kFS);
1206     EXPECT_NE(0u, program);
1207 }
1208 
1209 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1210 TEST_P(GLSLTest, InvariantAllBoth)
1211 {
1212     constexpr char kFS[] =
1213         "#pragma STDGL invariant(all)\n"
1214         "precision mediump float;\n"
1215         "varying float v_varying;\n"
1216         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1217 
1218     constexpr char kVS[] =
1219         "#pragma STDGL invariant(all)\n"
1220         "attribute vec4 a_position;\n"
1221         "varying float v_varying;\n"
1222         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1223 
1224     GLuint program = CompileProgram(kVS, kFS);
1225     EXPECT_EQ(0u, program);
1226 }
1227 
1228 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)1229 TEST_P(GLSLTest, MissingReturnFloat)
1230 {
1231     constexpr char kVS[] =
1232         "varying float v_varying;\n"
1233         "float f() { if (v_varying > 0.0) return 1.0; }\n"
1234         "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
1235 
1236     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1237     EXPECT_NE(0u, program);
1238 }
1239 
1240 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)1241 TEST_P(GLSLTest, MissingReturnVec2)
1242 {
1243     constexpr char kVS[] =
1244         "varying float v_varying;\n"
1245         "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
1246         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1247 
1248     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1249     EXPECT_NE(0u, program);
1250 }
1251 
1252 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)1253 TEST_P(GLSLTest, MissingReturnVec3)
1254 {
1255     constexpr char kVS[] =
1256         "varying float v_varying;\n"
1257         "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1258         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1259 
1260     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1261     EXPECT_NE(0u, program);
1262 }
1263 
1264 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)1265 TEST_P(GLSLTest, MissingReturnVec4)
1266 {
1267     constexpr char kVS[] =
1268         "varying float v_varying;\n"
1269         "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1270         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1271 
1272     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1273     EXPECT_NE(0u, program);
1274 }
1275 
1276 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)1277 TEST_P(GLSLTest, MissingReturnIVec4)
1278 {
1279     constexpr char kVS[] =
1280         "varying float v_varying;\n"
1281         "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1282         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1283 
1284     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1285     EXPECT_NE(0u, program);
1286 }
1287 
1288 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)1289 TEST_P(GLSLTest, MissingReturnMat4)
1290 {
1291     constexpr char kVS[] =
1292         "varying float v_varying;\n"
1293         "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1294         "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1295 
1296     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1297     EXPECT_NE(0u, program);
1298 }
1299 
1300 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)1301 TEST_P(GLSLTest, MissingReturnStruct)
1302 {
1303     constexpr char kVS[] =
1304         "varying float v_varying;\n"
1305         "struct s { float a; int b; vec2 c; };\n"
1306         "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1307         "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1308 
1309     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1310     EXPECT_NE(0u, program);
1311 }
1312 
1313 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)1314 TEST_P(GLSLTest_ES3, MissingReturnArray)
1315 {
1316     constexpr char kVS[] =
1317         "#version 300 es\n"
1318         "in float v_varying;\n"
1319         "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1320         "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1321 
1322     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1323     EXPECT_NE(0u, program);
1324 }
1325 
1326 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)1327 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1328 {
1329     constexpr char kVS[] =
1330         "#version 300 es\n"
1331         "in float v_varying;\n"
1332         "struct s { float a; int b; vec2 c; };\n"
1333         "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1334         "vec2(1.0, 1.0))); } }\n"
1335         "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1336 
1337     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1338     EXPECT_NE(0u, program);
1339 }
1340 
1341 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)1342 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1343 {
1344     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
1345     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
1346 
1347     constexpr char kVS[] =
1348         "#version 300 es\n"
1349         "in float v_varying;\n"
1350         "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1351         "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1352         "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1353         "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1354 
1355     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1356     EXPECT_NE(0u, program);
1357 }
1358 
1359 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)1360 TEST_P(GLSLTest_ES3, InvariantAllBoth)
1361 {
1362     constexpr char kFS[] =
1363         "#version 300 es\n"
1364         "#pragma STDGL invariant(all)\n"
1365         "precision mediump float;\n"
1366         "in float v_varying;\n"
1367         "out vec4 my_FragColor;\n"
1368         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1369 
1370     constexpr char kVS[] =
1371         "#version 300 es\n"
1372         "#pragma STDGL invariant(all)\n"
1373         "in vec4 a_position;\n"
1374         "out float v_varying;\n"
1375         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1376 
1377     GLuint program = CompileProgram(kVS, kFS);
1378     EXPECT_EQ(0u, program);
1379 }
1380 
1381 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)1382 TEST_P(GLSLTest, InvariantAllIn)
1383 {
1384     constexpr char kFS[] =
1385         "#pragma STDGL invariant(all)\n"
1386         "precision mediump float;\n"
1387         "varying float v_varying;\n"
1388         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1389 
1390     constexpr char kVS[] =
1391         "attribute vec4 a_position;\n"
1392         "varying float v_varying;\n"
1393         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1394 
1395     GLuint program = CompileProgram(kVS, kFS);
1396     EXPECT_NE(0u, program);
1397 }
1398 
1399 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)1400 TEST_P(GLSLTest_ES3, InvariantAllIn)
1401 {
1402     constexpr char kFS[] =
1403         "#version 300 es\n"
1404         "#pragma STDGL invariant(all)\n"
1405         "precision mediump float;\n"
1406         "in float v_varying;\n"
1407         "out vec4 my_FragColor;\n"
1408         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1409 
1410     constexpr char kVS[] =
1411         "#version 300 es\n"
1412         "in vec4 a_position;\n"
1413         "out float v_varying;\n"
1414         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1415 
1416     GLuint program = CompileProgram(kVS, kFS);
1417     EXPECT_EQ(0u, program);
1418 }
1419 
1420 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)1421 TEST_P(GLSLTest, InvariantAllOut)
1422 {
1423     constexpr char kFS[] =
1424         "precision mediump float;\n"
1425         "varying float v_varying;\n"
1426         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1427 
1428     constexpr char kVS[] =
1429         "#pragma STDGL invariant(all)\n"
1430         "attribute vec4 a_position;\n"
1431         "varying float v_varying;\n"
1432         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1433 
1434     GLuint program = CompileProgram(kVS, kFS);
1435     EXPECT_EQ(0u, program);
1436 }
1437 
1438 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)1439 TEST_P(GLSLTest_ES3, InvariantAllOut)
1440 {
1441     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1442     // for varyings which are invariant in vertex shader,
1443     // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
1444     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1445 
1446     constexpr char kFS[] =
1447         "#version 300 es\n"
1448         "precision mediump float;\n"
1449         "in float v_varying;\n"
1450         "out vec4 my_FragColor;\n"
1451         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1452 
1453     constexpr char kVS[] =
1454         "#version 300 es\n"
1455         "#pragma STDGL invariant(all)\n"
1456         "in vec4 a_position;\n"
1457         "out float v_varying;\n"
1458         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1459 
1460     GLuint program = CompileProgram(kVS, kFS);
1461     EXPECT_NE(0u, program);
1462 }
1463 
TEST_P(GLSLTest,MaxVaryingVec4)1464 TEST_P(GLSLTest, MaxVaryingVec4)
1465 {
1466     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1467     // (http://anglebug.com/1291)
1468     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1469 
1470     GLint maxVaryings = 0;
1471     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1472 
1473     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1474 }
1475 
1476 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)1477 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
1478 {
1479     GLint maxVaryings = 0;
1480     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1481 
1482     // Generate shader code that uses gl_FragCoord.
1483     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
1484 }
1485 
1486 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)1487 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
1488 {
1489     GLint maxVaryings = 0;
1490     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1491 
1492     // Generate shader code that uses gl_FragCoord and gl_PointCoord.
1493     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1494 }
1495 
1496 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)1497 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
1498 {
1499     GLint maxVaryings = 0;
1500     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1501 
1502     // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1503     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
1504 }
1505 
1506 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1507 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)1508 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
1509 {
1510     ANGLE_SKIP_TEST_IF(!IsD3D9());
1511 
1512     GLint maxVaryings = 0;
1513     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1514 
1515     VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
1516     VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
1517     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
1518 
1519     // Special case for gl_PointSize: we get it for free on D3D9.
1520     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
1521 }
1522 
1523 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1524 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)1525 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
1526 {
1527     GLint maxVaryings = 0;
1528     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1529 
1530     // Generate shader code that uses gl_FragCoord.
1531     VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
1532 }
1533 
TEST_P(GLSLTest,MaxVaryingVec3)1534 TEST_P(GLSLTest, MaxVaryingVec3)
1535 {
1536     GLint maxVaryings = 0;
1537     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1538 
1539     VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
1540 }
1541 
TEST_P(GLSLTest,MaxVaryingVec3Array)1542 TEST_P(GLSLTest, MaxVaryingVec3Array)
1543 {
1544     GLint maxVaryings = 0;
1545     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1546 
1547     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
1548 }
1549 
1550 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)1551 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
1552 {
1553     GLint maxVaryings = 0;
1554     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1555 
1556     VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
1557 }
1558 
1559 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)1560 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
1561 {
1562     GLint maxVaryings = 0;
1563     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1564 
1565     VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
1566 }
1567 
1568 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)1569 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
1570 {
1571     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1572     // (http://anglebug.com/3849)
1573     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
1574 
1575     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1576     // (http://anglebug.com/1291)
1577     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1578 
1579     GLint maxVaryings = 0;
1580     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1581 
1582     VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
1583 }
1584 
1585 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)1586 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
1587 {
1588     ANGLE_SKIP_TEST_IF(IsD3DSM3());
1589 
1590     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1591     ANGLE_SKIP_TEST_IF(IsOpenGLES());
1592 
1593     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1594     // (http://anglebug.com/1291)
1595     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1596 
1597     GLint maxVaryings = 0;
1598     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1599 
1600     // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1601     // we should be aware that when we're packing into an odd number of varying registers the
1602     // last row will be empty and can not fit the final vec2 arrary.
1603     GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1604 
1605     VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
1606 }
1607 
1608 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)1609 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
1610 {
1611     // (http://anglebug.com/4439)
1612     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
1613 
1614     // http://anglebug.com/4446
1615     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
1616 
1617     GLint maxVaryings = 0;
1618     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1619 
1620     std::stringstream vertexShaderSource;
1621     std::stringstream fragmentShaderSource;
1622 
1623     // substract 1 here for gl_PointSize
1624     const GLint vec4Count     = maxVaryings - 1;
1625     unsigned int varyingCount = 0;
1626     std::string varyingDeclaration;
1627     for (GLint i = 0; i < vec4Count; i++)
1628     {
1629         varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
1630         varyingCount += 1;
1631     }
1632     // Generate the vertex shader
1633     vertexShaderSource.clear();
1634     vertexShaderSource << varyingDeclaration;
1635     vertexShaderSource << "\nattribute vec4 a_position;\n";
1636     vertexShaderSource << "\nvoid main()\n{\n";
1637     unsigned int currentVSVarying = 0;
1638     for (GLint i = 0; i < vec4Count; i++)
1639     {
1640         vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
1641         currentVSVarying += 1;
1642     }
1643     vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
1644     vertexShaderSource << "\tgl_PointSize = 1.0;\n";
1645     vertexShaderSource << "}\n";
1646 
1647     // Generate the fragment shader
1648     fragmentShaderSource.clear();
1649     fragmentShaderSource << "precision highp float;\n";
1650     fragmentShaderSource << varyingDeclaration;
1651     fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
1652     unsigned int currentFSVarying = 0;
1653     // Make use of the vec4 varyings
1654     fragmentShaderSource << "\tretColor += ";
1655     for (GLint i = 0; i < vec4Count; i++)
1656     {
1657         fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
1658         currentFSVarying += 1;
1659     }
1660     fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
1661     constexpr GLuint testValue = 234;
1662     fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
1663                          << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
1664     fragmentShaderSource << "}\n";
1665 
1666     std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
1667     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
1668                                         fragmentShaderSource.str().c_str(), tfVaryings,
1669                                         GL_INTERLEAVED_ATTRIBS);
1670 
1671     GLBuffer xfbBuffer;
1672     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1673     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
1674                  GL_STATIC_DRAW);
1675 
1676     GLTransformFeedback xfb;
1677     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1678     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1679 
1680     glUseProgram(program1);
1681 
1682     const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
1683     GLBuffer vertexBuffer;
1684     // need to shift half pixel to make sure the line covers the center of the pixel
1685     const Vector3 vertices[2] = {
1686         {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
1687         {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
1688     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1689     glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
1690     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1691     glEnableVertexAttribArray(positionLocation);
1692 
1693     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
1694     glClear(GL_COLOR_BUFFER_BIT);
1695 
1696     glBeginTransformFeedback(GL_LINES);
1697     glDrawArrays(GL_LINES, 0, 2);
1698     glEndTransformFeedback();
1699 
1700     ASSERT_GL_NO_ERROR();
1701 
1702     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
1703 }
1704 
1705 // Verify shader source with a fixed length that is less than the null-terminated length will
1706 // compile.
TEST_P(GLSLTest,FixedShaderLength)1707 TEST_P(GLSLTest, FixedShaderLength)
1708 {
1709     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1710 
1711     const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
1712     const std::string source   = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1713     const char *sourceArray[1] = {source.c_str()};
1714     GLint lengths[1]           = {static_cast<GLint>(source.length() - appendGarbage.length())};
1715     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1716     glCompileShader(shader);
1717 
1718     GLint compileResult;
1719     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1720     EXPECT_NE(compileResult, 0);
1721 }
1722 
1723 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)1724 TEST_P(GLSLTest, NegativeShaderLength)
1725 {
1726     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1727 
1728     const char *sourceArray[1] = {essl1_shaders::fs::Red()};
1729     GLint lengths[1]           = {-10};
1730     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1731     glCompileShader(shader);
1732 
1733     GLint compileResult;
1734     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1735     EXPECT_NE(compileResult, 0);
1736 }
1737 
1738 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)1739 TEST_P(GLSLTest, InvalidFieldFirstChar)
1740 {
1741     GLuint shader      = glCreateShader(GL_VERTEX_SHADER);
1742     const char *source = "void main() {vec4 x; x.}";
1743     glShaderSource(shader, 1, &source, 0);
1744     glCompileShader(shader);
1745 
1746     GLint compileResult;
1747     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1748     EXPECT_EQ(0, compileResult);
1749 }
1750 
1751 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)1752 TEST_P(GLSLTest, MixedShaderLengths)
1753 {
1754     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1755 
1756     const char *sourceArray[] = {
1757         "void main()",
1758         "{",
1759         "    gl_FragColor = vec4(0, 0, 0, 0);",
1760         "}",
1761     };
1762     GLint lengths[] = {
1763         -10,
1764         1,
1765         static_cast<GLint>(strlen(sourceArray[2])),
1766         -1,
1767     };
1768     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1769 
1770     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1771     glCompileShader(shader);
1772 
1773     GLint compileResult;
1774     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1775     EXPECT_NE(compileResult, 0);
1776 }
1777 
1778 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)1779 TEST_P(GLSLTest, ZeroShaderLength)
1780 {
1781     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1782 
1783     const char *sourceArray[] = {
1784         "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
1785     };
1786     GLint lengths[] = {
1787         0, 0, -1, 0, 0,
1788     };
1789     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1790 
1791     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1792     glCompileShader(shader);
1793 
1794     GLint compileResult;
1795     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1796     EXPECT_NE(compileResult, 0);
1797 }
1798 
1799 // Tests that bad index expressions don't crash ANGLE's translator.
1800 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)1801 TEST_P(GLSLTest, BadIndexBug)
1802 {
1803     constexpr char kFSSourceVec[] =
1804         "precision mediump float;\n"
1805         "uniform vec4 uniformVec;\n"
1806         "void main()\n"
1807         "{\n"
1808         "    gl_FragColor = vec4(uniformVec[int()]);\n"
1809         "}";
1810 
1811     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
1812     EXPECT_EQ(0u, shader);
1813 
1814     if (shader != 0)
1815     {
1816         glDeleteShader(shader);
1817     }
1818 
1819     constexpr char kFSSourceMat[] =
1820         "precision mediump float;\n"
1821         "uniform mat4 uniformMat;\n"
1822         "void main()\n"
1823         "{\n"
1824         "    gl_FragColor = vec4(uniformMat[int()]);\n"
1825         "}";
1826 
1827     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
1828     EXPECT_EQ(0u, shader);
1829 
1830     if (shader != 0)
1831     {
1832         glDeleteShader(shader);
1833     }
1834 
1835     constexpr char kFSSourceArray[] =
1836         "precision mediump float;\n"
1837         "uniform vec4 uniformArray;\n"
1838         "void main()\n"
1839         "{\n"
1840         "    gl_FragColor = vec4(uniformArray[int()]);\n"
1841         "}";
1842 
1843     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
1844     EXPECT_EQ(0u, shader);
1845 
1846     if (shader != 0)
1847     {
1848         glDeleteShader(shader);
1849     }
1850 }
1851 
1852 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)1853 TEST_P(GLSLTest, StructSpecifiersUniforms)
1854 {
1855     constexpr char kFS[] = R"(precision mediump float;
1856 
1857 uniform struct S { float field; } s;
1858 
1859 void main()
1860 {
1861     gl_FragColor = vec4(1, 0, 0, 1);
1862     gl_FragColor.a += s.field;
1863 })";
1864 
1865     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
1866     EXPECT_NE(0u, program);
1867 }
1868 
1869 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)1870 TEST_P(GLSLTest, StructWithInitializer)
1871 {
1872     constexpr char kFS[] = R"(precision mediump float;
1873 
1874 struct S { float a; } s = S(1.0);
1875 
1876 void main()
1877 {
1878     gl_FragColor = vec4(0, 0, 0, 1);
1879     gl_FragColor.r += s.a;
1880 })";
1881 
1882     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1883     glUseProgram(program);
1884 
1885     // Test drawing, should be red.
1886     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
1887 
1888     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1889     EXPECT_GL_NO_ERROR();
1890 }
1891 
1892 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)1893 TEST_P(GLSLTest, UniformStructWithoutInitializer)
1894 {
1895     constexpr char kFS[] = R"(precision mediump float;
1896 
1897 struct S { float a; };
1898 uniform S u_s;
1899 
1900 void main()
1901 {
1902     gl_FragColor = vec4(u_s.a);
1903 })";
1904 
1905     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1906     glUseProgram(program);
1907 
1908     // Test drawing, should be red.
1909     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
1910 
1911     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1912     EXPECT_GL_NO_ERROR();
1913 }
1914 
1915 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)1916 TEST_P(GLSLTest, StructWithUniformInitializer)
1917 {
1918     constexpr char kFS[] = R"(precision mediump float;
1919 
1920 struct S { float a; } s = S(1.0);
1921 uniform S us;
1922 
1923 void main()
1924 {
1925     gl_FragColor = vec4(0, 0, 0, 1);
1926     gl_FragColor.r += s.a;
1927     gl_FragColor.g += us.a;
1928 })";
1929 
1930     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1931     glUseProgram(program);
1932 
1933     // Test drawing, should be red.
1934     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
1935 
1936     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1937     EXPECT_GL_NO_ERROR();
1938 }
1939 
1940 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1941 // beginning with "gl_" are filtered out by our validation logic, we must
1942 // bypass the validation to test the behaviour of the implementation.
1943 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)1944 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
1945 {
1946     constexpr char kFS[] = R"(precision mediump float;
1947 
1948 void main()
1949 {
1950     gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
1951 })";
1952 
1953     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1954 
1955     // We need to bypass validation for this call.
1956     GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
1957     EXPECT_EQ(-1, nearIndex);
1958 
1959     // Test drawing does not throw an exception.
1960     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
1961 
1962     EXPECT_GL_NO_ERROR();
1963 }
1964 
GenerateSmallPowShader(double base,double exponent)1965 std::string GenerateSmallPowShader(double base, double exponent)
1966 {
1967     std::stringstream stream;
1968 
1969     stream.precision(8);
1970 
1971     double result = pow(base, exponent);
1972 
1973     stream << "precision highp float;\n"
1974            << "float fun(float arg)\n"
1975            << "{\n"
1976            << "    return pow(arg, " << std::fixed << exponent << ");\n"
1977            << "}\n"
1978            << "\n"
1979            << "void main()\n"
1980            << "{\n"
1981            << "    const float a = " << std::scientific << base << ";\n"
1982            << "    float b = fun(a);\n"
1983            << "    if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1984            << "    {\n"
1985            << "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1986            << "    }\n"
1987            << "    else\n"
1988            << "    {\n"
1989            << "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1990            << "    }\n"
1991            << "}\n";
1992 
1993     return stream.str();
1994 }
1995 
1996 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
1997 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)1998 TEST_P(GLSLTest, PowOfSmallConstant)
1999 {
2000     // Test with problematic exponents that are close to an integer.
2001     std::vector<double> testExponents;
2002     std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2003     for (double epsilonMultiplier : epsilonMultipliers)
2004     {
2005         for (int i = -4; i <= 5; ++i)
2006         {
2007             if (i >= -1 && i <= 1)
2008                 continue;
2009             const double epsilon = 1.0e-8;
2010             double bad           = static_cast<double>(i) + epsilonMultiplier * epsilon;
2011             testExponents.push_back(bad);
2012         }
2013     }
2014 
2015     // Also test with a few exponents that are not close to an integer.
2016     testExponents.push_back(3.6);
2017     testExponents.push_back(3.4);
2018 
2019     for (double testExponent : testExponents)
2020     {
2021         const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2022 
2023         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2024 
2025         drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2026 
2027         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2028         EXPECT_GL_NO_ERROR();
2029     }
2030 }
2031 
2032 // Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
2033 // below
2034 // fail with a specific error message.
2035 // Additionally test that the same fragment shader compiles successfully with feature levels greater
2036 // than FL9_3.
TEST_P(GLSLTest,LoopIndexingValidation)2037 TEST_P(GLSLTest, LoopIndexingValidation)
2038 {
2039     constexpr char kFS[] = R"(precision mediump float;
2040 
2041 uniform float loopMax;
2042 
2043 void main()
2044 {
2045     gl_FragColor = vec4(1, 0, 0, 1);
2046     for (float l = 0.0; l < loopMax; l++)
2047     {
2048         if (loopMax > 3.0)
2049         {
2050             gl_FragColor.a += 0.1;
2051         }
2052     }
2053 })";
2054 
2055     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2056 
2057     const char *sourceArray[1] = {kFS};
2058     glShaderSource(shader, 1, sourceArray, nullptr);
2059     glCompileShader(shader);
2060 
2061     GLint compileResult;
2062     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2063 
2064     // If the test is configured to run limited to Feature Level 9_3, then it is
2065     // assumed that shader compilation will fail with an expected error message containing
2066     // "Loop index cannot be compared with non-constant expression"
2067     if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
2068     {
2069         if (compileResult != 0)
2070         {
2071             FAIL() << "Shader compilation succeeded, expected failure";
2072         }
2073         else
2074         {
2075             GLint infoLogLength;
2076             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2077 
2078             std::string infoLog;
2079             infoLog.resize(infoLogLength);
2080             glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2081 
2082             if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2083                 std::string::npos)
2084             {
2085                 FAIL() << "Shader compilation failed with unexpected error message";
2086             }
2087         }
2088     }
2089     else
2090     {
2091         EXPECT_NE(0, compileResult);
2092     }
2093 
2094     if (shader != 0)
2095     {
2096         glDeleteShader(shader);
2097     }
2098 }
2099 
2100 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2101 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2102 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2103 {
2104     // crbug.com/680631
2105     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2106 
2107     int maxUniforms = 10000;
2108     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2109     EXPECT_GL_NO_ERROR();
2110     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2111 
2112     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2113 }
2114 
2115 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2116 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2117 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2118 {
2119     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2120 
2121     int maxUniforms = 10000;
2122     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2123     EXPECT_GL_NO_ERROR();
2124     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2125 
2126     int maxTextureImageUnits = 0;
2127     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2128 
2129     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2130 }
2131 
2132 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2133 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2134 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2135 {
2136     int maxUniforms = 10000;
2137     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2138     EXPECT_GL_NO_ERROR();
2139     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2140 
2141     CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2142 }
2143 
2144 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2145 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2146 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2147 {
2148     // crbug.com/680631
2149     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2150 
2151     int maxUniforms = 10000;
2152     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2153     EXPECT_GL_NO_ERROR();
2154     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2155 
2156     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2157 }
2158 
2159 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2160 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2161 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2162 {
2163     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2164 
2165     int maxUniforms = 10000;
2166     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2167     EXPECT_GL_NO_ERROR();
2168 
2169     int maxTextureImageUnits = 0;
2170     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2171 
2172     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2173 }
2174 
2175 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2176 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2177 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2178 {
2179     int maxUniforms = 10000;
2180     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2181     EXPECT_GL_NO_ERROR();
2182     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2183               << std::endl;
2184 
2185     CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2186 }
2187 
2188 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2189 TEST_P(GLSLTest, TextureLOD)
2190 {
2191     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2192 
2193     constexpr char kFS[] =
2194         "#extension GL_EXT_shader_texture_lod : require\n"
2195         "uniform sampler2D u_texture;\n"
2196         "void main() {\n"
2197         "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2198         "0.0));\n"
2199         "}\n";
2200 
2201     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2202     ASSERT_NE(0u, shader);
2203     glDeleteShader(shader);
2204 }
2205 
2206 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2207 // function calls to use them in vertex shaders.  http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2208 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2209 {
2210     constexpr char kVS[] = R"(
2211   precision highp float;
2212   uniform int uni;
2213   uniform sampler2D texture;
2214 
2215   vec4 A();
2216 
2217   vec4 B() {
2218     vec4 a;
2219     for(int r=0; r<14; r++){
2220       if (r < uni) return vec4(0.0);
2221       a = A();
2222     }
2223     return a;
2224   }
2225 
2226   vec4 A() {
2227     return texture2D(texture, vec2(0.0, 0.0));
2228   }
2229 
2230   void main() {
2231     gl_Position = B();
2232   })";
2233 
2234     constexpr char kFS[] = R"(
2235 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
2236 )";
2237 
2238     ANGLE_GL_PROGRAM(program, kVS, kFS);
2239 }
2240 
2241 // Test to verify the a shader can have a sampler unused in a vertex shader
2242 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)2243 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
2244 {
2245     constexpr char kVS[] = R"(
2246 attribute vec2 position;
2247 varying mediump vec2 texCoord;
2248 uniform sampler2D tex;
2249 void main()
2250 {
2251     gl_Position = vec4(position, 0, 1);
2252     texCoord = position * 0.5 + vec2(0.5);
2253 })";
2254 
2255     constexpr char kFS[] = R"(
2256 varying mediump vec2 texCoord;
2257 uniform sampler2D tex;
2258 void main()
2259 {
2260     gl_FragColor = texture2D(tex, texCoord);
2261 })";
2262 
2263     ANGLE_GL_PROGRAM(program, kVS, kFS);
2264 
2265     // Initialize basic red texture.
2266     const std::vector<GLColor> redColors(4, GLColor::red);
2267     GLTexture texture;
2268     glBindTexture(GL_TEXTURE_2D, texture);
2269     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
2270     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2271     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2272     ASSERT_GL_NO_ERROR();
2273 
2274     drawQuad(program, "position", 0.0f);
2275 
2276     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
2277 }
2278 
2279 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)2280 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
2281 {
2282     constexpr char kFS[] =
2283         "precision mediump float;\n"
2284         "struct Data { mediump sampler2D data[2]; };\n"
2285         "uniform Data test[2];\n"
2286         "void main() {\n"
2287         "    gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
2288         "                        texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
2289         "                        texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
2290         "                        texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
2291         "}\n";
2292 
2293     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2294     glUseProgram(program.get());
2295     GLTexture textures[4];
2296     GLColor expected = MakeGLColor(32, 64, 96, 255);
2297     GLubyte data[8]  = {};  // 4 bytes of padding, so that texture can be initialized with 4 bytes
2298     memcpy(data, expected.data(), sizeof(expected));
2299     for (int i = 0; i < 4; i++)
2300     {
2301         int outerIdx = i % 2;
2302         int innerIdx = i / 2;
2303         glActiveTexture(GL_TEXTURE0 + i);
2304         glBindTexture(GL_TEXTURE_2D, textures[i]);
2305         // Each element provides two components.
2306         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
2307         std::stringstream uniformName;
2308         uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
2309         // Then send it as a uniform
2310         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
2311         // The uniform should be active.
2312         EXPECT_NE(uniformLocation, -1);
2313 
2314         glUniform1i(uniformLocation, 3 - i);
2315     }
2316     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2317     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
2318 }
2319 
2320 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
2321 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)2322 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
2323 {
2324     constexpr char kVS[] =
2325         "#version 300 es\n"
2326         "precision highp float;\n"
2327         "in vec4 a_vec;\n"
2328         "in mat2 a_mat;\n"
2329         "void main()\n"
2330         "{\n"
2331         "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
2332         "}";
2333 
2334     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2335     EXPECT_NE(0u, program);
2336 }
2337 
2338 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
2339 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
2340 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)2341 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
2342 {
2343     constexpr char kVS[] =
2344         "#version 300 es\n"
2345         "precision highp float;\n"
2346         "in mat3x2 a_matA;\n"
2347         "in mat2x3 a_matB;\n"
2348         "void main()\n"
2349         "{\n"
2350         "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
2351         "}";
2352 
2353     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2354     EXPECT_NE(0u, program);
2355 }
2356 
2357 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)2358 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
2359 {
2360     constexpr char kVS[] =
2361         "#version 300 es\n"
2362         "precision highp float;\n"
2363         "in vec4 a_vec;\n"
2364         "in mat2 a_mat;\n"
2365         "vec4 foo(vec4 a)\n"
2366         "{\n"
2367         "    return a;\n"
2368         "}\n"
2369         "vec4 foo(mat2 a)\n"
2370         "{\n"
2371         "    return vec4(a[0][0]);\n"
2372         "}\n"
2373         "void main()\n"
2374         "{\n"
2375         "    gl_Position = foo(a_vec) + foo(a_mat);\n"
2376         "}";
2377 
2378     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2379     EXPECT_NE(0u, program);
2380 }
2381 
2382 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
2383 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)2384 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
2385 {
2386     std::stringstream vertexShaderStream;
2387     // Note: SPIR-V doesn't allow more than 255 parameters to a function.
2388     const unsigned int paramCount = IsVulkan() ? 255u : 1024u;
2389 
2390     vertexShaderStream << "#version 300 es\n"
2391                           "precision highp float;\n"
2392                           "in vec4 a_vec;\n"
2393                           "vec4 lotsOfVec4Parameters(";
2394     for (unsigned int i = 0; i < paramCount - 1; ++i)
2395     {
2396         vertexShaderStream << "vec4 a" << i << ", ";
2397     }
2398     vertexShaderStream << "vec4 aLast)\n"
2399                           "{\n"
2400                           "    vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
2401     for (unsigned int i = 0; i < paramCount - 1; ++i)
2402     {
2403         vertexShaderStream << "    sum += a" << i << ";\n";
2404     }
2405     vertexShaderStream << "    sum += aLast;\n"
2406                           "    return sum;\n "
2407                           "}\n"
2408                           "void main()\n"
2409                           "{\n"
2410                           "    gl_Position = lotsOfVec4Parameters(";
2411     for (unsigned int i = 0; i < paramCount - 1; ++i)
2412     {
2413         vertexShaderStream << "a_vec, ";
2414     }
2415     vertexShaderStream << "a_vec);\n"
2416                           "}";
2417 
2418     GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
2419     EXPECT_NE(0u, program);
2420 }
2421 
2422 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
2423 // Test a shader where a global constant array is initialized with an expression containing array
2424 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2425 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
2426 // Also includes multiple array initializers in one declaration, where only the second one has
2427 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
2428 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)2429 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2430 {
2431     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2432     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2433 
2434     constexpr char kFS[] =
2435         "#version 300 es\n"
2436         "precision highp float;\n"
2437         "out vec4 my_FragColor;\n"
2438         "const highp float f[2] = float[2](0.1, 0.2);\n"
2439         "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2440         "void main()\n"
2441         "{\n"
2442         "    my_FragColor = vec4(h[1]);\n"
2443         "}";
2444 
2445     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2446     EXPECT_NE(0u, program);
2447 }
2448 
2449 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)2450 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2451 {
2452     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
2453 
2454     constexpr char kFS[] =
2455         "precision mediump float;\n"
2456         "uniform sampler2D uni[2];\n"
2457         "\n"
2458         "float zero(int x)\n"
2459         "{\n"
2460         "    return float(x) - float(x);\n"
2461         "}\n"
2462         "\n"
2463         "void main()\n"
2464         "{\n"
2465         "    vec4 c = vec4(0,0,0,0);\n"
2466         "    for (int ii = 1; ii < 3; ++ii) {\n"
2467         "        if (c.x > 255.0) {\n"
2468         "            c.x = 255.0 + zero(ii);\n"
2469         "            break;\n"
2470         "        }\n"
2471         // Index the sampler array with a predictable loop index (index-constant) as opposed to
2472         // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2473         // without an extension.
2474         "        c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2475         "    }\n"
2476         "    gl_FragColor = c;\n"
2477         "}";
2478 
2479     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2480     EXPECT_NE(0u, program);
2481 }
2482 
2483 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2484 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2485 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)2486 TEST_P(GLSLTest, PragmaDirective)
2487 {
2488     constexpr char kVS[] =
2489         "#pragma STDGL invariant(all)\n"
2490         "void main()\n"
2491         "{\n"
2492         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2493         "}\n";
2494 
2495     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2496     EXPECT_NE(0u, program);
2497 }
2498 
2499 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2500 // The function call that returns the array needs to be evaluated after ++j for the expression to
2501 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)2502 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2503 {
2504     constexpr char kFS[] =
2505         "#version 300 es\n"
2506         "precision mediump float;\n"
2507         "out vec4 my_FragColor; \n"
2508         "int[2] func(int param) {\n"
2509         "    return int[2](param, param);\n"
2510         "}\n"
2511         "void main() {\n"
2512         "    int a[2]; \n"
2513         "    for (int i = 0; i < 2; ++i) {\n"
2514         "        a[i] = 1;\n"
2515         "    }\n"
2516         "    int j = 0; \n"
2517         "    bool result = ((++j), (a == func(j)));\n"
2518         "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2519         "}\n";
2520 
2521     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2522     ASSERT_NE(0u, program);
2523 
2524     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2525 
2526     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2527 }
2528 
2529 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2530 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2531 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)2532 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2533 {
2534     constexpr char kFS[] =
2535         "#version 300 es\n"
2536         "precision mediump float;\n"
2537         "out vec4 my_FragColor; \n"
2538         "void main() {\n"
2539         "    int j = 0; \n"
2540         "    bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2541         "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2542         "}\n";
2543 
2544     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2545     ASSERT_NE(0u, program);
2546 
2547     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2548 
2549     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2550 }
2551 
2552 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2553 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)2554 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2555 {
2556     constexpr char kFS[] =
2557         "#version 300 es\n"
2558         "precision mediump float;\n"
2559         "out vec4 my_FragColor;\n"
2560         "uniform int u_zero;\n"
2561         "int sideEffectCount = 0;\n"
2562         "float func() {\n"
2563         "    ++sideEffectCount;\n"
2564         "    return -1.0;\n"
2565         "}\n"
2566         "void main() {\n"
2567         "    vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2568         "    float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2569         "    bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2570         "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2571         "}\n";
2572 
2573     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2574     ASSERT_NE(0u, program);
2575 
2576     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2577 
2578     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2579 }
2580 
2581 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2582 // From WebGL test conformance/rendering/point-specific-shader-variables.html
2583 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)2584 TEST_P(GLSLTest, RenderTrisWithPointCoord)
2585 {
2586     constexpr char kVS[] =
2587         "attribute vec2 aPosition;\n"
2588         "void main()\n"
2589         "{\n"
2590         "    gl_Position = vec4(aPosition, 0, 1);\n"
2591         "    gl_PointSize = 1.0;\n"
2592         "}";
2593     constexpr char kFS[] =
2594         "void main()\n"
2595         "{\n"
2596         "    gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2597         "    gl_FragColor = vec4(0, 1, 0, 1);\n"
2598         "}";
2599 
2600     ANGLE_GL_PROGRAM(prog, kVS, kFS);
2601     drawQuad(prog.get(), "aPosition", 0.5f);
2602     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2603 }
2604 
2605 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)2606 TEST_P(GLSLTest, NestedPowStatements)
2607 {
2608     constexpr char kFS[] =
2609         "precision mediump float;\n"
2610         "float func(float v)\n"
2611         "{\n"
2612         "   float f1 = pow(v, 2.0);\n"
2613         "   return pow(f1 + v, 2.0);\n"
2614         "}\n"
2615         "void main()\n"
2616         "{\n"
2617         "    float v = func(2.0);\n"
2618         "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2619         "}";
2620 
2621     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
2622     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
2623     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2624 }
2625 
2626 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)2627 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2628 {
2629     constexpr char kFS[] =
2630         "#version 300 es\n"
2631         "out highp vec4 o_color;\n"
2632         "void main() {\n"
2633         "    highp float f = -1.0;\n"
2634         "    // atan(tan(0.5), -f) should be 0.5.\n"
2635         "    highp float v = atan(tan(0.5), -f);\n"
2636         "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2637         "}\n";
2638 
2639     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
2640     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
2641     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2642 }
2643 
2644 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)2645 TEST_P(GLSLTest_ES3, AtanVec2)
2646 {
2647     constexpr char kFS[] =
2648         "#version 300 es\n"
2649         "out highp vec4 o_color;\n"
2650         "void main() {\n"
2651         "    highp float f = 1.0;\n"
2652         "    // atan(tan(0.5), f) should be 0.5.\n"
2653         "    highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2654         "    o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2655         "vec4(1, 0, 0, 1);\n"
2656         "}\n";
2657 
2658     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
2659     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
2660     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2661 }
2662 
2663 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)2664 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2665 {
2666     constexpr char kVS[] =
2667         "#version 300 es\n"
2668         "in highp vec4 position;\n"
2669         "out mediump vec4 v_color;\n"
2670         "uniform int ui_one;\n"
2671         "uniform int ui_two;\n"
2672         "uniform int ui_three;\n"
2673         "void main() {\n"
2674         "    int s[3];\n"
2675         "    s[0] = ui_one;\n"
2676         "    s[1] = -(-(-ui_two + 1) + 1);\n"  // s[1] = -ui_two
2677         "    s[2] = ui_three;\n"
2678         "    int result = 0;\n"
2679         "    for (int i = 0; i < ui_three; i++) {\n"
2680         "        result += s[i];\n"
2681         "    }\n"
2682         "    v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2683         "    gl_Position = position;\n"
2684         "}\n";
2685     constexpr char kFS[] =
2686         "#version 300 es\n"
2687         "in mediump vec4 v_color;\n"
2688         "layout(location=0) out mediump vec4 o_color;\n"
2689         "void main() {\n"
2690         "    o_color = v_color;\n"
2691         "}\n";
2692 
2693     ANGLE_GL_PROGRAM(prog, kVS, kFS);
2694 
2695     GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
2696     ASSERT_NE(-1, oneIndex);
2697     GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
2698     ASSERT_NE(-1, twoIndex);
2699     GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
2700     ASSERT_NE(-1, threeIndex);
2701     glUseProgram(prog.get());
2702     glUniform1i(oneIndex, 1);
2703     glUniform1i(twoIndex, 2);
2704     glUniform1i(threeIndex, 3);
2705 
2706     drawQuad(prog.get(), "position", 0.5f);
2707     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2708 }
2709 
2710 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)2711 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2712 {
2713     constexpr char kVS[] =
2714         "#version 300 es\n"
2715         "in highp vec4 position;\n"
2716         "out mediump vec4 v_color;\n"
2717         "uniform uint ui_one;\n"
2718         "uniform uint ui_two;\n"
2719         "uniform uint ui_three;\n"
2720         "void main() {\n"
2721         "    uint s[3];\n"
2722         "    s[0] = ui_one;\n"
2723         "    s[1] = -(-(-ui_two + 1u) + 1u);\n"  // s[1] = -ui_two
2724         "    s[2] = ui_three;\n"
2725         "    uint result = 0u;\n"
2726         "    for (uint i = 0u; i < ui_three; i++) {\n"
2727         "        result += s[i];\n"
2728         "    }\n"
2729         "    v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2730         "    gl_Position = position;\n"
2731         "}\n";
2732     constexpr char kFS[] =
2733         "#version 300 es\n"
2734         "in mediump vec4 v_color;\n"
2735         "layout(location=0) out mediump vec4 o_color;\n"
2736         "void main() {\n"
2737         "    o_color = v_color;\n"
2738         "}\n";
2739 
2740     ANGLE_GL_PROGRAM(prog, kVS, kFS);
2741 
2742     GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
2743     ASSERT_NE(-1, oneIndex);
2744     GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
2745     ASSERT_NE(-1, twoIndex);
2746     GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
2747     ASSERT_NE(-1, threeIndex);
2748     glUseProgram(prog.get());
2749     glUniform1ui(oneIndex, 1u);
2750     glUniform1ui(twoIndex, 2u);
2751     glUniform1ui(threeIndex, 3u);
2752 
2753     drawQuad(prog.get(), "position", 0.5f);
2754     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2755 }
2756 
2757 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
2758 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)2759 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2760 {
2761     // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2762     // its default value false.
2763     constexpr char kFS[] =
2764         "precision mediump float;\n"
2765         "uniform bool keep_flop_positive;\n"
2766         "float flop;\n"
2767         "void main() {\n"
2768         "    flop = -1.0,\n"
2769         "    (flop *= -1.0,\n"
2770         "    keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2771         "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
2772         "}";
2773 
2774     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
2775     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
2776     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2777 }
2778 
2779 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)2780 TEST_P(GLSLTest, ExternalAnd2DSampler)
2781 {
2782     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
2783 
2784     constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
2785 precision mediump float;
2786 uniform samplerExternalOES tex0;
2787 uniform sampler2D tex1;
2788 void main(void)
2789 {
2790     vec2 uv = vec2(0.0, 0.0);
2791     gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
2792 })";
2793 
2794     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2795 }
2796 
2797 // Test that literal infinity can be written out from the shader translator.
2798 // 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)2799 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2800 {
2801     constexpr char kFS[] =
2802         "#version 300 es\n"
2803         "precision highp float;\n"
2804         "out vec4 out_color;\n"
2805         "uniform float u;\n"
2806         "void main()\n"
2807         "{\n"
2808         "   float infVar = 1.0e40 - u;\n"
2809         "   bool correct = isinf(infVar) && infVar > 0.0;\n"
2810         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2811         "}\n";
2812 
2813     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2814     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
2815     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2816 }
2817 
2818 // Test that literal negative infinity can be written out from the shader translator.
2819 // 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)2820 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2821 {
2822     constexpr char kFS[] =
2823         "#version 300 es\n"
2824         "precision highp float;\n"
2825         "out vec4 out_color;\n"
2826         "uniform float u;\n"
2827         "void main()\n"
2828         "{\n"
2829         "   float infVar = -1.0e40 + u;\n"
2830         "   bool correct = isinf(infVar) && infVar < 0.0;\n"
2831         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2832         "}\n";
2833 
2834     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2835     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
2836     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2837 }
2838 
2839 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2840 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
2841 // a unittest for them. Instead we add the tests as end2end so will in particular test
2842 // TranslatorHLSL when run on Windows.
2843 
2844 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)2845 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2846 {
2847     constexpr char kFS[] = R"(#version 300 es
2848 precision mediump float;
2849 out vec4 color;
2850 
2851 uniform float u;
2852 float c = 0.0;
2853 float sideEffect()
2854 {
2855     c = u;
2856     return c;
2857 }
2858 
2859 void main(void)
2860 {
2861     float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
2862     color = vec4(b + c);
2863 })";
2864 
2865     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2866 }
2867 
2868 // Test that passes splitting multiple declarations and comma operators and for loops are
2869 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)2870 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2871 {
2872     constexpr char kFS[] = R"(#version 300 es
2873 precision mediump float;
2874 out vec4 color;
2875 
2876 uniform float u;
2877 float c = 0.0;
2878 float sideEffect()
2879 {
2880     c = u;
2881     return c;
2882 }
2883 
2884 void main(void)
2885 {
2886     for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
2887     {
2888         b += 1.0;
2889         color = vec4(b);
2890     }
2891 })";
2892 
2893     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2894 }
2895 
2896 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)2897 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2898 {
2899     constexpr char kFS[] =
2900         "#version 300 es\n"
2901         "precision mediump float;\n"
2902         "out vec4 color;\n"
2903         "void main(void)\n"
2904         "{\n"
2905         " for(float a = 0.0, b = 1.0;; a++)\n"
2906         " {\n"
2907         "  b += 1.0;\n"
2908         "  if (a > 10.0) {break;}\n"
2909         "  color = vec4(b);\n"
2910         " }\n"
2911         "}\n";
2912 
2913     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2914 }
2915 
2916 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)2917 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2918 {
2919     constexpr char kFS[] =
2920         "#version 300 es\n"
2921         "precision mediump float;\n"
2922         "out vec4 color;\n"
2923         "void main(void)\n"
2924         "{\n"
2925         " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2926         " {\n"
2927         "  b += 1.0;\n"
2928         "  a += 1.0;\n"
2929         "  color = vec4(b);\n"
2930         " }\n"
2931         "}\n";
2932 
2933     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2934 }
2935 
2936 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2937 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)2938 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2939 {
2940     constexpr char kFS[] =
2941         "#version 300 es\n"
2942         "precision mediump float;\n"
2943         "out vec4 my_FragColor;\n"
2944         "uniform int u_zero;\n"
2945         "void main() {\n"
2946         "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2947         "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2948         "    float f = m[1][1];\n"
2949         "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2950         "}\n";
2951 
2952     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2953     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
2954     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2955 }
2956 
2957 class WebGLGLSLTest : public GLSLTest
2958 {
2959   protected:
WebGLGLSLTest()2960     WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2961 };
2962 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)2963 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2964 {
2965     GLint maxVaryings = 0;
2966     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2967 
2968     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2969     // This test should fail, since we are really using (maxVaryings + 1) varyings.
2970     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2971 }
2972 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)2973 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2974 {
2975     GLint maxVaryings = 0;
2976     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2977 
2978     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2979     // This test should fail, since we are really using (maxVaryings + 1) varyings.
2980     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2981 }
2982 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)2983 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2984 {
2985     GLint maxVaryings = 0;
2986     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2987 
2988     VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2989 }
2990 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)2991 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2992 {
2993     GLint maxVaryings = 0;
2994     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2995 
2996     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2997 }
2998 
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)2999 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
3000 {
3001     GLint maxVaryings = 0;
3002     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3003 
3004     VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
3005 }
3006 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)3007 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
3008 {
3009     GLint maxVaryings = 0;
3010     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3011 
3012     VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
3013 }
3014 
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)3015 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
3016 {
3017     GLint maxVaryings = 0;
3018     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3019 
3020     VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
3021                     false);
3022 }
3023 
3024 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)3025 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
3026 {
3027     // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
3028     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
3029 
3030     // Failing on N5X Oreo http://anglebug.com/2304
3031     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3032 
3033     constexpr char kFS[] =
3034         "#version 310 es\n"
3035         "precision mediump float;\n"
3036         "out vec4 my_FragColor;\n"
3037         "uniform int u_zero;\n"
3038         "void main() {\n"
3039         "    if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
3040         "    {\n"
3041         "        my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3042         "    }\n"
3043         "    else\n"
3044         "    {\n"
3045         "        my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
3046         "    }\n"
3047         "}\n";
3048 
3049     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3050     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3051     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3052 }
3053 
3054 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)3055 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
3056 {
3057     // http://anglebug.com/1924
3058     ANGLE_SKIP_TEST_IF(IsOpenGL());
3059 
3060     // The shader first assigns v.x to v.z (1.0)
3061     // Then v.y to v.y (2.0)
3062     // Then v.z to v.x (1.0)
3063     constexpr char kFS[] =
3064         "#version 300 es\n"
3065         "precision highp float;\n"
3066         "out vec4 my_FragColor;\n"
3067         "void main() {\n"
3068         "    vec3 v = vec3(1.0, 2.0, 3.0);\n"
3069         "    for (int i = 0; i < 3; i++) {\n"
3070         "        v.zyx[i] = v[i];\n"
3071         "    }\n"
3072         "    my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
3073         "0, 0, 1);\n"
3074         "}\n";
3075 
3076     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3077     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3078     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3079 }
3080 
3081 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)3082 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
3083 {
3084     // Crashes on an assertion.  The driver reports no atomic counter buffers when queried from the
3085     // program, but ANGLE believes there to be one.
3086     //
3087     // This is likely due to the fact that ANGLE generates the following code, as a side effect of
3088     // the code on which .length() is being called:
3089     //
3090     //     _uac1[(_uvalue = _utestSideEffectValue)];
3091     //
3092     // The driver is optimizing the subscription out, and calling the atomic counter inactive.  This
3093     // was observed on nvidia, mesa and amd/windows.
3094     //
3095     // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
3096     // driver says don't.
3097     //
3098     // http://anglebug.com/3782
3099     ANGLE_SKIP_TEST_IF(IsOpenGL());
3100 
3101     // Skipping due to a bug on the Qualcomm Vulkan Android driver.
3102     // http://anglebug.com/3726
3103     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3104 
3105     constexpr char kCS[] = R"(#version 310 es
3106 precision mediump float;
3107 layout(local_size_x=1) in;
3108 
3109 layout(binding = 0) uniform atomic_uint ac1[2][3];
3110 uniform uint testSideEffectValue;
3111 
3112 layout(binding = 1, std140) buffer Result
3113 {
3114     uint value;
3115 } result;
3116 
3117 void main() {
3118     bool passed = true;
3119     if (ac1.length() != 2)
3120     {
3121         passed = false;
3122     }
3123     uint value = 0u;
3124     if (ac1[(value = testSideEffectValue)].length() != 3)
3125     {
3126         passed = false;
3127     }
3128     if (value != testSideEffectValue)
3129     {
3130         passed = false;
3131     }
3132     result.value = passed ? 255u : 127u;
3133 })";
3134 
3135     constexpr unsigned int kUniformTestValue     = 17;
3136     constexpr unsigned int kExpectedSuccessValue = 255;
3137     constexpr unsigned int kAtomicCounterRows    = 2;
3138     constexpr unsigned int kAtomicCounterCols    = 3;
3139 
3140     GLint maxAtomicCounters = 0;
3141     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
3142     EXPECT_GL_NO_ERROR();
3143 
3144     // Required minimum is 8 by the spec
3145     EXPECT_GE(maxAtomicCounters, 8);
3146     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
3147                        kAtomicCounterRows * kAtomicCounterCols);
3148 
3149     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3150     glUseProgram(program.get());
3151 
3152     constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
3153     GLBuffer atomicCounterBuffer;
3154     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
3155     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
3156     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
3157 
3158     constexpr unsigned int kOutputInitValue = 0;
3159     GLBuffer shaderStorageBuffer;
3160     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3161     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
3162                  GL_STATIC_DRAW);
3163     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
3164 
3165     GLint uniformLocation = glGetUniformLocation(program.get(), "testSideEffectValue");
3166     EXPECT_NE(uniformLocation, -1);
3167     glUniform1i(uniformLocation, kUniformTestValue);
3168 
3169     glDispatchCompute(1, 1, 1);
3170 
3171     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3172 
3173     const GLuint *ptr = reinterpret_cast<const GLuint *>(
3174         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
3175     EXPECT_EQ(*ptr, kExpectedSuccessValue);
3176     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3177 }
3178 
3179 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)3180 TEST_P(GLSLTest_ES31, InactiveImages)
3181 {
3182     ANGLE_SKIP_TEST_IF(IsD3D11());
3183 
3184     constexpr char kCS[] = R"(#version 310 es
3185 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3186 layout(rgba32ui) uniform highp readonly uimage2D image1;
3187 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
3188 void main()
3189 {
3190 })";
3191 
3192     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3193 
3194     glUseProgram(program.get());
3195     glDispatchCompute(1, 1, 1);
3196     EXPECT_GL_NO_ERROR();
3197 
3198     // Verify that the images are indeed inactive.
3199     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
3200     EXPECT_GL_NO_ERROR();
3201     EXPECT_EQ(GL_INVALID_INDEX, index);
3202 
3203     index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
3204     EXPECT_GL_NO_ERROR();
3205     EXPECT_EQ(GL_INVALID_INDEX, index);
3206 }
3207 
3208 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)3209 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
3210 {
3211     constexpr char kCS[] = R"(#version 310 es
3212 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3213 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
3214 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
3215 void main()
3216 {
3217 })";
3218 
3219     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3220 
3221     glUseProgram(program.get());
3222     glDispatchCompute(1, 1, 1);
3223     EXPECT_GL_NO_ERROR();
3224 
3225     // Verify that the atomic counters are indeed inactive.
3226     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
3227     EXPECT_GL_NO_ERROR();
3228     EXPECT_EQ(GL_INVALID_INDEX, index);
3229 
3230     index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
3231     EXPECT_GL_NO_ERROR();
3232     EXPECT_EQ(GL_INVALID_INDEX, index);
3233 }
3234 
3235 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)3236 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
3237 {
3238     // While the sampler is being extracted and declared outside of the struct, it's not removed
3239     // from the struct definition.  http://anglebug.com/4211
3240     ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
3241 
3242     constexpr char kCS[] = R"(#version 310 es
3243 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3244 struct S
3245 {
3246     vec4 v;
3247     sampler2D t[10];
3248 };
3249 uniform S s;
3250 void main()
3251 {
3252 })";
3253 
3254     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3255 
3256     glUseProgram(program.get());
3257     glDispatchCompute(1, 1, 1);
3258     EXPECT_GL_NO_ERROR();
3259 }
3260 
3261 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)3262 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
3263 {
3264     constexpr char kFS[] =
3265         "#version 310 es\n"
3266         "precision mediump float;\n"
3267         "out vec4 my_FragColor;\n"
3268         "uniform ivec2 test[2][2];\n"
3269         "void main() {\n"
3270         "    bool passed = true;\n"
3271         "    for (int i = 0; i < 2; i++) {\n"
3272         "        for (int j = 0; j < 2; j++) {\n"
3273         "            if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
3274         "                passed = false;\n"
3275         "            }\n"
3276         "        }\n"
3277         "    }\n"
3278         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3279         "}\n";
3280 
3281     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3282     glUseProgram(program.get());
3283     for (int i = 0; i < 2; i++)
3284     {
3285         for (int j = 0; j < 2; j++)
3286         {
3287             std::stringstream uniformName;
3288             uniformName << "test[" << i << "][" << j << "]";
3289             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3290             // All array indices should be used.
3291             EXPECT_NE(uniformLocation, -1);
3292             glUniform2i(uniformLocation, i + 1, j + 1);
3293         }
3294     }
3295     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3296     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3297 }
3298 
3299 // Test that array indices for arrays of arrays of basic types work as expected
3300 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)3301 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
3302 {
3303     // anglebug.com/3821 - fails on AMD Windows
3304     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3305     constexpr char kFS[] =
3306         "#version 310 es\n"
3307         "precision mediump float;\n"
3308         "out vec4 my_FragColor;\n"
3309         "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
3310         "void main() {\n"
3311         "    bool passed = true;\n"
3312         "    for (int i = 0; i < 2; i++) {\n"
3313         "        for (int j = 0; j < 2; j++) {\n"
3314         "            if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
3315         "                passed = false;\n"
3316         "            }\n"
3317         "        }\n"
3318         "    }\n"
3319         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3320         "}\n";
3321 
3322     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3323     glUseProgram(program.get());
3324     // Use interface queries to determine buffer size and offset
3325     GLuint uboBlockIndex   = glGetProgramResourceIndex(program.get(), GL_UNIFORM_BLOCK, "UBO");
3326     GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
3327     GLint uboDataSize;
3328     glGetProgramResourceiv(program.get(), GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
3329                            nullptr, &uboDataSize);
3330     std::unique_ptr<char[]> uboData(new char[uboDataSize]);
3331     for (int i = 0; i < 2; i++)
3332     {
3333         std::stringstream resourceName;
3334         resourceName << "UBO.test[" << i << "][0]";
3335         GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
3336         struct
3337         {
3338             GLint stride;
3339             GLint offset;
3340         } values;
3341         GLuint resourceIndex =
3342             glGetProgramResourceIndex(program.get(), GL_UNIFORM, resourceName.str().c_str());
3343         ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
3344         glGetProgramResourceiv(program.get(), GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2,
3345                                nullptr, &values.stride);
3346         for (int j = 0; j < 2; j++)
3347         {
3348             GLint(&dataPtr)[2] =
3349                 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
3350             dataPtr[0] = i + 1;
3351             dataPtr[1] = j + 1;
3352         }
3353     }
3354     GLBuffer ubo;
3355     glBindBuffer(GL_UNIFORM_BUFFER, ubo.get());
3356     glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
3357     GLuint ubo_index = glGetUniformBlockIndex(program.get(), "UBO");
3358     ASSERT_NE(ubo_index, GL_INVALID_INDEX);
3359     glUniformBlockBinding(program.get(), ubo_index, 5);
3360     glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo.get());
3361     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3362     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3363 }
3364 
3365 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)3366 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
3367 {
3368     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3369     // so sampler array of array handling is disabled
3370     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3371 
3372     constexpr char kFS[] =
3373         "#version 310 es\n"
3374         "precision mediump float;\n"
3375         "out vec4 my_FragColor;\n"
3376         "uniform mediump isampler2D test[2][2];\n"
3377         "void main() {\n"
3378         "    bool passed = true;\n"
3379         "#define DO_CHECK(i,j) \\\n"
3380         "    if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
3381         "        passed = false; \\\n"
3382         "    }\n"
3383         "    DO_CHECK(0, 0)\n"
3384         "    DO_CHECK(0, 1)\n"
3385         "    DO_CHECK(1, 0)\n"
3386         "    DO_CHECK(1, 1)\n"
3387         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3388         "}\n";
3389 
3390     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3391     glUseProgram(program.get());
3392     GLTexture textures[2][2];
3393     for (int i = 0; i < 2; i++)
3394     {
3395         for (int j = 0; j < 2; j++)
3396         {
3397             // First generate the texture
3398             int textureUnit = i * 2 + j;
3399             glActiveTexture(GL_TEXTURE0 + textureUnit);
3400             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
3401             GLint texData[2] = {i + 1, j + 1};
3402             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
3403             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3404             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3405             // Then send it as a uniform
3406             std::stringstream uniformName;
3407             uniformName << "test[" << i << "][" << j << "]";
3408             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3409             // All array indices should be used.
3410             EXPECT_NE(uniformLocation, -1);
3411             glUniform1i(uniformLocation, textureUnit);
3412         }
3413     }
3414     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3415     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3416 }
3417 
3418 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)3419 TEST_P(GLSLTest_ES31, StructArraySampler)
3420 {
3421     constexpr char kFS[] =
3422         "#version 310 es\n"
3423         "precision mediump float;\n"
3424         "out vec4 my_FragColor;\n"
3425         "struct Data { mediump sampler2D data[2]; };\n"
3426         "uniform Data test;\n"
3427         "void main() {\n"
3428         "    my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
3429         "                        texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
3430         "}\n";
3431 
3432     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3433     glUseProgram(program.get());
3434     GLTexture textures[2];
3435     GLColor expected = MakeGLColor(32, 64, 96, 255);
3436     GLubyte data[6]  = {};  // Two bytes of padding, so that texture can be initialized with 4 bytes
3437     memcpy(data, expected.data(), sizeof(expected));
3438     for (int i = 0; i < 2; i++)
3439     {
3440         glActiveTexture(GL_TEXTURE0 + i);
3441         glBindTexture(GL_TEXTURE_2D, textures[i]);
3442         // Each element provides two components.
3443         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
3444         std::stringstream uniformName;
3445         uniformName << "test.data[" << i << "]";
3446         // Then send it as a uniform
3447         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3448         // The uniform should be active.
3449         EXPECT_NE(uniformLocation, -1);
3450         glUniform1i(uniformLocation, i);
3451     }
3452     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3453     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3454 }
3455 
3456 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)3457 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
3458 {
3459     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3460     // so sampler array of array handling is disabled
3461     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3462 
3463     constexpr char kFS[] =
3464         "#version 310 es\n"
3465         "precision mediump float;\n"
3466         "out vec4 my_FragColor;\n"
3467         "struct Data { mediump isampler2D data[2][2]; };\n"
3468         "uniform Data test;\n"
3469         "void main() {\n"
3470         "    bool passed = true;\n"
3471         "#define DO_CHECK(i,j) \\\n"
3472         "    if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
3473         "        passed = false; \\\n"
3474         "    }\n"
3475         "    DO_CHECK(0, 0)\n"
3476         "    DO_CHECK(0, 1)\n"
3477         "    DO_CHECK(1, 0)\n"
3478         "    DO_CHECK(1, 1)\n"
3479         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3480         "}\n";
3481 
3482     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3483     glUseProgram(program.get());
3484     GLTexture textures[2][2];
3485     for (int i = 0; i < 2; i++)
3486     {
3487         for (int j = 0; j < 2; j++)
3488         {
3489             // First generate the texture
3490             int textureUnit = i * 2 + j;
3491             glActiveTexture(GL_TEXTURE0 + textureUnit);
3492             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
3493             GLint texData[2] = {i + 1, j + 1};
3494             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
3495             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3496             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3497             // Then send it as a uniform
3498             std::stringstream uniformName;
3499             uniformName << "test.data[" << i << "][" << j << "]";
3500             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3501             // All array indices should be used.
3502             EXPECT_NE(uniformLocation, -1);
3503             glUniform1i(uniformLocation, textureUnit);
3504         }
3505     }
3506     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3507     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3508 }
3509 
3510 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)3511 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
3512 {
3513     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3514     // so sampler array of array handling is disabled
3515     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3516 
3517     GLint numTextures;
3518     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
3519     ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
3520     constexpr char kFS[] =
3521         "#version 310 es\n"
3522         "precision mediump float;\n"
3523         "out vec4 my_FragColor;\n"
3524         "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
3525         "uniform Data test[2];\n"
3526         "void main() {\n"
3527         "    bool passed = true;\n"
3528         "#define DO_CHECK_ikl(i,k,l) \\\n"
3529         "    if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
3530         "        passed = false; \\\n"
3531         "    } \\\n"
3532         "    if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
3533         "        passed = false; \\\n"
3534         "    }\n"
3535         "#define DO_CHECK_ik(i,k) \\\n"
3536         "    DO_CHECK_ikl(i, k, 0) \\\n"
3537         "    DO_CHECK_ikl(i, k, 1)\n"
3538         "#define DO_CHECK_i(i) \\\n"
3539         "    DO_CHECK_ik(i, 0) \\\n"
3540         "    DO_CHECK_ik(i, 1)\n"
3541         "    DO_CHECK_i(0)\n"
3542         "    DO_CHECK_i(1)\n"
3543         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3544         "}\n";
3545 
3546     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3547     glUseProgram(program.get());
3548     GLTexture textures[2][2][2][2];
3549     for (int i = 0; i < 2; i++)
3550     {
3551         for (int j = 0; j < 2; j++)
3552         {
3553             for (int k = 0; k < 2; k++)
3554             {
3555                 for (size_t l = 0; l < 2; l++)
3556                 {
3557                     // First generate the texture
3558                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
3559                     glActiveTexture(GL_TEXTURE0 + textureUnit);
3560                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
3561                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
3562                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
3563                                  &texData[0]);
3564                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3565                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3566                     // Then send it as a uniform
3567                     std::stringstream uniformName;
3568                     uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
3569                     GLint uniformLocation =
3570                         glGetUniformLocation(program.get(), uniformName.str().c_str());
3571                     // All array indices should be used.
3572                     EXPECT_NE(uniformLocation, -1);
3573                     glUniform1i(uniformLocation, textureUnit);
3574                 }
3575             }
3576         }
3577     }
3578     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3579     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3580 }
3581 
3582 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)3583 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
3584 {
3585     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3586     // so sampler array of array handling is disabled
3587     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3588 
3589     GLint numTextures;
3590     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
3591     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
3592     constexpr char kFS[] =
3593         "#version 310 es\n"
3594         "precision mediump float;\n"
3595         "out vec4 my_FragColor;\n"
3596         "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
3597         "uniform Data test[2][3];\n"
3598         "const vec2 ZERO = vec2(0.0, 0.0);\n"
3599         "void main() {\n"
3600         "    bool passed = true;\n"
3601         "#define DO_CHECK_INNER0(i,j,l) \\\n"
3602         "    if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
3603         "        passed = false; \\\n"
3604         "    }\n"
3605         "#define DO_CHECK_INNER1(i,j,l) \\\n"
3606         "    if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
3607         "        passed = false; \\\n"
3608         "    }\n"
3609         "#define DO_CHECK(i,j) \\\n"
3610         "    DO_CHECK_INNER0(i, j, 0) \\\n"
3611         "    DO_CHECK_INNER0(i, j, 1) \\\n"
3612         "    DO_CHECK_INNER1(i, j, 0) \\\n"
3613         "    DO_CHECK_INNER1(i, j, 1) \\\n"
3614         "    DO_CHECK_INNER1(i, j, 2)\n"
3615         "    DO_CHECK(0, 0)\n"
3616         "    DO_CHECK(0, 1)\n"
3617         "    DO_CHECK(0, 2)\n"
3618         "    DO_CHECK(1, 0)\n"
3619         "    DO_CHECK(1, 1)\n"
3620         "    DO_CHECK(1, 2)\n"
3621         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3622         "}\n";
3623 
3624     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3625     glUseProgram(program.get());
3626     struct Data
3627     {
3628         GLTexture data1[2];
3629         GLTexture data2[3];
3630     };
3631     Data textures[2][3];
3632     for (int i = 0; i < 2; i++)
3633     {
3634         for (int j = 0; j < 3; j++)
3635         {
3636             GLTexture *arrays[]     = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
3637             size_t arrayLengths[]   = {2, 3};
3638             size_t arrayOffsets[]   = {0, 2};
3639             size_t totalArrayLength = 5;
3640             for (int k = 0; k < 2; k++)
3641             {
3642                 GLTexture *array   = arrays[k];
3643                 size_t arrayLength = arrayLengths[k];
3644                 size_t arrayOffset = arrayOffsets[k];
3645                 for (size_t l = 0; l < arrayLength; l++)
3646                 {
3647                     // First generate the texture
3648                     int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
3649                     glActiveTexture(GL_TEXTURE0 + textureUnit);
3650                     glBindTexture(GL_TEXTURE_2D, array[l]);
3651                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
3652                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
3653                                  &texData[0]);
3654                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3655                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3656                     // Then send it as a uniform
3657                     std::stringstream uniformName;
3658                     uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
3659                     GLint uniformLocation =
3660                         glGetUniformLocation(program.get(), uniformName.str().c_str());
3661                     // All array indices should be used.
3662                     EXPECT_NE(uniformLocation, -1);
3663                     glUniform1i(uniformLocation, textureUnit);
3664                 }
3665             }
3666         }
3667     }
3668     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3669     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3670 }
3671 
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)3672 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
3673 {
3674     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3675     // so sampler array of array handling is disabled
3676     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3677 
3678     GLint numTextures;
3679     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
3680     ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
3681     constexpr char kFS[] =
3682         "#version 310 es\n"
3683         "precision mediump float;\n"
3684         "out vec4 my_FragColor;\n"
3685         "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
3686         "uniform Data test[3];\n"
3687         "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
3688         "void main() {\n"
3689         "    bool passed = true;\n"
3690         "#define DO_CHECK_ik(i,k) \\\n"
3691         "    if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
3692         "        passed = false; \\\n"
3693         "    } \\\n"
3694         "    if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
3695         "        passed = false; \\\n"
3696         "    }\n"
3697         "#define DO_CHECK_i(i) \\\n"
3698         "    DO_CHECK_ik(i, 0) \\\n"
3699         "    DO_CHECK_ik(i, 1)\n"
3700         "    DO_CHECK_i(0)\n"
3701         "    DO_CHECK_i(1)\n"
3702         "    DO_CHECK_i(2)\n"
3703         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3704         "}\n";
3705 
3706     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3707     glUseProgram(program.get());
3708     GLTexture textures[3][2][2];
3709     for (int i = 0; i < 3; i++)
3710     {
3711         for (int j = 0; j < 2; j++)
3712         {
3713             for (int k = 0; k < 2; k++)
3714             {
3715                 // First generate the texture
3716                 int textureUnit = k + 2 * (j + 2 * i);
3717                 glActiveTexture(GL_TEXTURE0 + textureUnit);
3718                 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
3719                 GLint texData[4]        = {i + 1, j + 1, k + 1, 1};
3720                 GLubyte texDataFloat[4] = {(i + 1) * 64 - 1, (j + 1) * 64 - 1, (k + 1) * 64 - 1,
3721                                            64};
3722                 if (j == 0)
3723                 {
3724                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
3725                                  &texData[0]);
3726                 }
3727                 else
3728                 {
3729                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3730                                  &texDataFloat[0]);
3731                 }
3732                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3733                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3734                 // Then send it as a uniform
3735                 std::stringstream uniformName;
3736                 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
3737                 GLint uniformLocation =
3738                     glGetUniformLocation(program.get(), uniformName.str().c_str());
3739                 // All array indices should be used.
3740                 EXPECT_NE(uniformLocation, -1);
3741                 glUniform1i(uniformLocation, textureUnit);
3742             }
3743         }
3744     }
3745     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3746     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3747 }
3748 
3749 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)3750 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
3751 {
3752     // anglebug.com/3832 - no sampler array params on Android
3753     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3754     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3755     // so sampler array of array handling is disabled
3756     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3757     constexpr char kFS[] =
3758         "#version 310 es\n"
3759         "precision mediump float;\n"
3760         "out vec4 my_FragColor;\n"
3761         "uniform mediump isampler2D test[2][3];\n"
3762         "const vec2 ZERO = vec2(0.0, 0.0);\n"
3763         "\n"
3764         "bool check(isampler2D data[2][3]);\n"
3765         "bool check(isampler2D data[2][3]) {\n"
3766         "#define DO_CHECK(i,j) \\\n"
3767         "    if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
3768         "        return false; \\\n"
3769         "    }\n"
3770         "    DO_CHECK(0, 0)\n"
3771         "    DO_CHECK(0, 1)\n"
3772         "    DO_CHECK(0, 2)\n"
3773         "    DO_CHECK(1, 0)\n"
3774         "    DO_CHECK(1, 1)\n"
3775         "    DO_CHECK(1, 2)\n"
3776         "    return true;\n"
3777         "}\n"
3778         "void main() {\n"
3779         "    bool passed = check(test);\n"
3780         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3781         "}\n";
3782 
3783     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3784     glUseProgram(program.get());
3785     GLTexture textures[2][3];
3786     for (int i = 0; i < 2; i++)
3787     {
3788         for (int j = 0; j < 3; j++)
3789         {
3790             // First generate the texture
3791             int textureUnit = i * 3 + j;
3792             glActiveTexture(GL_TEXTURE0 + textureUnit);
3793             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
3794             GLint texData[2] = {i + 1, j + 1};
3795             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
3796             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3797             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3798             // Then send it as a uniform
3799             std::stringstream uniformName;
3800             uniformName << "test[" << i << "][" << j << "]";
3801             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3802             // All array indices should be used.
3803             EXPECT_NE(uniformLocation, -1);
3804             glUniform1i(uniformLocation, textureUnit);
3805         }
3806     }
3807     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3808     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3809 }
3810 
3811 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)3812 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
3813 {
3814     // anglebug.com/3832 - no sampler array params on Android
3815     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3816     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3817     // so sampler array of array handling is disabled
3818     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3819     constexpr char kFS[] =
3820         "#version 310 es\n"
3821         "precision mediump float;\n"
3822         "out vec4 my_FragColor;\n"
3823         "struct Data { mediump isampler2D data[2][3]; };\n"
3824         "uniform Data test;\n"
3825         "const vec2 ZERO = vec2(0.0, 0.0);\n"
3826         "\n"
3827         "bool check(Data data) {\n"
3828         "#define DO_CHECK(i,j) \\\n"
3829         "    if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
3830         "        return false; \\\n"
3831         "    }\n"
3832         "    DO_CHECK(0, 0)\n"
3833         "    DO_CHECK(0, 1)\n"
3834         "    DO_CHECK(0, 2)\n"
3835         "    DO_CHECK(1, 0)\n"
3836         "    DO_CHECK(1, 1)\n"
3837         "    DO_CHECK(1, 2)\n"
3838         "    return true;\n"
3839         "}\n"
3840         "void main() {\n"
3841         "    bool passed = check(test);\n"
3842         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3843         "}\n";
3844 
3845     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3846     glUseProgram(program.get());
3847     GLTexture textures[2][3];
3848     for (int i = 0; i < 2; i++)
3849     {
3850         for (int j = 0; j < 3; j++)
3851         {
3852             // First generate the texture
3853             int textureUnit = i * 3 + j;
3854             glActiveTexture(GL_TEXTURE0 + textureUnit);
3855             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
3856             GLint texData[2] = {i + 1, j + 1};
3857             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
3858             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3859             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3860             // Then send it as a uniform
3861             std::stringstream uniformName;
3862             uniformName << "test.data[" << i << "][" << j << "]";
3863             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3864             // All array indices should be used.
3865             EXPECT_NE(uniformLocation, -1);
3866             glUniform1i(uniformLocation, textureUnit);
3867         }
3868     }
3869     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3870     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3871 }
3872 
3873 // Test that arrays of arrays of structs with arrays of arrays of samplers
3874 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)3875 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
3876 {
3877     // anglebug.com/3832 - no sampler array params on Android
3878     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3879     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3880     // so sampler array of array handling is disabled
3881     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3882     GLint numTextures;
3883     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
3884     ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
3885     constexpr char kFS[] =
3886         "#version 310 es\n"
3887         "precision mediump float;\n"
3888         "out vec4 my_FragColor;\n"
3889         "struct Data { mediump isampler2D data[2][2]; };\n"
3890         "uniform Data test[3][2];\n"
3891         "const vec2 ZERO = vec2(0.0, 0.0);\n"
3892         "\n"
3893         "bool check(Data data[3][2]) {\n"
3894         "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
3895         "    if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
3896         "        return false; \\\n"
3897         "    }\n"
3898         "#define DO_CHECK_ij(i,j) \\\n"
3899         "    DO_CHECK_ijkl(i, j, 0, 0) \\\n"
3900         "    DO_CHECK_ijkl(i, j, 0, 1) \\\n"
3901         "    DO_CHECK_ijkl(i, j, 1, 0) \\\n"
3902         "    DO_CHECK_ijkl(i, j, 1, 1)\n"
3903         "    DO_CHECK_ij(0, 0)\n"
3904         "    DO_CHECK_ij(1, 0)\n"
3905         "    DO_CHECK_ij(2, 0)\n"
3906         "    DO_CHECK_ij(0, 1)\n"
3907         "    DO_CHECK_ij(1, 1)\n"
3908         "    DO_CHECK_ij(2, 1)\n"
3909         "    return true;\n"
3910         "}\n"
3911         "void main() {\n"
3912         "    bool passed = check(test);\n"
3913         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3914         "}\n";
3915 
3916     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3917     glUseProgram(program.get());
3918     GLTexture textures[3][2][2][2];
3919     for (int i = 0; i < 3; i++)
3920     {
3921         for (int j = 0; j < 2; j++)
3922         {
3923             for (int k = 0; k < 2; k++)
3924             {
3925                 for (int l = 0; l < 2; l++)
3926                 {
3927                     // First generate the texture
3928                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
3929                     glActiveTexture(GL_TEXTURE0 + textureUnit);
3930                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
3931                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
3932                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
3933                                  &texData[0]);
3934                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3935                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3936                     // Then send it as a uniform
3937                     std::stringstream uniformName;
3938                     uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
3939                     GLint uniformLocation =
3940                         glGetUniformLocation(program.get(), uniformName.str().c_str());
3941                     // All array indices should be used.
3942                     EXPECT_NE(uniformLocation, -1);
3943                     glUniform1i(uniformLocation, textureUnit);
3944                 }
3945             }
3946         }
3947     }
3948     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3949     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3950 }
3951 
3952 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)3953 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
3954 {
3955     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
3956     // so sampler array of array handling is disabled
3957     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
3958 
3959     GLint numTextures;
3960     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
3961     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
3962     // anglebug.com/3832 - no sampler array params on Android
3963     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3964     // Seems like this is failing on Windows Intel?
3965     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
3966     constexpr char kFS[] =
3967         "#version 310 es\n"
3968         "precision mediump float;\n"
3969         "out vec4 my_FragColor;\n"
3970         "uniform mediump isampler2D test[2][3][4];\n"
3971         "uniform mediump isampler2D test2[4];\n"
3972         "const vec2 ZERO = vec2(0.0, 0.0);\n"
3973         "\n"
3974         "bool check1D(isampler2D arr[4], int x, int y) {\n"
3975         "    if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
3976         "    if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
3977         "    if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
3978         "    if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
3979         "    return true;\n"
3980         "}\n"
3981         "bool check2D(isampler2D arr[3][4], int x) {\n"
3982         "    if (!check1D(arr[0], x, 0)) return false;\n"
3983         "    if (!check1D(arr[1], x, 1)) return false;\n"
3984         "    if (!check1D(arr[2], x, 2)) return false;\n"
3985         "    return true;\n"
3986         "}\n"
3987         "bool check3D(isampler2D arr[2][3][4]) {\n"
3988         "    if (!check2D(arr[0], 0)) return false;\n"
3989         "    if (!check2D(arr[1], 1)) return false;\n"
3990         "    return true;\n"
3991         "}\n"
3992         "void main() {\n"
3993         "    bool passed = check3D(test) && check1D(test2, 7, 8);\n"
3994         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3995         "}\n";
3996 
3997     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3998     glUseProgram(program.get());
3999     GLTexture textures1[2][3][4];
4000     GLTexture textures2[4];
4001     for (int i = 0; i < 2; i++)
4002     {
4003         for (int j = 0; j < 3; j++)
4004         {
4005             for (int k = 0; k < 4; k++)
4006             {
4007                 // First generate the texture
4008                 int textureUnit = k + 4 * (j + 3 * i);
4009                 glActiveTexture(GL_TEXTURE0 + textureUnit);
4010                 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
4011                 GLint texData[3] = {i + 1, j + 1, k + 1};
4012                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
4013                              &texData[0]);
4014                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4015                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4016                 // Then send it as a uniform
4017                 std::stringstream uniformName;
4018                 uniformName << "test[" << i << "][" << j << "][" << k << "]";
4019                 GLint uniformLocation =
4020                     glGetUniformLocation(program.get(), uniformName.str().c_str());
4021                 // All array indices should be used.
4022                 EXPECT_NE(uniformLocation, -1);
4023                 glUniform1i(uniformLocation, textureUnit);
4024             }
4025         }
4026     }
4027     for (int k = 0; k < 4; k++)
4028     {
4029         // First generate the texture
4030         int textureUnit = 2 * 3 * 4 + k;
4031         glActiveTexture(GL_TEXTURE0 + textureUnit);
4032         glBindTexture(GL_TEXTURE_2D, textures2[k]);
4033         GLint texData[3] = {7 + 1, 8 + 1, k + 1};
4034         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
4035         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4036         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4037         // Then send it as a uniform
4038         std::stringstream uniformName;
4039         uniformName << "test2[" << k << "]";
4040         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4041         // All array indices should be used.
4042         EXPECT_NE(uniformLocation, -1);
4043         glUniform1i(uniformLocation, textureUnit);
4044     }
4045     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4046     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4047 }
4048 
4049 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)4050 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
4051 {
4052     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/3604 - rewriter can create name collisions
4053     GLint numTextures;
4054     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4055     ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
4056     // anglebug.com/3832 - no sampler array params on Android
4057     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4058     constexpr char kFS[] =
4059         "#version 310 es\n"
4060         "precision mediump sampler2D;\n"
4061         "precision mediump float;\n"
4062         "uniform sampler2D test_field1_field2[2][2];\n"
4063         "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
4064         "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
4065         "vec4 func1(sampler2D param_field1_field2[2][2],\n"
4066         "           int param_field1_field2_offset,\n"
4067         "           S1 param_field1,\n"
4068         "           S2 param) {\n"
4069         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
4070         "}\n"
4071         "out vec4 my_FragColor;\n"
4072         "void main() {\n"
4073         "    my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
4074         "    my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
4075         "    vec2 uv = vec2(0.0);\n"
4076         "    my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
4077         "                    texture(test_field1.field2[0][0], uv) +\n"
4078         "                    texture(test.field1_field2[0][0], uv);\n"
4079         "}\n";
4080     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4081     glActiveTexture(GL_TEXTURE0);
4082     GLTexture tex;
4083     glBindTexture(GL_TEXTURE_2D, tex);
4084     GLint zero = 0;
4085     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
4086     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4087     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4088 }
4089 
4090 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)4091 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
4092 {
4093     // anglebug.com/2703 - QC doesn't support arrays of samplers as parameters,
4094     // so sampler array of array handling is disabled
4095     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
4096 
4097     constexpr char kFS[] =
4098         "#version 310 es\n"
4099         "precision mediump sampler2D;\n"
4100         "precision mediump float;\n"
4101         "uniform sampler2D sampler_array[2][2];\n"
4102         "uniform int array[3][2];\n"
4103         "vec4 func1(int param[2],\n"
4104         "           int param2[3]) {\n"
4105         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
4106         "}\n"
4107         "out vec4 my_FragColor;\n"
4108         "void main() {\n"
4109         "    my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
4110         "    my_FragColor += func1(array[1], int[](1, 2, 3));\n"
4111         "}\n";
4112     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4113     glActiveTexture(GL_TEXTURE0);
4114     GLTexture tex;
4115     glBindTexture(GL_TEXTURE_2D, tex);
4116     GLint zero = 0;
4117     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
4118     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4119     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4120 }
4121 
4122 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
4123 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)4124 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
4125 {
4126     // This seems to be bugged on some version of Android. Might not affect the newest versions.
4127     // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
4128     // Test skipped on Android because of bug with Nexus 5X.
4129     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4130 
4131     constexpr char kVS[] =
4132         "#version 300 es\n"
4133         "out vec2 texCoord;\n"
4134         "in vec2 position;\n"
4135         "void main()\n"
4136         "{\n"
4137         "    gl_Position = vec4(position, 0, 1);\n"
4138         "    texCoord = position * 0.5 + vec2(0.5);\n"
4139         "}\n";
4140 
4141     constexpr char kSimpleFS[] =
4142         "#version 300 es\n"
4143         "in mediump vec2 texCoord;\n"
4144         "out mediump vec4 fragColor;\n"
4145         "void main()\n"
4146         "{\n"
4147         "    fragColor = vec4(texCoord, 0, 1);\n"
4148         "}\n";
4149 
4150     constexpr char kNestedFS[] =
4151         "#version 300 es\n"
4152         "uniform mediump sampler2D samplerA;\n"
4153         "uniform mediump sampler2D samplerB;\n"
4154         "in mediump vec2 texCoord;\n"
4155         "out mediump vec4 fragColor;\n"
4156         "void main ()\n"
4157         "{\n"
4158         "    fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
4159         "}\n";
4160 
4161     ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
4162     ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
4163 
4164     // Initialize a first texture with default texCoord data.
4165     GLTexture texA;
4166     glActiveTexture(GL_TEXTURE0);
4167     glBindTexture(GL_TEXTURE_2D, texA);
4168     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
4169                  GL_UNSIGNED_BYTE, nullptr);
4170     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4171     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4172 
4173     GLFramebuffer fbo;
4174     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4175     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
4176 
4177     drawQuad(initProg, "position", 0.5f);
4178     ASSERT_GL_NO_ERROR();
4179 
4180     // Initialize a second texture with a simple color pattern.
4181     GLTexture texB;
4182     glActiveTexture(GL_TEXTURE1);
4183     glBindTexture(GL_TEXTURE_2D, texB);
4184 
4185     std::array<GLColor, 4> simpleColors = {
4186         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4187     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4188                  simpleColors.data());
4189     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4190     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4191 
4192     // Draw with the nested program, using the first texture to index the second.
4193     glBindFramebuffer(GL_FRAMEBUFFER, 0);
4194     glUseProgram(nestedProg);
4195     GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
4196     ASSERT_NE(-1, samplerALoc);
4197     glUniform1i(samplerALoc, 0);
4198     GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
4199     ASSERT_NE(-1, samplerBLoc);
4200     glUniform1i(samplerBLoc, 1);
4201 
4202     drawQuad(nestedProg, "position", 0.5f);
4203     ASSERT_GL_NO_ERROR();
4204 
4205     // Compute four texel centers.
4206     Vector2 windowSize(getWindowWidth(), getWindowHeight());
4207     Vector2 quarterWindowSize = windowSize / 4;
4208     Vector2 ul                = quarterWindowSize;
4209     Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
4210     Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
4211     Vector2 lr = windowSize - quarterWindowSize;
4212 
4213     EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
4214     EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
4215     EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
4216     EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
4217 }
4218 
4219 // Tests that using a constant declaration as the only statement in a for loop without curly braces
4220 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)4221 TEST_P(GLSLTest, ConstantStatementInForLoop)
4222 {
4223     constexpr char kVS[] =
4224         "void main()\n"
4225         "{\n"
4226         "    for (int i = 0; i < 10; ++i)\n"
4227         "        const int b = 0;\n"
4228         "}\n";
4229 
4230     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
4231     EXPECT_NE(0u, shader);
4232     glDeleteShader(shader);
4233 }
4234 
4235 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
4236 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)4237 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
4238 {
4239     constexpr char kVS[] =
4240         "void main()\n"
4241         "{\n"
4242         "    for (const int i = 0; i < 0;) {}\n"
4243         "}\n";
4244 
4245     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
4246     EXPECT_NE(0u, shader);
4247     glDeleteShader(shader);
4248 }
4249 
4250 // Test that uninitialized local variables are initialized to 0.
TEST_P(GLSLTest_ES3,InitUninitializedLocals)4251 TEST_P(GLSLTest_ES3, InitUninitializedLocals)
4252 {
4253     // Test skipped on Android GLES because local variable initialization is disabled.
4254     // http://anglebug.com/2046
4255     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4256 
4257     constexpr char kFS[] =
4258         "#version 300 es\n"
4259         "precision mediump float;\n"
4260         "out vec4 my_FragColor;\n"
4261         "int result = 0;\n"
4262         "void main()\n"
4263         "{\n"
4264         "    int u;\n"
4265         "    result += u;\n"
4266         "    int k = 0;\n"
4267         "    for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
4268         "    {\n"
4269         "        result += j;\n"
4270         "    }\n"
4271         "    if (result == 2)\n"
4272         "    {\n"
4273         "        my_FragColor = vec4(0, 1, 0, 1);\n"
4274         "    }\n"
4275         "    else\n"
4276         "    {\n"
4277         "        my_FragColor = vec4(1, 0, 0, 1);\n"
4278         "    }\n"
4279         "}\n";
4280 
4281     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4282     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4283     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4284 }
4285 
4286 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
4287 // specifically tests with two different struct variables declared in the same block.
TEST_P(GLSLTest,InitUninitializedStructContainingArrays)4288 TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
4289 {
4290     // Test skipped on Android GLES because local variable initialization is disabled.
4291     // http://anglebug.com/2046
4292     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4293 
4294     constexpr char kFS[] =
4295         "precision mediump float;\n"
4296         "struct T\n"
4297         "{\n"
4298         "    int a[2];\n"
4299         "};\n"
4300         "struct S\n"
4301         "{\n"
4302         "    T t[2];\n"
4303         "};\n"
4304         "void main()\n"
4305         "{\n"
4306         "    S s;\n"
4307         "    S s2;\n"
4308         "    if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
4309         "    {\n"
4310         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
4311         "    }\n"
4312         "    else\n"
4313         "    {\n"
4314         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
4315         "    }\n"
4316         "}\n";
4317 
4318     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4319     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
4320     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4321 }
4322 
4323 // Verify that two shaders with the same uniform name and members but different structure names will
4324 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)4325 TEST_P(GLSLTest, StructureNameMatchingTest)
4326 {
4327     const char *vsSource =
4328         "// Structures must have the same name, sequence of type names, and\n"
4329         "// type definitions, and field names to be considered the same type.\n"
4330         "// GLSL 1.017 4.2.4\n"
4331         "precision mediump float;\n"
4332         "struct info {\n"
4333         "  vec4 pos;\n"
4334         "  vec4 color;\n"
4335         "};\n"
4336         "\n"
4337         "uniform info uni;\n"
4338         "void main()\n"
4339         "{\n"
4340         "    gl_Position = uni.pos;\n"
4341         "}\n";
4342 
4343     GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
4344     ASSERT_NE(0u, vs);
4345     glDeleteShader(vs);
4346 
4347     const char *fsSource =
4348         "// Structures must have the same name, sequence of type names, and\n"
4349         "// type definitions, and field names to be considered the same type.\n"
4350         "// GLSL 1.017 4.2.4\n"
4351         "precision mediump float;\n"
4352         "struct info1 {\n"
4353         "  vec4 pos;\n"
4354         "  vec4 color;\n"
4355         "};\n"
4356         "\n"
4357         "uniform info1 uni;\n"
4358         "void main()\n"
4359         "{\n"
4360         "    gl_FragColor = uni.color;\n"
4361         "}\n";
4362 
4363     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
4364     ASSERT_NE(0u, fs);
4365     glDeleteShader(fs);
4366 
4367     GLuint program = CompileProgram(vsSource, fsSource);
4368     EXPECT_EQ(0u, program);
4369 }
4370 
4371 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(GLSLTest_ES3,UninitializedNamelessStructInForInitStatement)4372 TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
4373 {
4374     // Test skipped on Android GLES because local variable initialization is disabled.
4375     // http://anglebug.com/2046
4376     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4377 
4378     constexpr char kFS[] =
4379         "#version 300 es\n"
4380         "precision highp float;\n"
4381         "out vec4 my_FragColor;\n"
4382         "void main()\n"
4383         "{\n"
4384         "    my_FragColor = vec4(1, 0, 0, 1);\n"
4385         "    for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
4386         "        my_FragColor = vec4(0, 1, 0, 1);\n"
4387         "    }\n"
4388         "}\n";
4389 
4390     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4391     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4392     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4393 }
4394 
4395 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)4396 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
4397 {
4398     // http://anglebug.com/2862
4399     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4400 
4401     constexpr char kFS[] =
4402         "precision mediump float;\n"
4403         "int result;\n"
4404         "int i[2], j = i[0] + 1;\n"
4405         "void main()\n"
4406         "{\n"
4407         "    result += j;\n"
4408         "    if (result == 1)\n"
4409         "    {\n"
4410         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
4411         "    }\n"
4412         "    else\n"
4413         "    {\n"
4414         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
4415         "    }\n"
4416         "}\n";
4417 
4418     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4419     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
4420     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4421 }
4422 
4423 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)4424 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
4425 {
4426     constexpr char kFS[] =
4427         "precision mediump float;\n"
4428         "struct { float q; } b;\n"
4429         "void main()\n"
4430         "{\n"
4431         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
4432         "    if (b.q == 0.0)\n"
4433         "    {\n"
4434         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
4435         "    }\n"
4436         "}\n";
4437 
4438     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4439     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
4440     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4441 }
4442 
4443 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)4444 TEST_P(GLSLTest, EmbeddedStructUniform)
4445 {
4446     const char kFragmentShader[] = R"(precision mediump float;
4447 uniform struct { float q; } b;
4448 void main()
4449 {
4450     gl_FragColor = vec4(1, 0, 0, 1);
4451     if (b.q == 0.5)
4452     {
4453         gl_FragColor = vec4(0, 1, 0, 1);
4454     }
4455 })";
4456 
4457     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
4458     glUseProgram(program);
4459     GLint uniLoc = glGetUniformLocation(program, "b.q");
4460     ASSERT_NE(-1, uniLoc);
4461     glUniform1f(uniLoc, 0.5f);
4462 
4463     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
4464     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4465 }
4466 
4467 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)4468 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
4469 {
4470     const char kVertexShader[] = R"(attribute vec2 position;
4471 varying vec2 texCoord;
4472 void main()
4473 {
4474     gl_Position = vec4(position, 0, 1);
4475     texCoord = position * 0.5 + vec2(0.5);
4476 })";
4477 
4478     const char kFragmentShader[] = R"(precision mediump float;
4479 struct S { sampler2D samp; bool b; };
4480 uniform S uni;
4481 varying vec2 texCoord;
4482 void main()
4483 {
4484     if (uni.b)
4485     {
4486         gl_FragColor = texture2D(uni.samp, texCoord);
4487     }
4488     else
4489     {
4490         gl_FragColor = vec4(1, 0, 0, 1);
4491     }
4492 })";
4493 
4494     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
4495     glUseProgram(program);
4496 
4497     GLint bLoc = glGetUniformLocation(program, "uni.b");
4498     ASSERT_NE(-1, bLoc);
4499     GLint sampLoc = glGetUniformLocation(program, "uni.samp");
4500     ASSERT_NE(-1, sampLoc);
4501 
4502     glUniform1i(bLoc, 1);
4503 
4504     std::array<GLColor, 4> kGreenPixels = {
4505         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
4506 
4507     GLTexture tex;
4508     glBindTexture(GL_TEXTURE_2D, tex);
4509     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4510                  kGreenPixels.data());
4511     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4512     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4513     ASSERT_GL_NO_ERROR();
4514 
4515     drawQuad(program, "position", 0.5f);
4516     ASSERT_GL_NO_ERROR();
4517 
4518     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4519 }
4520 
4521 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)4522 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
4523 {
4524     const char kFragmentShader[] = R"(precision mediump float;
4525 uniform struct { float q; } b, c;
4526 void main()
4527 {
4528     gl_FragColor = vec4(1, 0, 0, 1);
4529     if (b.q == 0.5 && c.q == 1.0)
4530     {
4531         gl_FragColor = vec4(0, 1, 0, 1);
4532     }
4533 })";
4534 
4535     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
4536     glUseProgram(program);
4537 
4538     GLint uniLocB = glGetUniformLocation(program, "b.q");
4539     ASSERT_NE(-1, uniLocB);
4540     glUniform1f(uniLocB, 0.5f);
4541 
4542     GLint uniLocC = glGetUniformLocation(program, "c.q");
4543     ASSERT_NE(-1, uniLocC);
4544     glUniform1f(uniLocC, 1.0f);
4545 
4546     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
4547     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4548 }
4549 
4550 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)4551 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
4552 {
4553     constexpr char kFS[] =
4554         "#version 300 es\n"
4555         "precision highp float;\n"
4556         "out vec4 my_FragColor;\n"
4557         "void main()\n"
4558         "{\n"
4559         "    float i = 0.0;\n"
4560         "    while (bool foo = (i < 1.5))\n"
4561         "    {\n"
4562         "        if (!foo)\n"
4563         "        {\n"
4564         "            ++i;\n"
4565         "        }\n"
4566         "        if (i > 3.5)\n"
4567         "        {\n"
4568         "            break;\n"
4569         "        }\n"
4570         "        ++i;\n"
4571         "    }\n"
4572         "    my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
4573         "}\n";
4574 
4575     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4576     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4577     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4578 }
4579 
4580 // Test that a variable hides a user-defined function with the same name after its initializer.
4581 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
4582 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)4583 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
4584 {
4585     constexpr char kFS[] =
4586         "precision mediump float;\n"
4587         "uniform vec4 u;\n"
4588         "vec4 foo()\n"
4589         "{\n"
4590         "    return u;\n"
4591         "}\n"
4592         "void main()\n"
4593         "{\n"
4594         "    vec4 foo = foo();\n"
4595         "    gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
4596         "}\n";
4597 
4598     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4599     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
4600     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4601 }
4602 
4603 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)4604 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
4605 {
4606     constexpr char kFS[] =
4607         "precision mediump float;\n"
4608         "uniform float u_zero;\n"
4609         "struct S { float foo; };\n"
4610         "struct S2 { float foo; };\n"
4611         "float get(S s) { return s.foo + u_zero; }\n"
4612         "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
4613         "void main()\n"
4614         "{\n"
4615         "    S s;\n"
4616         "    s.foo = 0.5;\n"
4617         "    S2 s2;\n"
4618         "    s2.foo = 0.25;\n"
4619         "    gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
4620         "}\n";
4621 
4622     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4623     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
4624     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4625 }
4626 
4627 // Test that a varying struct that's not statically used in the fragment shader works.
4628 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)4629 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
4630 {
4631     constexpr char kVS[] =
4632         "#version 300 es\n"
4633         "struct S {\n"
4634         "    vec4 field;\n"
4635         "};\n"
4636         "out S varStruct;\n"
4637         "void main()\n"
4638         "{\n"
4639         "    gl_Position = vec4(1.0);\n"
4640         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
4641         "}\n";
4642 
4643     constexpr char kFS[] =
4644         "#version 300 es\n"
4645         "precision mediump float;\n"
4646         "struct S {\n"
4647         "    vec4 field;\n"
4648         "};\n"
4649         "in S varStruct;\n"
4650         "out vec4 col;\n"
4651         "void main()\n"
4652         "{\n"
4653         "    col = vec4(1.0);\n"
4654         "}\n";
4655 
4656     ANGLE_GL_PROGRAM(program, kVS, kFS);
4657 }
4658 
4659 // Test that a varying struct that's not declared in the fragment shader links successfully.
4660 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)4661 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
4662 {
4663     constexpr char kVS[] =
4664         "#version 300 es\n"
4665         "struct S {\n"
4666         "    vec4 field;\n"
4667         "};\n"
4668         "out S varStruct;\n"
4669         "void main()\n"
4670         "{\n"
4671         "    gl_Position = vec4(1.0);\n"
4672         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
4673         "}\n";
4674 
4675     constexpr char kFS[] =
4676         "#version 300 es\n"
4677         "precision mediump float;\n"
4678         "out vec4 col;\n"
4679         "void main()\n"
4680         "{\n"
4681         "    col = vec4(1.0);\n"
4682         "}\n";
4683 
4684     ANGLE_GL_PROGRAM(program, kVS, kFS);
4685 }
4686 
4687 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
4688 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)4689 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
4690 {
4691     // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
4692     // going to use it.  See section 9.1 in
4693     // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
4694     // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
4695     //
4696     // However, nvidia OpenGL ES drivers fail to link this program.
4697     //
4698     // http://anglebug.com/3413
4699     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
4700 
4701     constexpr char kVS[] =
4702         "#version 300 es\n"
4703         "void main()\n"
4704         "{\n"
4705         "    gl_Position = vec4(1.0);\n"
4706         "}\n";
4707 
4708     constexpr char kFS[] =
4709         "#version 300 es\n"
4710         "precision mediump float;\n"
4711         "out vec4 col;\n"
4712         "struct S {\n"
4713         "    vec4 field;\n"
4714         "};\n"
4715         "in S varStruct;\n"
4716         "void main()\n"
4717         "{\n"
4718         "    col = vec4(1.0);\n"
4719         "}\n";
4720 
4721     ANGLE_GL_PROGRAM(program, kVS, kFS);
4722 }
4723 
4724 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotInitializedInVertexShader)4725 TEST_P(GLSLTest_ES3, VaryingStructNotInitializedInVertexShader)
4726 {
4727     // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
4728     // specification that the varying values are undefined in the fragment stage).  See section 9.1
4729     // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
4730     // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
4731     //
4732     // However, windows and mac OpenGL drivers fail to link this program.  With a message like:
4733     //
4734     // > Input of fragment shader 'varStruct' not written by vertex shader
4735     //
4736     // http://anglebug.com/3413
4737     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || (IsWindows() && !IsNVIDIA())));
4738 
4739     constexpr char kVS[] =
4740         "#version 300 es\n"
4741         "struct S {\n"
4742         "    vec4 field;\n"
4743         "};\n"
4744         "out S varStruct;\n"
4745         "void main()\n"
4746         "{\n"
4747         "    gl_Position = vec4(1.0);\n"
4748         "}\n";
4749 
4750     constexpr char kFS[] =
4751         "#version 300 es\n"
4752         "precision mediump float;\n"
4753         "out vec4 col;\n"
4754         "struct S {\n"
4755         "    vec4 field;\n"
4756         "};\n"
4757         "in S varStruct;\n"
4758         "void main()\n"
4759         "{\n"
4760         "    col = varStruct.field;\n"
4761         "}\n";
4762 
4763     ANGLE_GL_PROGRAM(program, kVS, kFS);
4764 }
4765 
4766 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)4767 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
4768 {
4769     constexpr char kVS[] =
4770         "#version 300 es\n"
4771         "in vec4 inputAttribute;\n"
4772         "struct S {\n"
4773         "    vec4 field;\n"
4774         "};\n"
4775         "out S varStruct;\n"
4776         "out S varStruct2;\n"
4777         "void main()\n"
4778         "{\n"
4779         "    gl_Position = inputAttribute;\n"
4780         "    varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
4781         "    varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
4782         "}\n";
4783 
4784     constexpr char kFS[] =
4785         "#version 300 es\n"
4786         "precision mediump float;\n"
4787         "out vec4 col;\n"
4788         "struct S {\n"
4789         "    vec4 field;\n"
4790         "};\n"
4791         "in S varStruct;\n"
4792         "in S varStruct2;\n"
4793         "void main()\n"
4794         "{\n"
4795         "    col = varStruct.field + varStruct2.field;\n"
4796         "}\n";
4797 
4798     ANGLE_GL_PROGRAM(program, kVS, kFS);
4799     drawQuad(program.get(), "inputAttribute", 0.5f);
4800     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4801 }
4802 
4803 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)4804 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
4805 {
4806     // TODO(syoussefi): fails on android with:
4807     //
4808     // > Internal Vulkan error: A return array was too small for the result
4809     //
4810     // http://anglebug.com/3220
4811     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
4812 
4813     constexpr char kVS[] =
4814         "#version 300 es\n"
4815         "in vec4 inputAttribute;\n"
4816         "struct S {\n"
4817         "    vec4 field1;\n"
4818         "    vec4 field2;\n"
4819         "};\n"
4820         "out S varStruct;\n"
4821         "out S varStruct2;\n"
4822         "void main()\n"
4823         "{\n"
4824         "    gl_Position = inputAttribute;\n"
4825         "    varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
4826         "    varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
4827         "    varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
4828         "    varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
4829         "}\n";
4830 
4831     constexpr char kFS[] =
4832         "#version 300 es\n"
4833         "precision mediump float;\n"
4834         "out vec4 col;\n"
4835         "struct S {\n"
4836         "    vec4 field1;\n"
4837         "    vec4 field2;\n"
4838         "};\n"
4839         "in S varStruct;\n"
4840         "in S varStruct2;\n"
4841         "void main()\n"
4842         "{\n"
4843         "    col = varStruct.field1 + varStruct2.field2;\n"
4844         "}\n";
4845 
4846     ANGLE_GL_PROGRAM(program, kVS, kFS);
4847     drawQuad(program.get(), "inputAttribute", 0.5f);
4848     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4849 }
4850 
4851 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)4852 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
4853 {
4854     constexpr char kVS[] =
4855         "#version 300 es\n"
4856         "in vec4 inputAttribute;\n"
4857         "out vec4 varArray[4];\n"
4858         "void main()\n"
4859         "{\n"
4860         "    gl_Position = inputAttribute;\n"
4861         "    varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
4862         "    varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
4863         "    varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
4864         "    varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
4865         "}\n";
4866 
4867     constexpr char kFS[] =
4868         "#version 300 es\n"
4869         "precision mediump float;\n"
4870         "out vec4 col;\n"
4871         "void main()\n"
4872         "{\n"
4873         "    col = vec4(0.0, 0.0, 0.0, 1.0);\n"
4874         "}\n";
4875 
4876     ANGLE_GL_PROGRAM(program, kVS, kFS);
4877     drawQuad(program.get(), "inputAttribute", 0.5f);
4878     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4879 }
4880 
4881 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)4882 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
4883 {
4884     constexpr char kVS[] =
4885         "#version 300 es\n"
4886         "in vec4 inputAttribute;\n"
4887         "struct S {\n"
4888         "    vec4 field;\n"
4889         "};\n"
4890         "out S varStruct;\n"
4891         "out S varStruct2;\n"
4892         "void main()\n"
4893         "{\n"
4894         "    gl_Position = inputAttribute;\n"
4895         "    varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
4896         "    varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
4897         "}\n";
4898 
4899     constexpr char kFS[] =
4900         "#version 300 es\n"
4901         "precision mediump float;\n"
4902         "out vec4 col;\n"
4903         "struct S {\n"
4904         "    vec4 field;\n"
4905         "};\n"
4906         "in S varStruct;\n"
4907         "in S varStruct2;\n"
4908         "void main()\n"
4909         "{\n"
4910         "    col = varStruct.field;\n"
4911         "}\n";
4912 
4913     ANGLE_GL_PROGRAM(program, kVS, kFS);
4914     drawQuad(program.get(), "inputAttribute", 0.5f);
4915     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4916 }
4917 
4918 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)4919 TEST_P(GLSLTest_ES3, VaryingMatrices)
4920 {
4921     constexpr char kVS[] =
4922         "#version 300 es\n"
4923         "in vec4 inputAttribute;\n"
4924         "out mat2x2 varMat;\n"
4925         "out mat2x2 varMat2;\n"
4926         "out mat4x3 varMat3;\n"
4927         "void main()\n"
4928         "{\n"
4929         "    gl_Position = inputAttribute;\n"
4930         "    varMat[0] = vec2(1, 1);\n"
4931         "    varMat[1] = vec2(1, 1);\n"
4932         "    varMat2[0] = vec2(0.5, 0.5);\n"
4933         "    varMat2[1] = vec2(0.5, 0.5);\n"
4934         "    varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
4935         "    varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
4936         "    varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
4937         "    varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
4938         "}\n";
4939 
4940     constexpr char kFS[] =
4941         "#version 300 es\n"
4942         "precision mediump float;\n"
4943         "out vec4 col;\n"
4944         "in mat2x2 varMat;\n"
4945         "in mat2x2 varMat2;\n"
4946         "in mat4x3 varMat3;\n"
4947         "void main()\n"
4948         "{\n"
4949         "    col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
4950         "}\n";
4951 
4952     ANGLE_GL_PROGRAM(program, kVS, kFS);
4953     drawQuad(program.get(), "inputAttribute", 0.5f);
4954     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
4955 }
4956 
4957 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)4958 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
4959 {
4960     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
4961     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
4962 
4963     const char kFragmentShader[] = R"(precision mediump float;
4964 struct S { sampler2D samplerMember; };
4965 uniform S uStruct;
4966 uniform vec2 uTexCoord;
4967 vec4 foo(S structVar)
4968 {
4969     return texture2D(structVar.samplerMember, uTexCoord);
4970 }
4971 void main()
4972 {
4973     gl_FragColor = foo(uStruct);
4974 })";
4975 
4976     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
4977 
4978     // Initialize the texture with green.
4979     GLTexture tex;
4980     glActiveTexture(GL_TEXTURE0);
4981     glBindTexture(GL_TEXTURE_2D, tex);
4982     GLubyte texData[] = {0u, 255u, 0u, 255u};
4983     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
4984     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4985     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4986     ASSERT_GL_NO_ERROR();
4987 
4988     // Draw
4989     glUseProgram(program);
4990     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
4991     ASSERT_NE(-1, samplerMemberLoc);
4992     glUniform1i(samplerMemberLoc, 0);
4993     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
4994     ASSERT_NE(-1, texCoordLoc);
4995     glUniform2f(texCoordLoc, 0.5f, 0.5f);
4996 
4997     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4998     ASSERT_GL_NO_ERROR();
4999 
5000     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5001 }
5002 
5003 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)5004 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
5005 {
5006     // Shader failed to compile on Android. http://anglebug.com/2114
5007     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
5008 
5009     const char kFragmentShader[] = R"(precision mediump float;
5010 struct S { sampler2D samplerMember; };
5011 uniform S uStruct;
5012 uniform vec2 uTexCoord;
5013 vec4 foo(S structVar);
5014 vec4 foo(S structVar)
5015 {
5016     return texture2D(structVar.samplerMember, uTexCoord);
5017 }
5018 void main()
5019 {
5020     gl_FragColor = foo(uStruct);
5021 })";
5022 
5023     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5024 
5025     // Initialize the texture with green.
5026     GLTexture tex;
5027     glActiveTexture(GL_TEXTURE0);
5028     glBindTexture(GL_TEXTURE_2D, tex);
5029     GLubyte texData[] = {0u, 255u, 0u, 255u};
5030     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5031     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5032     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5033     ASSERT_GL_NO_ERROR();
5034 
5035     // Draw
5036     glUseProgram(program);
5037     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
5038     ASSERT_NE(-1, samplerMemberLoc);
5039     glUniform1i(samplerMemberLoc, 0);
5040     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5041     ASSERT_NE(-1, texCoordLoc);
5042     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5043 
5044     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5045     ASSERT_GL_NO_ERROR();
5046 
5047     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5048 }
5049 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)5050 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
5051 {
5052     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
5053     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
5054 
5055     constexpr char kFS[] =
5056         "precision mediump float;\n"
5057         "struct S\n"
5058         "{\n"
5059         "    sampler2D samplerMember; \n"
5060         "};\n"
5061         "uniform S uStructs[2];\n"
5062         "uniform vec2 uTexCoord;\n"
5063         "\n"
5064         "vec4 foo(S[2] structs)\n"
5065         "{\n"
5066         "    return texture2D(structs[0].samplerMember, uTexCoord);\n"
5067         "}\n"
5068         "void main()\n"
5069         "{\n"
5070         "    gl_FragColor = foo(uStructs);\n"
5071         "}\n";
5072 
5073     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5074 
5075     // Initialize the texture with green.
5076     GLTexture tex;
5077     glActiveTexture(GL_TEXTURE0);
5078     glBindTexture(GL_TEXTURE_2D, tex);
5079     GLubyte texData[] = {0u, 255u, 0u, 255u};
5080     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5081     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5082     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5083     ASSERT_GL_NO_ERROR();
5084 
5085     // Draw
5086     glUseProgram(program);
5087     GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
5088     ASSERT_NE(-1, samplerMemberLoc);
5089     glUniform1i(samplerMemberLoc, 0);
5090     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5091     ASSERT_NE(-1, texCoordLoc);
5092     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5093 
5094     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5095     ASSERT_GL_NO_ERROR();
5096 
5097     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5098 }
5099 
5100 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)5101 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
5102 {
5103     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
5104     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
5105 
5106     // TODO(jmadill): Fix on Android/vulkan if possible. http://anglebug.com/2703
5107     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
5108 
5109     constexpr char kFS[] =
5110         "precision mediump float;\n"
5111         "struct S\n"
5112         "{\n"
5113         "    sampler2D samplerMembers[2];\n"
5114         "};\n"
5115         "uniform S uStruct;\n"
5116         "uniform vec2 uTexCoord;\n"
5117         "\n"
5118         "vec4 foo(S str)\n"
5119         "{\n"
5120         "    return texture2D(str.samplerMembers[0], uTexCoord);\n"
5121         "}\n"
5122         "void main()\n"
5123         "{\n"
5124         "    gl_FragColor = foo(uStruct);\n"
5125         "}\n";
5126 
5127     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5128 
5129     // Initialize the texture with green.
5130     GLTexture tex;
5131     glActiveTexture(GL_TEXTURE0);
5132     glBindTexture(GL_TEXTURE_2D, tex);
5133     GLubyte texData[] = {0u, 255u, 0u, 255u};
5134     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5135     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5136     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5137     ASSERT_GL_NO_ERROR();
5138 
5139     // Draw
5140     glUseProgram(program);
5141     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
5142     ASSERT_NE(-1, samplerMemberLoc);
5143     glUniform1i(samplerMemberLoc, 0);
5144     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5145     ASSERT_NE(-1, texCoordLoc);
5146     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5147 
5148     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5149     ASSERT_GL_NO_ERROR();
5150 
5151     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5152 }
5153 
5154 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)5155 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
5156 {
5157     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
5158     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
5159 
5160     const char kFragmentShader[] = R"(precision mediump float;
5161 struct S { sampler2D samplerMember; };
5162 struct T { S nest; };
5163 uniform T uStruct;
5164 uniform vec2 uTexCoord;
5165 vec4 foo2(S structVar)
5166 {
5167     return texture2D(structVar.samplerMember, uTexCoord);
5168 }
5169 vec4 foo(T structVar)
5170 {
5171     return foo2(structVar.nest);
5172 }
5173 void main()
5174 {
5175     gl_FragColor = foo(uStruct);
5176 })";
5177 
5178     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5179 
5180     // Initialize the texture with green.
5181     GLTexture tex;
5182     glActiveTexture(GL_TEXTURE0);
5183     glBindTexture(GL_TEXTURE_2D, tex);
5184     GLubyte texData[] = {0u, 255u, 0u, 255u};
5185     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5186     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5187     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5188     ASSERT_GL_NO_ERROR();
5189 
5190     // Draw
5191     glUseProgram(program);
5192     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
5193     ASSERT_NE(-1, samplerMemberLoc);
5194     glUniform1i(samplerMemberLoc, 0);
5195     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5196     ASSERT_NE(-1, texCoordLoc);
5197     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5198 
5199     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5200     ASSERT_GL_NO_ERROR();
5201 
5202     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5203 }
5204 
5205 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)5206 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
5207 {
5208     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
5209     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
5210 
5211     const char kFragmentShader[] = R"(precision mediump float;
5212 struct S { sampler2D samplerMember; bool b; };
5213 uniform S uStruct;
5214 uniform vec2 uTexCoord;
5215 vec4 foo(S structVar)
5216 {
5217     if (structVar.b)
5218         return texture2D(structVar.samplerMember, uTexCoord);
5219     else
5220         return vec4(1, 0, 0, 1);
5221 }
5222 void main()
5223 {
5224     gl_FragColor = foo(uStruct);
5225 })";
5226 
5227     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5228 
5229     // Initialize the texture with green.
5230     GLTexture tex;
5231     glActiveTexture(GL_TEXTURE0);
5232     glBindTexture(GL_TEXTURE_2D, tex);
5233     GLubyte texData[] = {0u, 255u, 0u, 255u};
5234     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5235     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5236     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5237     ASSERT_GL_NO_ERROR();
5238 
5239     // Draw
5240     glUseProgram(program);
5241     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
5242     ASSERT_NE(-1, samplerMemberLoc);
5243     glUniform1i(samplerMemberLoc, 0);
5244     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5245     ASSERT_NE(-1, texCoordLoc);
5246     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5247     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
5248     ASSERT_NE(-1, bLoc);
5249     glUniform1i(bLoc, 1);
5250 
5251     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5252     ASSERT_GL_NO_ERROR();
5253 
5254     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5255 }
5256 
5257 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)5258 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
5259 {
5260     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
5261     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
5262 
5263     const char kFragmentShader[] = R"(precision mediump float;
5264 struct S { sampler2D samplerMember; bool b; };
5265 struct T { S nest; bool b; };
5266 uniform T uStruct;
5267 uniform vec2 uTexCoord;
5268 vec4 foo2(S structVar)
5269 {
5270     if (structVar.b)
5271         return texture2D(structVar.samplerMember, uTexCoord);
5272     else
5273         return vec4(1, 0, 0, 1);
5274 }
5275 vec4 foo(T structVar)
5276 {
5277     if (structVar.b)
5278         return foo2(structVar.nest);
5279     else
5280         return vec4(1, 0, 0, 1);
5281 }
5282 void main()
5283 {
5284     gl_FragColor = foo(uStruct);
5285 })";
5286 
5287     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5288 
5289     // Initialize the texture with green.
5290     GLTexture tex;
5291     glActiveTexture(GL_TEXTURE0);
5292     glBindTexture(GL_TEXTURE_2D, tex);
5293     GLubyte texData[] = {0u, 255u, 0u, 255u};
5294     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5295     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5296     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5297     ASSERT_GL_NO_ERROR();
5298 
5299     // Draw
5300     glUseProgram(program);
5301     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
5302     ASSERT_NE(-1, samplerMemberLoc);
5303     glUniform1i(samplerMemberLoc, 0);
5304     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5305     ASSERT_NE(-1, texCoordLoc);
5306     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5307 
5308     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
5309     ASSERT_NE(-1, bLoc);
5310     glUniform1i(bLoc, 1);
5311 
5312     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
5313     ASSERT_NE(-1, nestbLoc);
5314     glUniform1i(nestbLoc, 1);
5315 
5316     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5317     ASSERT_GL_NO_ERROR();
5318 
5319     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5320 }
5321 
5322 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)5323 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
5324 {
5325     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
5326     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsAdreno() && IsOpenGLES());
5327 
5328     const char kFragmentShader[] = R"(precision mediump float;
5329 struct S { bool b; sampler2D samplerMember; };
5330 struct T { bool b; S nest; };
5331 uniform T uStruct;
5332 uniform vec2 uTexCoord;
5333 vec4 foo2(S structVar)
5334 {
5335     if (structVar.b)
5336         return texture2D(structVar.samplerMember, uTexCoord);
5337     else
5338         return vec4(1, 0, 0, 1);
5339 }
5340 vec4 foo(T structVar)
5341 {
5342     if (structVar.b)
5343         return foo2(structVar.nest);
5344     else
5345         return vec4(1, 0, 0, 1);
5346 }
5347 void main()
5348 {
5349     gl_FragColor = foo(uStruct);
5350 })";
5351 
5352     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5353 
5354     // Initialize the texture with green.
5355     GLTexture tex;
5356     glActiveTexture(GL_TEXTURE0);
5357     glBindTexture(GL_TEXTURE_2D, tex);
5358     GLubyte texData[] = {0u, 255u, 0u, 255u};
5359     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
5360     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5361     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5362     ASSERT_GL_NO_ERROR();
5363 
5364     // Draw
5365     glUseProgram(program);
5366     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
5367     ASSERT_NE(-1, samplerMemberLoc);
5368     glUniform1i(samplerMemberLoc, 0);
5369     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
5370     ASSERT_NE(-1, texCoordLoc);
5371     glUniform2f(texCoordLoc, 0.5f, 0.5f);
5372 
5373     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
5374     ASSERT_NE(-1, bLoc);
5375     glUniform1i(bLoc, 1);
5376 
5377     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
5378     ASSERT_NE(-1, nestbLoc);
5379     glUniform1i(nestbLoc, 1);
5380 
5381     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5382     ASSERT_GL_NO_ERROR();
5383 
5384     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
5385 }
5386 // Test that a global variable declared after main() works. This is a regression test for an issue
5387 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)5388 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
5389 {
5390     constexpr char kFS[] =
5391         "precision mediump float;\n"
5392         "int getFoo();\n"
5393         "uniform int u_zero;\n"
5394         "void main()\n"
5395         "{\n"
5396         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
5397         "    if (getFoo() == 0)\n"
5398         "    {\n"
5399         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
5400         "    }\n"
5401         "}\n"
5402         "int foo;\n"
5403         "int getFoo()\n"
5404         "{\n"
5405         "    foo = u_zero;\n"
5406         "    return foo;\n"
5407         "}\n";
5408 
5409     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5410     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5411     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5412 }
5413 
5414 // Test calling array length() with a "this" expression having side effects inside a loop condition.
5415 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)5416 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
5417 {
5418     // "a" gets doubled three times in the below program.
5419     constexpr char kFS[] = R"(#version 300 es
5420 precision highp float;
5421 out vec4 my_FragColor;
5422 uniform int u_zero;
5423 int a;
5424 int[2] doubleA()
5425 {
5426     a *= 2;
5427     return int[2](a, a);
5428 }
5429 void main()
5430 {
5431     a = u_zero + 1;
5432     for (int i = 0; i < doubleA().length(); ++i)
5433     {}
5434     if (a == 8)
5435     {
5436         my_FragColor = vec4(0, 1, 0, 1);
5437     }
5438     else
5439     {
5440         my_FragColor = vec4(1, 0, 0, 1);
5441     }
5442 })";
5443 
5444     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5445     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5446     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5447 }
5448 
5449 // Test calling array length() with a "this" expression having side effects that interact with side
5450 // effects of another operand of the same sequence operator. The spec says that sequence operator
5451 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)5452 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
5453 {
5454     constexpr char kFS[] = R"(#version 300 es
5455 precision highp float;
5456 out vec4 my_FragColor;
5457 uniform int u_zero;
5458 int a;
5459 int[3] doubleA()
5460 {
5461     a *= 2;
5462     return int[3](a, a, a);
5463 }
5464 void main()
5465 {
5466     a = u_zero;
5467     int b = (a++, doubleA().length());
5468     if (b == 3 && a == 2)
5469     {
5470         my_FragColor = vec4(0, 1, 0, 1);
5471     }
5472     else
5473     {
5474         my_FragColor = vec4(1, 0, 0, 1);
5475     }
5476 })";
5477 
5478     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5479     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5480     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5481 }
5482 
5483 // Test calling array length() with a "this" expression that also contains a call of array length().
5484 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)5485 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
5486 {
5487     constexpr char kFS[] = R"(#version 300 es
5488 precision highp float;
5489 out vec4 my_FragColor;
5490 uniform int u_zero;
5491 int a;
5492 int[3] multiplyA(int multiplier)
5493 {
5494     a *= multiplier;
5495     return int[3](a, a, a);
5496 }
5497 void main()
5498 {
5499     a = u_zero + 1;
5500     int b = multiplyA(multiplyA(2).length()).length();
5501     if (b == 3 && a == 6)
5502     {
5503         my_FragColor = vec4(0, 1, 0, 1);
5504     }
5505     else
5506     {
5507         my_FragColor = vec4(1, 0, 0, 1);
5508     }
5509 })";
5510 
5511     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5512     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5513     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5514 }
5515 
5516 // Test calling array length() with a "this" expression having side effects inside an if condition.
5517 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)5518 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
5519 {
5520     // Bug in the shader translator.  http://anglebug.com/3829
5521     ANGLE_SKIP_TEST_IF(true);
5522 
5523     // "a" shouldn't get modified by this shader.
5524     constexpr char kFS[] = R"(#version 300 es
5525 precision highp float;
5526 out vec4 my_FragColor;
5527 uniform int u_zero;
5528 int a;
5529 int[2] doubleA()
5530 {
5531     a *= 2;
5532     return int[2](a, a);
5533 }
5534 void main()
5535 {
5536     a = u_zero + 1;
5537     if (u_zero != 0 && doubleA().length() == 2)
5538     {
5539         ++a;
5540     }
5541     if (a == 1)
5542     {
5543         my_FragColor = vec4(0, 1, 0, 1);
5544     }
5545     else
5546     {
5547         my_FragColor = vec4(1, 0, 0, 1);
5548     }
5549 })";
5550 
5551     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5552     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5553     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5554 }
5555 
5556 // Test calling array length() with a "this" expression having side effects in a statement where the
5557 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)5558 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
5559 {
5560     // Bug in the shader translator.  http://anglebug.com/3829
5561     ANGLE_SKIP_TEST_IF(true);
5562 
5563     // "a" shouldn't get modified by this shader.
5564     constexpr char kFS[] = R"(#version 300 es
5565 precision highp float;
5566 out vec4 my_FragColor;
5567 uniform int u_zero;
5568 int a;
5569 int[2] doubleA()
5570 {
5571     a *= 2;
5572     return int[2](a, a);
5573 }
5574 void main()
5575 {
5576     a = u_zero + 1;
5577     bool test = u_zero != 0 && doubleA().length() == 2;
5578     if (a == 1)
5579     {
5580         my_FragColor = vec4(0, 1, 0, 1);
5581     }
5582     else
5583     {
5584         my_FragColor = vec4(1, 0, 0, 1);
5585     }
5586 })";
5587 
5588     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5589     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5590     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5591 }
5592 
5593 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)5594 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
5595 {
5596     constexpr char kFS[] = R"(#version 300 es
5597 precision highp float;
5598 uniform int u;
5599 void main()
5600 {
5601     switch (u)
5602     {
5603         case 0:
5604             ivec2 i;
5605             i.yx;
5606     }
5607 })";
5608 
5609     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5610 }
5611 
5612 // Test that switch fall-through works correctly.
5613 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)5614 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
5615 {
5616     constexpr char kFS[] = R"(#version 300 es
5617 precision highp float;
5618 out vec4 my_FragColor;
5619 uniform int u_zero;
5620 
5621 void main()
5622 {
5623     int i = 0;
5624     // switch should fall through both cases.
5625     switch(u_zero)
5626     {
5627         case 0:
5628             i += 1;
5629         case 1:
5630             i += 2;
5631     }
5632     if (i == 3)
5633     {
5634         my_FragColor = vec4(0, 1, 0, 1);
5635     }
5636     else
5637     {
5638         my_FragColor = vec4(1, 0, 0, 1);
5639     }
5640 })";
5641 
5642     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5643     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5644     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5645 }
5646 
5647 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)5648 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
5649 {
5650     constexpr char kFS[] = R"(#version 300 es
5651 
5652 precision mediump float;
5653 uniform int i;
5654 void main()
5655 {
5656     switch (i)
5657     {
5658         case 0:
5659             break;
5660         default:
5661             {}
5662     }
5663 })";
5664     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5665 }
5666 
5667 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)5668 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
5669 {
5670     constexpr char kFS[] = R"(#version 300 es
5671 
5672 precision mediump float;
5673 uniform int i;
5674 void main()
5675 {
5676     switch (i)
5677     {
5678         case 0:
5679             break;
5680         default:
5681             float;
5682     }
5683 })";
5684     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5685 }
5686 
5687 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)5688 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
5689 {
5690     constexpr char kFS[] = R"(#version 300 es
5691 
5692 precision highp float;
5693 
5694 uniform int u_zero;
5695 out vec4 my_FragColor;
5696 
5697 bool test(int n)
5698 {
5699     switch(n) {
5700         case 0:
5701         {
5702             {
5703                 break;
5704             }
5705         }
5706         case 1:
5707         {
5708             return true;
5709         }
5710         case 2:
5711         {
5712             n++;
5713         }
5714     }
5715     return false;
5716 }
5717 
5718 void main()
5719 {
5720     my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
5721 })";
5722 
5723     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5724     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5725     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5726 }
5727 
5728 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
5729 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)5730 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
5731 {
5732     constexpr char kFS[] = R"(#version 300 es
5733 
5734 precision highp float;
5735 out vec4 my_FragColor;
5736 
5737 uniform int u_zero;
5738 
5739 void main()
5740 {
5741     my_FragColor = vec4(1, 0, 0, 1);
5742     switch (u_zero)
5743     {
5744         case 0:
5745             ivec2 i;
5746             i = ivec2(1, 0);
5747         default:
5748             my_FragColor = vec4(0, i[0], 0, 1);
5749     }
5750 })";
5751 
5752     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5753     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5754     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5755 }
5756 
5757 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
5758 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)5759 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
5760 {
5761     constexpr char kFS[] = R"(#version 300 es
5762 
5763 precision highp float;
5764 out vec4 my_FragColor;
5765 
5766 uniform int u_zero;
5767 uniform int u_zero2;
5768 
5769 void main()
5770 {
5771     my_FragColor = vec4(1, 0, 0, 1);
5772     switch (u_zero)
5773     {
5774         case 0:
5775             ivec2 i;
5776             i = ivec2(1, 0);
5777             switch (u_zero2)
5778             {
5779                 case 0:
5780                     int j;
5781                 default:
5782                     j = 1;
5783                     i *= j;
5784             }
5785         default:
5786             my_FragColor = vec4(0, i[0], 0, 1);
5787     }
5788 })";
5789 
5790     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5791     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5792     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5793 }
5794 
5795 // Test that an empty switch/case statement is translated in a way that compiles and executes the
5796 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)5797 TEST_P(GLSLTest_ES3, EmptySwitch)
5798 {
5799     constexpr char kFS[] = R"(#version 300 es
5800 
5801 precision highp float;
5802 
5803 uniform int u_zero;
5804 out vec4 my_FragColor;
5805 
5806 void main()
5807 {
5808     int i = u_zero;
5809     switch(++i) {}
5810     my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
5811 })";
5812 
5813     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5814     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5815     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5816 }
5817 
5818 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)5819 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
5820 {
5821     // Incorrect output color was seen on Android. http://anglebug.com/2226
5822     ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
5823 
5824     constexpr char kFS[] = R"(#version 300 es
5825 
5826 precision highp float;
5827 out vec4 my_FragColor;
5828 
5829 uniform float u_zero;
5830 
5831 struct S
5832 {
5833     float field;
5834 };
5835 
5836 void main()
5837 {
5838     const S constS = S(1.0);
5839     S nonConstS = constS;
5840     nonConstS.field = u_zero;
5841     bool fail = (constS == nonConstS);
5842     my_FragColor = vec4(0, 1, 0, 1);
5843     if (fail)
5844     {
5845         my_FragColor = vec4(1, 0, 0, 1);
5846     }
5847 })";
5848 
5849     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5850     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5851     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5852 }
5853 
5854 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)5855 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
5856 {
5857     constexpr char kVS[] = R"(#version 300 es
5858 in vec4 inputAttribute;
5859 
5860 flat out struct S
5861 {
5862     int field;
5863 } v_s;
5864 
5865 void main()
5866 {
5867     v_s.field = 1;
5868     gl_Position = inputAttribute;
5869 })";
5870 
5871     constexpr char kFS[] = R"(#version 300 es
5872 
5873 precision highp float;
5874 out vec4 my_FragColor;
5875 
5876 flat in struct S
5877 {
5878     int field;
5879 } v_s;
5880 
5881 void main()
5882 {
5883     bool success = (v_s.field == 1);
5884     my_FragColor = vec4(1, 0, 0, 1);
5885     if (success)
5886     {
5887         my_FragColor = vec4(0, 1, 0, 1);
5888     }
5889 })";
5890 
5891     ANGLE_GL_PROGRAM(program, kVS, kFS);
5892     drawQuad(program.get(), "inputAttribute", 0.5f);
5893     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5894 }
5895 
5896 // Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
5897 // bug that appeared in NVIDIA OpenGL drivers and that is worked around by
5898 // VectorizeVectorScalarArithmetic AST transform.
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)5899 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
5900 {
5901     constexpr char kFS[] = R"(precision mediump float;
5902 
5903 void main() {
5904     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
5905     for (int i = 0; i < 2; i++)
5906     {
5907         gl_FragColor += (2.0 * gl_FragCoord.x);
5908     }
5909     if (gl_FragColor.g == gl_FragColor.r &&
5910         gl_FragColor.b == gl_FragColor.r &&
5911         gl_FragColor.a == gl_FragColor.r)
5912     {
5913         gl_FragColor = vec4(0, 1, 0, 1);
5914     }
5915 })";
5916 
5917     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5918     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
5919     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5920 }
5921 
5922 // Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
5923 // bug that appeared in NVIDIA OpenGL drivers and that is worked around by
5924 // VectorizeVectorScalarArithmetic AST transform.
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)5925 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
5926 {
5927     constexpr char kFS[] = R"(precision mediump float;
5928 
5929 void main() {
5930     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
5931     for (int i = 0; i < 2; i++)
5932     {
5933         float x = gl_FragCoord.x;
5934         gl_FragColor = gl_FragColor + (x /= 2.0);
5935     }
5936     if (gl_FragColor.g == gl_FragColor.r &&
5937         gl_FragColor.b == gl_FragColor.r &&
5938         gl_FragColor.a == gl_FragColor.r)
5939     {
5940         gl_FragColor = vec4(0, 1, 0, 1);
5941     }
5942 })";
5943 
5944     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5945     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
5946     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5947 }
5948 
5949 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
5950 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)5951 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
5952 {
5953     constexpr char kVS[] = R"(#version 300 es
5954 
5955 in vec4 inputAttribute;
5956 
5957 flat out int v;
5958 
5959 void main()
5960 {
5961     v = 1;
5962     gl_Position = inputAttribute;
5963 })";
5964 
5965     constexpr char kFS[] = R"(#version 300 es
5966 
5967 precision highp float;
5968 out vec4 my_FragColor;
5969 
5970 flat in int v;
5971 
5972 void main()
5973 {
5974     my_FragColor = vec4(0, (true ? v : 0), 0, 1);
5975 })";
5976 
5977     ANGLE_GL_PROGRAM(program, kVS, kFS);
5978     drawQuad(program.get(), "inputAttribute", 0.5f);
5979     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5980 }
5981 
5982 // Verify that the link error message from last link failure is cleared when the new link is
5983 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)5984 TEST_P(GLSLTest, ClearLinkErrorLog)
5985 {
5986     constexpr char kVS[] = R"(attribute vec4 vert_in;
5987 varying vec4 vert_out;
5988 void main()
5989 {
5990     gl_Position = vert_in;
5991     vert_out = vert_in;
5992 })";
5993 
5994     constexpr char kFS[] = R"(precision mediump float;
5995 varying vec4 frag_in;
5996 void main()
5997 {
5998     gl_FragColor = frag_in;
5999 })";
6000 
6001     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
6002     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6003 
6004     GLuint program = glCreateProgram();
6005 
6006     // The first time the program link fails because of lack of fragment shader.
6007     glAttachShader(program, vs);
6008     glLinkProgram(program);
6009     GLint linkStatus = GL_TRUE;
6010     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
6011     ASSERT_FALSE(linkStatus);
6012 
6013     const std::string &lackOfFragmentShader = QueryErrorMessage(program);
6014 
6015     // The second time the program link fails because of the mismatch of the varying types.
6016     glAttachShader(program, fs);
6017     glLinkProgram(program);
6018     linkStatus = GL_TRUE;
6019     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
6020     ASSERT_FALSE(linkStatus);
6021 
6022     const std::string &varyingTypeMismatch = QueryErrorMessage(program);
6023 
6024     EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
6025 
6026     glDetachShader(program, vs);
6027     glDetachShader(program, fs);
6028     glDeleteShader(vs);
6029     glDeleteShader(fs);
6030     glDeleteProgram(program);
6031 
6032     ASSERT_GL_NO_ERROR();
6033 }
6034 
6035 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)6036 TEST_P(GLSLTest, DrawAfterShaderLinkError)
6037 {
6038     constexpr char kVS[]    = R"(attribute vec4 position;
6039         varying vec4 vColor;
6040         void main()
6041         {
6042             vColor = vec4(0.0, 1.0, 0.0, 1.0);
6043             gl_Position = position;
6044         })";
6045     constexpr char kFS[]    = R"(precision mediump float;
6046         varying vec4 vColor;
6047         void main()
6048         {
6049             gl_FragColor = vColor;
6050         })";
6051     constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
6052 
6053     GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
6054 
6055     // Create bad fragment shader
6056     {
6057         const char *sourceArray[1] = {kBadFS};
6058         glShaderSource(fsBad, 1, sourceArray, nullptr);
6059         glCompileShader(fsBad);
6060 
6061         GLint compileResult;
6062         glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
6063         ASSERT_FALSE(compileResult);
6064     }
6065 
6066     ANGLE_GL_PROGRAM(program, kVS, kFS);
6067     GLuint fs = GetProgramShader(program.get(), GL_FRAGMENT_SHADER);
6068 
6069     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6070     glClear(GL_COLOR_BUFFER_BIT);
6071     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6072 
6073     glUseProgram(program.get());
6074     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
6075     std::array<Vector3, 6> quadVertices = GetQuadVertices();
6076     for (Vector3 &vertex : quadVertices)
6077     {
6078         vertex.z() = 0.5f;
6079     }
6080     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
6081     glEnableVertexAttribArray(positionLocation);
6082     glDrawArrays(GL_TRIANGLES, 0, 6);
6083     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6084 
6085     glDetachShader(program.get(), fs);
6086     glAttachShader(program.get(), fsBad);
6087     glLinkProgram(program.get());
6088     GLint linkStatus = GL_TRUE;
6089     glGetProgramiv(program.get(), GL_LINK_STATUS, &linkStatus);
6090     ASSERT_FALSE(linkStatus);
6091 
6092     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6093     glClear(GL_COLOR_BUFFER_BIT);
6094     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6095 
6096     glDrawArrays(GL_TRIANGLES, 0, 6);
6097     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6098 }
6099 
6100 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)6101 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
6102 {
6103     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
6104 varying vec4 vertex_out;
6105 void main()
6106 {
6107     vertex_out = inputAttribute;
6108     gl_Position = inputAttribute;
6109 })";
6110 
6111     constexpr char kFS[] = R"(precision mediump float;
6112 varying float vertex_out;
6113 void main()
6114 {
6115     gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
6116 })";
6117 
6118     validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
6119 }
6120 
6121 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)6122 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
6123 {
6124     constexpr char kVS[] = R"(#version 300 es
6125 in vec4 inputAttribute;
6126 struct S {
6127     float val1;
6128     vec4 val2;
6129 };
6130 out S vertex_out;
6131 void main()
6132 {
6133     vertex_out.val2 = inputAttribute;
6134     vertex_out.val1 = inputAttribute[0];
6135     gl_Position = inputAttribute;
6136 })";
6137 
6138     constexpr char kFS[] = R"(#version 300 es
6139 precision mediump float;
6140 struct S {
6141     float val1;
6142     vec4 val3;
6143 };
6144 in S vertex_out;
6145 layout (location = 0) out vec4 frag_out;
6146 void main()
6147 {
6148     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
6149 })";
6150 
6151     validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
6152 }
6153 
6154 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)6155 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
6156 {
6157     constexpr char kVS[] = R"(#version 300 es
6158 in vec4 inputAttribute;
6159 struct S {
6160     float val1;
6161     vec4 val2;
6162 };
6163 out S vertex_out;
6164 void main()
6165 {
6166     vertex_out.val2 = inputAttribute;
6167     vertex_out.val1 = inputAttribute[0];
6168     gl_Position = inputAttribute;
6169 })";
6170 
6171     constexpr char kFS[] = R"(#version 300 es
6172 precision mediump float;
6173 struct S {
6174     float val1;
6175     vec2 val2;
6176 };
6177 in S vertex_out;
6178 layout (location = 0) out vec4 frag_out;
6179 void main()
6180 {
6181     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
6182 })";
6183 
6184     validateComponentsInErrorMessage(kVS, kFS, "Types",
6185                                      "varying 'vertex_out' member 'vertex_out.val2'");
6186 }
6187 
6188 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
6189 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)6190 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
6191 {
6192     constexpr char kVS[] = R"(
6193 struct T
6194 {
6195     vec2 t1;
6196     vec3 t2;
6197 };
6198 struct S {
6199     T val1;
6200     vec4 val2;
6201 };
6202 uniform S uni;
6203 
6204 attribute vec4 inputAttribute;
6205 varying vec4 vertex_out;
6206 void main()
6207 {
6208     vertex_out = uni.val2;
6209     gl_Position = inputAttribute;
6210 })";
6211 
6212     constexpr char kFS[] = R"(precision highp float;
6213 struct T
6214 {
6215     vec2 t1;
6216     vec3 t3;
6217 };
6218 struct S {
6219     T val1;
6220     vec4 val2;
6221 };
6222 uniform S uni;
6223 
6224 varying vec4 vertex_out;
6225 void main()
6226 {
6227     gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
6228 })";
6229 
6230     validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
6231 }
6232 
6233 // Validate error messages  when the link mismatch occurs on the type of a non-struct uniform block
6234 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)6235 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
6236 {
6237     constexpr char kVS[] = R"(#version 300 es
6238 uniform S {
6239     vec2 val1;
6240     vec4 val2;
6241 } uni;
6242 
6243 in vec4 inputAttribute;
6244 out vec4 vertex_out;
6245 void main()
6246 {
6247     vertex_out = uni.val2;
6248     gl_Position = inputAttribute;
6249 })";
6250 
6251     constexpr char kFS[] = R"(#version 300 es
6252 precision highp float;
6253 uniform S {
6254     vec2 val1;
6255     vec3 val2;
6256 } uni;
6257 
6258 in vec4 vertex_out;
6259 layout (location = 0) out vec4 frag_out;
6260 void main()
6261 {
6262     frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
6263 })";
6264 
6265     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
6266 }
6267 
6268 // Validate error messages  when the link mismatch occurs on the type of a member of a uniform block
6269 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)6270 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
6271 {
6272     constexpr char kVS[] = R"(#version 300 es
6273 struct T
6274 {
6275     vec2 t1;
6276     vec3 t2;
6277 };
6278 uniform S {
6279     T val1;
6280     vec4 val2;
6281 } uni;
6282 
6283 in vec4 inputAttribute;
6284 out vec4 vertex_out;
6285 void main()
6286 {
6287     vertex_out = uni.val2;
6288     gl_Position = inputAttribute;
6289 })";
6290 
6291     constexpr char kFS[] = R"(#version 300 es
6292 precision highp float;
6293 struct T
6294 {
6295     vec2 t1;
6296     vec4 t2;
6297 };
6298 uniform S {
6299     T val1;
6300     vec4 val2;
6301 } uni;
6302 
6303 in vec4 vertex_out;
6304 layout (location = 0) out vec4 frag_out;
6305 void main()
6306 {
6307     frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
6308 })";
6309 
6310     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
6311 }
6312 
6313 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
6314 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)6315 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
6316 {
6317     constexpr char kVS[] = R"(#version 300 es
6318 precision mediump float;
6319 
6320 void main()
6321 {
6322     gl_Position = vec4(0, 1, 0, 1);
6323 })";
6324 
6325     constexpr char kFS[] = R"(#version 300 es
6326 precision mediump float;
6327 in float foo;
6328 out vec4 my_FragColor;
6329 
6330 void main()
6331 {
6332     if (false)
6333     {
6334         float unreferenced = foo;
6335     }
6336     my_FragColor = vec4(0, 1, 0, 1);
6337 })";
6338 
6339     validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
6340 }
6341 
6342 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)6343 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
6344 {
6345     constexpr char kVS[] = R"(#version 300 es
6346 precision mediump float;
6347 in vec4 iv;
6348 out vec4 v;
6349 void main()
6350 {
6351     gl_Position = iv;
6352     v = iv;
6353 })";
6354 
6355     constexpr char kFS[] = R"(#version 300 es
6356 precision mediump float;
6357 in vec4 v;
6358 out vec4 color;
6359 void main()
6360 {
6361     color = true ? vec4(0.0) : v;
6362 })";
6363 
6364     ANGLE_GL_PROGRAM(program, kVS, kFS);
6365 }
6366 
6367 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)6368 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
6369 {
6370     constexpr char kVS[] = R"(#version 310 es
6371 precision highp float;
6372 in vec4 position;
6373 layout(location = 1) out vec4 shaderOutput;
6374 void main() {
6375     gl_Position = position;
6376     shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
6377 })";
6378 
6379     constexpr char kFS[] = R"(#version 310 es
6380 precision highp float;
6381 layout(location = 1) in vec4 shaderInput;
6382 out vec4 outColor;
6383 void main() {
6384     outColor = shaderInput;
6385 })";
6386 
6387     ANGLE_GL_PROGRAM(program, kVS, kFS);
6388     drawQuad(program, "position", 0.5f);
6389     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6390 }
6391 
6392 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)6393 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
6394 {
6395     // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
6396     // up red. http://crbug.com/838885
6397     ANGLE_SKIP_TEST_IF(IsD3D11());
6398 
6399     constexpr char kFS[] = R"(#version 300 es
6400 precision highp float;
6401 out vec4 my_FragColor;
6402 void main()
6403 {
6404     vec2 coord = gl_FragCoord.xy / 500.0;
6405     my_FragColor = vec4(1, 0, 0, 1);
6406     if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
6407     {
6408         my_FragColor = vec4(0, 1, 0, 1);
6409     }
6410 })";
6411 
6412     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6413     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6414     // Verify that all the corners of the rendered result are green.
6415     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6416     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
6417     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
6418     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
6419 }
6420 
6421 // Verify that a link error is generated when the sum of the number of active image uniforms and
6422 // active shader storage blocks in a rendering pipeline exceeds
6423 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)6424 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
6425 {
6426     // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
6427     // D3D11 back-ends.
6428     ANGLE_SKIP_TEST_IF(IsD3D11());
6429 
6430     GLint maxVertexShaderStorageBlocks;
6431     GLint maxVertexImageUniforms;
6432     GLint maxFragmentShaderStorageBlocks;
6433     GLint maxFragmentImageUniforms;
6434     GLint maxCombinedShaderStorageBlocks;
6435     GLint maxCombinedImageUniforms;
6436     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
6437     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
6438     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
6439     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
6440     glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
6441     glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
6442 
6443     ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
6444     ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
6445     ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
6446     ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
6447 
6448     GLint vertexSSBOs   = maxVertexShaderStorageBlocks;
6449     GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
6450     // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
6451     if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
6452     {
6453         fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
6454     }
6455 
6456     GLint vertexImages   = maxVertexImageUniforms;
6457     GLint fragmentImages = maxFragmentImageUniforms;
6458     // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
6459     if (vertexImages + fragmentImages > maxCombinedImageUniforms)
6460     {
6461         vertexImages = maxCombinedImageUniforms - fragmentImages;
6462     }
6463 
6464     GLint maxDrawBuffers;
6465     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
6466 
6467     GLint maxCombinedShaderOutputResources;
6468     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
6469     ASSERT_GL_NO_ERROR();
6470 
6471     ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
6472                            maxDrawBuffers <=
6473                        maxCombinedShaderOutputResources);
6474 
6475     std::ostringstream vertexStream;
6476     vertexStream << "#version 310 es\n";
6477     for (int i = 0; i < vertexSSBOs; ++i)
6478     {
6479         vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
6480                      << "{\n"
6481                         "    float data;\n"
6482                         "} ssbo"
6483                      << i << ";\n";
6484     }
6485     vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
6486                  << "];\n";
6487     vertexStream << "void main()\n"
6488                     "{\n"
6489                     "    float val = 0.1;\n"
6490                     "    vec4 val2 = vec4(0.0);\n";
6491     for (int i = 0; i < vertexSSBOs; ++i)
6492     {
6493         vertexStream << "    val += ssbo" << i << ".data; \n";
6494     }
6495     for (int i = 0; i < vertexImages; ++i)
6496     {
6497         vertexStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
6498     }
6499     vertexStream << "    gl_Position = vec4(val, val2);\n"
6500                     "}\n";
6501 
6502     std::ostringstream fragmentStream;
6503     fragmentStream << "#version 310 es\n"
6504                    << "precision highp float;\n";
6505     for (int i = 0; i < fragmentSSBOs; ++i)
6506     {
6507         fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
6508                        << "{\n"
6509                           "    float data;\n"
6510                           "} ssbo"
6511                        << i << ";\n";
6512     }
6513     fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
6514                    << fragmentImages << "];\n";
6515     fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
6516 
6517     fragmentStream << "void main()\n"
6518                       "{\n"
6519                       "    float val = 0.1;\n"
6520                       "    vec4 val2 = vec4(0.0);\n";
6521     for (int i = 0; i < fragmentSSBOs; ++i)
6522     {
6523         fragmentStream << "    val += ssbo" << i << ".data; \n";
6524     }
6525     for (int i = 0; i < fragmentImages; ++i)
6526     {
6527         fragmentStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
6528     }
6529     for (int i = 0; i < maxDrawBuffers; ++i)
6530     {
6531         fragmentStream << "    foutput[" << i << "] = vec4(val, val2);\n";
6532     }
6533     fragmentStream << "}\n";
6534 
6535     GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
6536     EXPECT_EQ(0u, program);
6537 
6538     ASSERT_GL_NO_ERROR();
6539 }
6540 
6541 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
6542 // function works correctly.
TEST_P(GLSLTest_ES3,AssignAssignmentToSwizzled)6543 TEST_P(GLSLTest_ES3, AssignAssignmentToSwizzled)
6544 {
6545     constexpr char kFS[] = R"(#version 300 es
6546 precision highp float;
6547 out vec4 my_FragColor;
6548 
6549 uniform float uzero;
6550 
6551 vec3 fun(float s, float v)
6552 {
6553     vec3 r = vec3(0);
6554     if (s < 1.0) {
6555         r.x = r.y = r.z = v;
6556         return r;
6557     }
6558     return r;
6559 }
6560 
6561 void main()
6562 {
6563     my_FragColor.a = 1.0;
6564     my_FragColor.rgb = fun(uzero, 1.0);
6565 })";
6566 
6567     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6568     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6569     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
6570 }
6571 
6572 // Test a fragment shader that returns inside if (that being the only branch that actually gets
6573 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)6574 TEST_P(GLSLTest, IfElseIfAndReturn)
6575 {
6576     constexpr char kVS[] = R"(attribute vec4 a_position;
6577 varying vec2 vPos;
6578 void main()
6579 {
6580     gl_Position = a_position;
6581     vPos = a_position.xy;
6582 })";
6583 
6584     constexpr char kFS[] = R"(precision mediump float;
6585 varying vec2 vPos;
6586 void main()
6587 {
6588     if (vPos.x < 1.0) // This colors the whole canvas green
6589     {
6590         gl_FragColor = vec4(0, 1, 0, 1);
6591         return;
6592     }
6593     else if (vPos.x < 1.1) // This should have no effect
6594     {
6595         gl_FragColor = vec4(1, 0, 0, 1);
6596     }
6597 })";
6598 
6599     ANGLE_GL_PROGRAM(program, kVS, kFS);
6600     drawQuad(program.get(), "a_position", 0.5f);
6601     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6602 }
6603 
6604 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)6605 TEST_P(GLSLTest, PointCoordConsistency)
6606 {
6607     // On Intel Windows OpenGL drivers PointCoord appears to be flipped when drawing to the
6608     // default framebuffer. http://anglebug.com/2805
6609     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6610 
6611     // AMD's OpenGL drivers may have the same issue. http://anglebug.com/1643
6612     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
6613     // http://anglebug.com/4092
6614     ANGLE_SKIP_TEST_IF(isSwiftshader());
6615 
6616     constexpr char kPointCoordVS[] = R"(attribute vec2 position;
6617 uniform vec2 viewportSize;
6618 void main()
6619 {
6620    gl_Position = vec4(position, 0, 1);
6621    gl_PointSize = viewportSize.x;
6622 })";
6623 
6624     constexpr char kPointCoordFS[] = R"(void main()
6625 {
6626     gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
6627 })";
6628 
6629     ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
6630     glUseProgram(program);
6631 
6632     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
6633     ASSERT_NE(-1, uniLoc);
6634     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
6635                 static_cast<GLfloat>(getWindowHeight()));
6636 
6637     // Draw to backbuffer.
6638     glClear(GL_COLOR_BUFFER_BIT);
6639     glDrawArrays(GL_POINTS, 0, 1);
6640     ASSERT_GL_NO_ERROR();
6641 
6642     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
6643     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
6644                  backbufferData.data());
6645 
6646     GLTexture tex;
6647     glBindTexture(GL_TEXTURE_2D, tex);
6648     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6649                  GL_UNSIGNED_BYTE, nullptr);
6650 
6651     GLFramebuffer fbo;
6652     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6653     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
6654     ASSERT_GL_NO_ERROR();
6655     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6656 
6657     // Draw to user FBO.
6658     glClear(GL_COLOR_BUFFER_BIT);
6659     glDrawArrays(GL_POINTS, 0, 1);
6660     ASSERT_GL_NO_ERROR();
6661 
6662     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
6663     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
6664                  userFBOData.data());
6665 
6666     ASSERT_GL_NO_ERROR();
6667     ASSERT_EQ(userFBOData.size(), backbufferData.size());
6668     EXPECT_EQ(userFBOData, backbufferData);
6669 }
6670 
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)6671 bool SubrectEquals(const std::vector<GLColor> &bigArray,
6672                    const std::vector<GLColor> &smallArray,
6673                    int bigSize,
6674                    int offset,
6675                    int smallSize)
6676 {
6677     int badPixels = 0;
6678     for (int y = 0; y < smallSize; y++)
6679     {
6680         for (int x = 0; x < smallSize; x++)
6681         {
6682             int bigOffset   = (y + offset) * bigSize + x + offset;
6683             int smallOffset = y * smallSize + x;
6684             if (bigArray[bigOffset] != smallArray[smallOffset])
6685                 badPixels++;
6686         }
6687     }
6688     return badPixels == 0;
6689 }
6690 
6691 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)6692 TEST_P(GLSLTest, FragCoordConsistency)
6693 {
6694     constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
6695 void main()
6696 {
6697     gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
6698 })";
6699 
6700     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
6701     glUseProgram(program);
6702 
6703     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
6704     ASSERT_NE(-1, uniLoc);
6705     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
6706                 static_cast<GLfloat>(getWindowHeight()));
6707 
6708     // Draw to backbuffer.
6709     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
6710     ASSERT_GL_NO_ERROR();
6711 
6712     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
6713     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
6714                  backbufferData.data());
6715 
6716     GLTexture tex;
6717     glBindTexture(GL_TEXTURE_2D, tex);
6718     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6719                  GL_UNSIGNED_BYTE, nullptr);
6720 
6721     GLFramebuffer fbo;
6722     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6723     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
6724     ASSERT_GL_NO_ERROR();
6725     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6726 
6727     // Draw to user FBO.
6728     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
6729     ASSERT_GL_NO_ERROR();
6730 
6731     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
6732     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
6733                  userFBOData.data());
6734 
6735     ASSERT_GL_NO_ERROR();
6736     ASSERT_EQ(userFBOData.size(), backbufferData.size());
6737     EXPECT_EQ(userFBOData, backbufferData)
6738         << "FragCoord should be the same to default and user FBO";
6739 
6740     // Repeat the same test but with a smaller viewport.
6741     ASSERT_EQ(getWindowHeight(), getWindowWidth());
6742     const int kQuarterSize = getWindowWidth() >> 2;
6743     glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
6744 
6745     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6746     glClear(GL_COLOR_BUFFER_BIT);
6747     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
6748 
6749     std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
6750     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
6751                  GL_UNSIGNED_BYTE, userFBOViewportData.data());
6752 
6753     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6754     glClear(GL_COLOR_BUFFER_BIT);
6755     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
6756 
6757     std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
6758     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
6759                  GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
6760     ASSERT_GL_NO_ERROR();
6761     EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
6762         << "FragCoord should be the same to default and user FBO even with a custom viewport";
6763 
6764     // Check that the subrectangles are the same between the viewport and non-viewport modes.
6765     EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
6766                               kQuarterSize * 2));
6767     EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
6768                               kQuarterSize, kQuarterSize * 2));
6769 }
6770 
6771 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)6772 TEST_P(GLSLTest, DefinedInMacroSucceeds)
6773 {
6774     constexpr char kVS[] = R"(precision mediump float;
6775 attribute highp vec4 position;
6776 varying vec2 out0;
6777 
6778 void main()
6779 {
6780 #define AAA defined(BBB)
6781 
6782 #if !AAA
6783     out0 = vec2(0.0, 1.0);
6784 #else
6785     out0 = vec2(1.0, 0.0);
6786 #endif
6787     gl_Position = position;
6788 })";
6789 
6790     constexpr char kFS[] = R"(precision mediump float;
6791 varying vec2 out0;
6792 void main()
6793 {
6794     gl_FragColor = vec4(out0, 0, 1);
6795 })";
6796 
6797     ANGLE_GL_PROGRAM(program, kVS, kFS);
6798     drawQuad(program, "position", 0.5f);
6799     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6800 }
6801 
6802 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)6803 TEST_P(GLSLTest, DefinedInMacroWithUndef)
6804 {
6805     constexpr char kVS[] = R"(precision mediump float;
6806 attribute highp vec4 position;
6807 varying vec2 out0;
6808 
6809 void main()
6810 {
6811 #define BBB 1
6812 #define AAA defined(BBB)
6813 #undef BBB
6814 
6815 #if AAA
6816     out0 = vec2(1.0, 0.0);
6817 #else
6818     out0 = vec2(0.0, 1.0);
6819 #endif
6820     gl_Position = position;
6821 })";
6822 
6823     constexpr char kFS[] = R"(precision mediump float;
6824 varying vec2 out0;
6825 void main()
6826 {
6827     gl_FragColor = vec4(out0, 0, 1);
6828 })";
6829 
6830     ANGLE_GL_PROGRAM(program, kVS, kFS);
6831     drawQuad(program, "position", 0.5f);
6832     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6833 }
6834 
6835 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)6836 TEST_P(GLSLTest, DefinedAfterMacroUsage)
6837 {
6838     constexpr char kVS[] = R"(precision mediump float;
6839 attribute highp vec4 position;
6840 varying vec2 out0;
6841 
6842 void main()
6843 {
6844 #define AAA defined(BBB)
6845 #define BBB 1
6846 
6847 #if AAA
6848     out0 = vec2(0.0, 1.0);
6849 #else
6850     out0 = vec2(1.0, 0.0);
6851 #endif
6852     gl_Position = position;
6853 })";
6854 
6855     constexpr char kFS[] = R"(precision mediump float;
6856 varying vec2 out0;
6857 void main()
6858 {
6859     gl_FragColor = vec4(out0, 0, 1);
6860 })";
6861 
6862     ANGLE_GL_PROGRAM(program, kVS, kFS);
6863     drawQuad(program, "position", 0.5f);
6864     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6865 }
6866 
6867 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)6868 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
6869 {
6870     constexpr char kVS[] = R"(precision mediump float;
6871 attribute highp vec4 position;
6872 varying vec2 out0;
6873 
6874 void main()
6875 {
6876 #define BBB 1
6877 #define AAA(defi, ned) defi ## ned(BBB)
6878 
6879 #if AAA(defi, ned)
6880     out0 = vec2(0.0, 1.0);
6881 #else
6882     out0 = vec2(1.0, 0.0);
6883 #endif
6884     gl_Position = position;
6885 })";
6886 
6887     constexpr char kFS[] = R"(precision mediump float;
6888 varying vec2 out0;
6889 void main()
6890 {
6891     gl_FragColor = vec4(out0, 0, 1);
6892 })";
6893 
6894     GLuint program = CompileProgram(kVS, kFS);
6895     EXPECT_EQ(0u, program);
6896     glDeleteProgram(program);
6897 }
6898 
6899 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)6900 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
6901 {
6902     constexpr char kVS[] = R"(precision mediump float;
6903 attribute highp vec4 position;
6904 varying vec2 out0;
6905 
6906 void main()
6907 {
6908 #define BBB 1
6909 #define AAA(defined) defined(BBB)
6910 
6911 #if AAA(defined)
6912     out0 = vec2(0.0, 1.0);
6913 #else
6914     out0 = vec2(1.0, 0.0);
6915 #endif
6916     gl_Position = position;
6917 })";
6918 
6919     constexpr char kFS[] = R"(precision mediump float;
6920 varying vec2 out0;
6921 void main()
6922 {
6923     gl_FragColor = vec4(out0, 0, 1);
6924 })";
6925 
6926     GLuint program = CompileProgram(kVS, kFS);
6927     EXPECT_EQ(0u, program);
6928     glDeleteProgram(program);
6929 }
6930 
6931 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)6932 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
6933 {
6934     constexpr char kVS[] = R"(precision mediump float;
6935 attribute highp vec4 position;
6936 varying float out0;
6937 
6938 void main()
6939 {
6940 #define AAA defined(BBB)
6941 
6942 #if !AAA
6943     out0 = 1.0;
6944 #else
6945     out0 = 0.0;
6946 #endif
6947     gl_Position = dEQP_Position;
6948 })";
6949 
6950     constexpr char kFS[] = R"(precision mediump float;
6951 varying float out0;
6952 void main()
6953 {
6954     gl_FragColor = vec4(out0, 0, 0, 1);
6955 })";
6956 
6957     GLuint program = CompileProgram(kVS, kFS);
6958     EXPECT_EQ(0u, program);
6959     glDeleteProgram(program);
6960 }
6961 
6962 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)6963 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
6964 {
6965     constexpr char kVS[] = R"(void main()
6966 {
6967     gl_Position = vec4(1, 0, 0, 1);
6968 })";
6969 
6970     constexpr char kFS[] = R"(#if defined(GL_ES)
6971 precision mediump float;
6972 void main()
6973 {
6974     gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
6975 }
6976 #else
6977 foo
6978 #endif
6979 )";
6980 
6981     ANGLE_GL_PROGRAM(program, kVS, kFS);
6982 }
6983 
6984 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)6985 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
6986 {
6987     constexpr char kFS[] = R"(#version 300 es
6988 precision mediump float;
6989 
6990 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
6991 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);
6992 
6993 out vec4 color;
6994 
6995 void main()
6996 {
6997     mat4x2 result = matrixCompMult(matA, matB);
6998     vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
6999     if (vresult == vec2(4.0, 4.0))
7000     {
7001         color = vec4(0.0, 1.0, 0.0, 1.0);
7002     }
7003     else
7004     {
7005         color = vec4(1.0, 0.0, 0.0, 1.0);
7006     }
7007 })";
7008 
7009     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7010     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7011     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7012 }
7013 
7014 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)7015 TEST_P(GLSLTest_ES3, InitSameNameArray)
7016 {
7017     constexpr char kFS[] = R"(#version 300 es
7018       precision highp float;
7019       out vec4 my_FragColor;
7020 
7021       void main()
7022       {
7023           float arr[2] = float[2](1.0, 1.0);
7024           {
7025               float arr[2] = arr;
7026               my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
7027           }
7028       })";
7029 
7030     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7031     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7032     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7033 }
7034 
7035 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)7036 TEST_P(GLSLTest, FragData)
7037 {
7038     // Ensures that we don't regress and emit Vulkan layer warnings.
7039     // TODO(jonahr): http://anglebug.com/3900 - Remove check once warnings are cleaned up
7040     if (IsVulkan())
7041     {
7042         treatPlatformWarningsAsErrors();
7043     }
7044 
7045     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
7046     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7047     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7048     EXPECT_GL_NO_ERROR();
7049     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7050 }
7051 
7052 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)7053 TEST_P(GLSLTest, MemoryExhaustedTest)
7054 {
7055     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
7056     GLuint program =
7057         CompileProgram(essl1_shaders::vs::Simple(), BuillBigInitialStackShader(36).c_str());
7058     EXPECT_NE(0u, program);
7059 }
7060 
7061 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)7062 TEST_P(GLSLTest, InactiveSamplersInStruct)
7063 {
7064     // While the sampler is being extracted and declared outside of the struct, it's not removed
7065     // from the struct definition.  http://anglebug.com/4211
7066     ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
7067 
7068     constexpr char kVS[] = R"(attribute vec4 a_position;
7069 void main() {
7070   gl_Position = a_position;
7071 })";
7072 
7073     constexpr char kFS[] = R"(precision highp float;
7074 struct S
7075 {
7076     vec4 v;
7077     sampler2D t[10];
7078 };
7079 uniform S s;
7080 void main() {
7081   gl_FragColor = s.v;
7082 })";
7083 
7084     ANGLE_GL_PROGRAM(program, kVS, kFS);
7085 
7086     drawQuad(program, "a_position", 0.5f);
7087 }
7088 
7089 // Helper functions for MixedRowAndColumnMajorMatrices* tests
7090 
7091 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)7092 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
7093 {
7094     return (value + alignment - 1) & ~(alignment - 1);
7095 }
7096 
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)7097 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
7098 {
7099     unsigned int outputInitData = 0;
7100     glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
7101     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
7102     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
7103     EXPECT_GL_NO_ERROR();
7104 }
7105 
7106 // Fill provided buffer with matrices based on the given dimensions.  The buffer should be large
7107 // 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)7108 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
7109                     const bool matrixIsColMajor[],
7110                     size_t matrixCount,
7111                     float data[],
7112                     bool isStd430,
7113                     bool isTransposed)
7114 {
7115     size_t offset = 0;
7116     for (size_t m = 0; m < matrixCount; ++m)
7117     {
7118         uint32_t cols   = matrixDims[m].first;
7119         uint32_t rows   = matrixDims[m].second;
7120         bool isColMajor = matrixIsColMajor[m] != isTransposed;
7121 
7122         uint32_t arraySize              = isColMajor ? cols : rows;
7123         uint32_t arrayElementComponents = isColMajor ? rows : cols;
7124         // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
7125         // MixedRowAndColumnMajorMatrices* tests don't use).  With std430, small matrices can have
7126         // a stride of 2 between rows/columns.
7127         uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
7128 
7129         offset = RoundUpPow2(offset, stride);
7130 
7131         for (uint32_t i = 0; i < arraySize; ++i)
7132         {
7133             for (uint32_t c = 0; c < arrayElementComponents; ++c)
7134             {
7135                 uint32_t row = isColMajor ? c : i;
7136                 uint32_t col = isColMajor ? i : c;
7137 
7138                 data[offset + i * stride + c] = col * 4 + row;
7139             }
7140         }
7141 
7142         offset += arraySize * stride;
7143     }
7144     return offset;
7145 }
7146 
7147 // Initialize and bind the buffer.
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,float data[],uint32_t dataSize,bool isUniform)7148 void InitBuffer(GLuint program,
7149                 const char *name,
7150                 GLuint buffer,
7151                 uint32_t bindingIndex,
7152                 float data[],
7153                 uint32_t dataSize,
7154                 bool isUniform)
7155 {
7156     GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
7157 
7158     glBindBufferBase(bindPoint, bindingIndex, buffer);
7159     glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
7160 
7161     if (isUniform)
7162     {
7163         GLint blockIndex = glGetUniformBlockIndex(program, name);
7164         glUniformBlockBinding(program, blockIndex, bindingIndex);
7165     }
7166 }
7167 
7168 // Verify that buffer data is written by the shader as expected.
VerifyBuffer(GLuint buffer,const float data[],uint32_t dataSize)7169 bool VerifyBuffer(GLuint buffer, const float data[], uint32_t dataSize)
7170 {
7171     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
7172 
7173     const float *ptr = reinterpret_cast<const float *>(
7174         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize, GL_MAP_READ_BIT));
7175 
7176     bool isCorrect = memcmp(ptr, data, dataSize * sizeof(*data)) == 0;
7177     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7178 
7179     return isCorrect;
7180 }
7181 
7182 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)7183 bool VerifySuccess(GLuint buffer)
7184 {
7185     uint32_t success = 1;
7186     return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
7187 }
7188 
7189 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
7190 // both std140 and std430 layouts.  Tests many combinations of std140 vs std430, struct being used
7191 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
7192 // nested structs, matrix arrays, inout parameters etc.
7193 //
7194 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)7195 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
7196 {
7197     GLint maxComputeShaderStorageBlocks;
7198     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
7199 
7200     // The test uses 9 SSBOs.  Skip if not that many are supported.
7201     ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
7202 
7203     // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
7204     // UBO also see it as row-major despite explicit column-major qualifier.
7205     // http://anglebug.com/3830
7206     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
7207 
7208     // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
7209     // read column-major despite explicit row-major qualifier.  http://anglebug.com/3837
7210     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
7211 
7212     // Fails on windows AMD on GL: http://anglebug.com/3838
7213     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
7214 
7215     // Fails to compile the shader on Android.  http://anglebug.com/3839
7216     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
7217 
7218     // Fails on assertion in translation to D3D.  http://anglebug.com/3841
7219     ANGLE_SKIP_TEST_IF(IsD3D11());
7220 
7221     // Fails on SSBO validation on Android/Vulkan.  http://anglebug.com/3840
7222     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
7223 
7224     // Fails input verification as well as std140 SSBO validation.  http://anglebug.com/3844
7225     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
7226 
7227     // Fails on ARM on Vulkan.  http://anglebug.com/4492
7228     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
7229 
7230     constexpr char kCS[] = R"(#version 310 es
7231 precision highp float;
7232 layout(local_size_x=1) in;
7233 
7234 struct Inner
7235 {
7236     mat3x4 m3c4r;
7237     mat4x3 m4c3r;
7238 };
7239 
7240 struct Matrices
7241 {
7242     mat2 m2c2r;
7243     mat2x3 m2c3r[2];
7244     mat3x2 m3c2r;
7245     Inner inner;
7246 };
7247 
7248 // For simplicity, the layouts are either of:
7249 // - col-major mat4, row-major rest
7250 // - row-major mat4, col-major rest
7251 //
7252 // The former is tagged with c, the latter with r.
7253 layout(std140, column_major) uniform Ubo140c
7254 {
7255     mat4 m4c4r;
7256     layout(row_major) Matrices m;
7257 } ubo140cIn;
7258 
7259 layout(std140, row_major) uniform Ubo140r
7260 {
7261     mat4 m4c4r;
7262     layout(column_major) Matrices m;
7263 } ubo140rIn;
7264 
7265 layout(std140, row_major, binding = 0) buffer Ssbo140c
7266 {
7267     layout(column_major) mat4 m4c4r;
7268     Matrices m;
7269 } ssbo140cIn;
7270 
7271 layout(std140, column_major, binding = 1) buffer Ssbo140r
7272 {
7273     layout(row_major) mat4 m4c4r;
7274     Matrices m;
7275 } ssbo140rIn;
7276 
7277 layout(std430, column_major, binding = 2) buffer Ssbo430c
7278 {
7279     mat4 m4c4r;
7280     layout(row_major) Matrices m;
7281 } ssbo430cIn;
7282 
7283 layout(std430, row_major, binding = 3) buffer Ssbo430r
7284 {
7285     mat4 m4c4r;
7286     layout(column_major) Matrices m;
7287 } ssbo430rIn;
7288 
7289 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
7290 {
7291     layout(column_major) mat4 m4c4r;
7292     Matrices m;
7293 } ssbo140cOut;
7294 
7295 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
7296 {
7297     layout(row_major) mat4 m4c4r;
7298     Matrices m;
7299 } ssbo140rOut;
7300 
7301 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
7302 {
7303     mat4 m4c4r;
7304     layout(row_major) Matrices m;
7305 } ssbo430cOut;
7306 
7307 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
7308 {
7309     mat4 m4c4r;
7310     layout(column_major) Matrices m;
7311 } ssbo430rOut;
7312 
7313 layout(std140, binding = 8) buffer Result
7314 {
7315     uint success;
7316 } resultOut;
7317 
7318 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
7319 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
7320 
7321 #define VERIFY_IN(result, mat, cols, rows)                  \
7322     EXPECT(result, mat[0].x, 0.0);                          \
7323     EXPECT(result, mat[0][1], 1.0);                         \
7324     EXPECTV(result, mat[0].xy, vec2(0, 1));                 \
7325     EXPECTV(result, mat[1].xy, vec2(4, 5));                 \
7326     for (int c = 0; c < cols; ++c)                          \
7327     {                                                       \
7328         for (int r = 0; r < rows; ++r)                      \
7329         {                                                   \
7330             EXPECT(result, mat[c][r], float(c * 4 + r));    \
7331         }                                                   \
7332     }
7333 
7334 #define COPY(matIn, matOut, cols, rows)     \
7335     matOut = matOut + matIn;                \
7336     /* random operations for testing */     \
7337     matOut[0].x += matIn[0].x + matIn[1].x; \
7338     matOut[0].x -= matIn[1].x;              \
7339     matOut[0][1] += matIn[0][1];            \
7340     matOut[1] += matIn[1];                  \
7341     matOut[1].xy -= matIn[1].xy;            \
7342     /* undo the above to get back matIn */  \
7343     matOut[0].x -= matIn[0].x;              \
7344     matOut[0][1] -= matIn[0][1];            \
7345     matOut[1] -= matIn[1];                  \
7346     matOut[1].xy += matIn[1].xy;
7347 
7348 bool verifyMatrices(in Matrices m)
7349 {
7350     bool result = true;
7351     VERIFY_IN(result, m.m2c2r, 2, 2);
7352     VERIFY_IN(result, m.m2c3r[0], 2, 3);
7353     VERIFY_IN(result, m.m2c3r[1], 2, 3);
7354     VERIFY_IN(result, m.m3c2r, 3, 2);
7355     VERIFY_IN(result, m.inner.m3c4r, 3, 4);
7356     VERIFY_IN(result, m.inner.m4c3r, 4, 3);
7357     return result;
7358 }
7359 
7360 mat4 copyMat4(in mat4 m)
7361 {
7362     return m;
7363 }
7364 
7365 void copyMatrices(in Matrices mIn, inout Matrices mOut)
7366 {
7367     COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
7368     COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
7369     COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
7370     COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
7371     COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
7372     COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
7373 }
7374 
7375 void main()
7376 {
7377     bool result = true;
7378 
7379     VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
7380     VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
7381     EXPECT(result, verifyMatrices(ubo140cIn.m), true);
7382 
7383     VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
7384     VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
7385     EXPECT(result, verifyMatrices(ubo140rIn.m), true);
7386 
7387     VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
7388     VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
7389     EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
7390 
7391     VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
7392     VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
7393     EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
7394 
7395     VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
7396     VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
7397     EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
7398 
7399     VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
7400     VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
7401     EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
7402 
7403     // Only assign to SSBO from a single invocation.
7404     if (gl_GlobalInvocationID.x == 0u)
7405     {
7406         ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
7407         copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
7408         ssbo140cOut.m.m2c3r[1] = mat2x3(0);
7409         COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
7410 
7411         ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
7412         copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
7413         ssbo140rOut.m.inner.m3c4r = mat3x4(0);
7414         COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
7415 
7416         ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
7417         copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
7418         ssbo430cOut.m.m3c2r = mat3x2(0);
7419         COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
7420 
7421         ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
7422         copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
7423         ssbo430rOut.m.inner.m4c3r = mat4x3(0);
7424         COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
7425 
7426         resultOut.success = uint(result);
7427     }
7428 })";
7429 
7430     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
7431     EXPECT_GL_NO_ERROR();
7432 
7433     constexpr size_t kMatrixCount                                     = 7;
7434     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
7435         {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
7436     };
7437     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
7438         true, false, false, false, false, false, false,
7439     };
7440 
7441     float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
7442     float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
7443     float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
7444     float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
7445     float dataZeros[kMatrixCount * 4 * 4]          = {};
7446 
7447     const uint32_t sizeStd140ColMajor =
7448         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
7449     const uint32_t sizeStd140RowMajor =
7450         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
7451     const uint32_t sizeStd430ColMajor =
7452         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
7453     const uint32_t sizeStd430RowMajor =
7454         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
7455 
7456     GLBuffer uboStd140ColMajor, uboStd140RowMajor;
7457     GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
7458     GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
7459     GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
7460     GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
7461 
7462     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
7463                true);
7464     InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
7465                true);
7466     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
7467                false);
7468     InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
7469                false);
7470     InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
7471                false);
7472     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
7473                false);
7474     InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
7475                false);
7476     InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
7477                false);
7478     InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
7479                false);
7480     InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
7481                false);
7482     EXPECT_GL_NO_ERROR();
7483 
7484     GLBuffer outputBuffer;
7485     CreateOutputBuffer(&outputBuffer, 8);
7486 
7487     glUseProgram(program);
7488     glDispatchCompute(1, 1, 1);
7489     EXPECT_GL_NO_ERROR();
7490     EXPECT_TRUE(VerifySuccess(outputBuffer));
7491 
7492     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
7493     EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
7494     EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
7495     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
7496 }
7497 
7498 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)7499 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
7500 {
7501     // Fails to compile the shader on Android: http://anglebug.com/3839
7502     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
7503 
7504     // http://anglebug.com/3837
7505     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
7506 
7507     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
7508     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
7509 
7510     // Fails on windows AMD on GL: http://anglebug.com/3838
7511     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
7512 
7513     // Fails on D3D due to mistranslation: http://anglebug.com/3841
7514     ANGLE_SKIP_TEST_IF(IsD3D11());
7515 
7516     constexpr char kFS[] = R"(#version 300 es
7517 precision highp float;
7518 out vec4 outColor;
7519 
7520 layout(std140, column_major) uniform Ubo
7521 {
7522     mat4 m1;
7523     layout(row_major) mat4 m2;
7524 } ubo[3];
7525 
7526 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
7527 
7528 #define VERIFY_IN(result, mat, cols, rows)                  \
7529     for (int c = 0; c < cols; ++c)                          \
7530     {                                                       \
7531         for (int r = 0; r < rows; ++r)                      \
7532         {                                                   \
7533             EXPECT(result, mat[c][r], float(c * 4 + r));    \
7534         }                                                   \
7535     }
7536 
7537 void main()
7538 {
7539     bool result = true;
7540 
7541     VERIFY_IN(result, ubo[0].m1, 4, 4);
7542     VERIFY_IN(result, ubo[0].m2, 4, 4);
7543 
7544     VERIFY_IN(result, ubo[1].m1, 4, 4);
7545     VERIFY_IN(result, ubo[1].m2, 4, 4);
7546 
7547     VERIFY_IN(result, ubo[2].m1, 4, 4);
7548     VERIFY_IN(result, ubo[2].m2, 4, 4);
7549 
7550     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7551 })";
7552 
7553     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7554     EXPECT_GL_NO_ERROR();
7555 
7556     constexpr size_t kMatrixCount                                     = 2;
7557     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
7558         {4, 4},
7559         {4, 4},
7560     };
7561     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
7562         true,
7563         false,
7564     };
7565 
7566     float data[kMatrixCount * 4 * 4] = {};
7567 
7568     const uint32_t size =
7569         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
7570 
7571     GLBuffer ubos[3];
7572 
7573     InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
7574     InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
7575     InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
7576 
7577     EXPECT_GL_NO_ERROR();
7578 
7579     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7580     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7581 }
7582 
7583 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)7584 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
7585 {
7586     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
7587     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
7588 
7589     // Fails on D3D due to mistranslation: http://anglebug.com/3841
7590     ANGLE_SKIP_TEST_IF(IsD3D11());
7591 
7592     constexpr char kFS[] = R"(#version 300 es
7593 precision highp float;
7594 out vec4 outColor;
7595 
7596 struct S
7597 {
7598     mat2x3 m2[3];
7599 };
7600 
7601 layout(std140, column_major) uniform Ubo
7602 {
7603     mat4 m1;
7604     layout(row_major) S s[2];
7605 } ubo;
7606 
7607 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
7608 
7609 #define VERIFY_IN(result, mat, cols, rows)                  \
7610     for (int c = 0; c < cols; ++c)                          \
7611     {                                                       \
7612         for (int r = 0; r < rows; ++r)                      \
7613         {                                                   \
7614             EXPECT(result, mat[c][r], float(c * 4 + r));    \
7615         }                                                   \
7616     }
7617 
7618 bool verify2x3(mat2x3 mat)
7619 {
7620     bool result = true;
7621 
7622     for (int c = 0; c < 2; ++c)
7623     {
7624         for (int r = 0; r < 3; ++r)
7625         {
7626             EXPECT(result, mat[c][r], float(c * 4 + r));
7627         }
7628     }
7629 
7630     return result;
7631 }
7632 
7633 void main()
7634 {
7635     bool result = true;
7636 
7637     int sideEffect = 0;
7638     VERIFY_IN(result, ubo.m1, 4, 4);
7639     EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
7640     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
7641     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
7642 
7643     EXPECT(result, sideEffect, 2);
7644 
7645     EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
7646     EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
7647     EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
7648 
7649     EXPECT(result, sideEffect, 4);
7650 
7651     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7652 })";
7653 
7654     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7655     EXPECT_GL_NO_ERROR();
7656 
7657     constexpr size_t kMatrixCount                                     = 7;
7658     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
7659         {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
7660     };
7661     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
7662         true, false, false, false, false, false, false,
7663     };
7664 
7665     float data[kMatrixCount * 4 * 4] = {};
7666 
7667     const uint32_t size =
7668         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
7669 
7670     GLBuffer ubo;
7671     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
7672 
7673     EXPECT_GL_NO_ERROR();
7674 
7675     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7676     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7677 }
7678 
7679 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)7680 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
7681 {
7682     // http://anglebug.com/3837
7683     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
7684 
7685     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
7686     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
7687     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
7688 
7689     constexpr char kFS[] = R"(#version 300 es
7690 precision highp float;
7691 out vec4 outColor;
7692 
7693 layout(std140, column_major) uniform Ubo
7694 {
7695     mat4 m1;
7696     layout(row_major) mat4 m2[2];
7697 } ubo;
7698 
7699 void main()
7700 {
7701     bool result = true;
7702 
7703     int x = 0;
7704     if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
7705     {
7706         result = true;
7707     }
7708     else
7709     {
7710         result = false;
7711     }
7712 
7713     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7714 })";
7715 
7716     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7717     EXPECT_GL_NO_ERROR();
7718 
7719     constexpr size_t kMatrixCount                                     = 3;
7720     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
7721         {4, 4},
7722         {4, 4},
7723         {4, 4},
7724     };
7725     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
7726 
7727     float data[kMatrixCount * 4 * 4] = {};
7728 
7729     const uint32_t size =
7730         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
7731 
7732     GLBuffer ubo;
7733     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
7734 
7735     EXPECT_GL_NO_ERROR();
7736 
7737     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7738     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7739 }
7740 
7741 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)7742 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
7743 {
7744     // Fails on Android: http://anglebug.com/3839
7745     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
7746 
7747     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
7748     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
7749     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
7750 
7751     constexpr char kFS[] = R"(#version 300 es
7752 precision highp float;
7753 out vec4 outColor;
7754 
7755 layout(std140, column_major) uniform Ubo
7756 {
7757     mat4 m1;
7758     layout(row_major) mat4 m2[2];
7759 } ubo;
7760 
7761 void main()
7762 {
7763     bool result = true;
7764 
7765     int x = 0;
7766     if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
7767     {
7768         // First x == 1 should prevent the side effect of the second expression (x = 1) from
7769         // being executed.  If x = 1 is run before the if, the condition of the if would be true,
7770         // which is a failure.
7771         result = false;
7772     }
7773     if (x == 1)
7774     {
7775         result = false;
7776     }
7777 
7778     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7779 })";
7780 
7781     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7782     EXPECT_GL_NO_ERROR();
7783 
7784     constexpr size_t kMatrixCount                                     = 3;
7785     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
7786         {4, 4},
7787         {4, 4},
7788         {4, 4},
7789     };
7790     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
7791 
7792     float data[kMatrixCount * 4 * 4] = {};
7793 
7794     const uint32_t size =
7795         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
7796 
7797     GLBuffer ubo;
7798     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
7799 
7800     EXPECT_GL_NO_ERROR();
7801 
7802     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7804 }
7805 
7806 // Test that dynamic indexing of swizzled l-values should work.
7807 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)7808 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
7809 {
7810     // The shader first assigns v.x to v.z (1.0)
7811     // Then v.y to v.y (2.0)
7812     // Then v.z to v.x (1.0)
7813     constexpr char kFS[] = R"(#version 300 es
7814 precision highp float;
7815 out vec4 my_FragColor;
7816 void main() {
7817     vec3 v = vec3(1.0, 2.0, 3.0);
7818     for (int i = 0; i < 3; i++) {
7819         v.zyx[i] = v[i];
7820     }
7821     my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7822 })";
7823 
7824     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7825     EXPECT_GL_NO_ERROR();
7826     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
7827     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7828 }
7829 
7830 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
7831 // make sure they are all linked ok.  The front-end sorts these resources and traverses the list of
7832 // "uniforms" to find the range for each resource.  A bug there was causing some resource ranges to
7833 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)7834 TEST_P(GLSLTest_ES31, MixOfAllResources)
7835 {
7836     constexpr char kComputeShader[] = R"(#version 310 es
7837 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
7838 layout(binding = 1, std430) buffer Output {
7839   uint ubo_value;
7840   uint default_value;
7841   uint sampler_value;
7842   uint ac_value;
7843   uint image_value;
7844 } outbuf;
7845 uniform Input {
7846   uint input_value;
7847 } inbuf;
7848 uniform uint default_uniform;
7849 uniform sampler2D smplr;
7850 layout(binding=0) uniform atomic_uint ac;
7851 layout(r32ui) uniform highp readonly uimage2D image;
7852 
7853 void main(void)
7854 {
7855   outbuf.ubo_value = inbuf.input_value;
7856   outbuf.default_value = default_uniform;
7857   outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
7858   outbuf.ac_value = atomicCounterIncrement(ac);
7859   outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
7860 }
7861 )";
7862     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
7863     EXPECT_GL_NO_ERROR();
7864 
7865     glUseProgram(program);
7866 
7867     unsigned int inputData = 89u;
7868     GLBuffer inputBuffer;
7869     glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
7870     glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
7871     GLuint inputBufferIndex = glGetUniformBlockIndex(program.get(), "Input");
7872     ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
7873     glUniformBlockBinding(program.get(), inputBufferIndex, 0);
7874     glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
7875 
7876     unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
7877                                       0x13579BDFu};
7878     GLBuffer outputBuffer;
7879     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
7880     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
7881     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
7882     EXPECT_GL_NO_ERROR();
7883 
7884     unsigned int uniformData = 456u;
7885     GLint uniformLocation    = glGetUniformLocation(program, "default_uniform");
7886     ASSERT_NE(uniformLocation, -1);
7887     glUniform1ui(uniformLocation, uniformData);
7888 
7889     unsigned int acData = 2u;
7890     GLBuffer atomicCounterBuffer;
7891     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
7892     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
7893     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
7894     EXPECT_GL_NO_ERROR();
7895 
7896     unsigned int imageData = 33u;
7897     GLTexture image;
7898     glBindTexture(GL_TEXTURE_2D, image);
7899     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
7900     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
7901     glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
7902     EXPECT_GL_NO_ERROR();
7903 
7904     GLColor textureData(127, 18, 189, 211);
7905     GLTexture texture;
7906     glBindTexture(GL_TEXTURE_2D, texture);
7907     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
7908     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7909     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7910     ASSERT_GL_NO_ERROR();
7911 
7912     glDispatchCompute(1, 1, 1);
7913     EXPECT_GL_NO_ERROR();
7914 
7915     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7916 
7917     // read back
7918     const GLuint *ptr = reinterpret_cast<const GLuint *>(
7919         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
7920     EXPECT_EQ(ptr[0], inputData);
7921     EXPECT_EQ(ptr[1], uniformData);
7922     EXPECT_NEAR(ptr[2], textureData.R, 1.0);
7923     EXPECT_EQ(ptr[3], acData);
7924     EXPECT_EQ(ptr[4], imageData);
7925 
7926     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7927 }
7928 
7929 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)7930 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
7931 {
7932     // http://anglebug.com/3831
7933     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
7934 
7935     // Fails on windows AMD on GL: http://anglebug.com/3838
7936     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
7937 
7938     // Fails on D3D due to mistranslation: http://anglebug.com/3841
7939     ANGLE_SKIP_TEST_IF(IsD3D11());
7940 
7941     constexpr char kCS[] = R"(#version 310 es
7942 precision highp float;
7943 layout(local_size_x=1) in;
7944 
7945 layout(std140, column_major) uniform Ubo
7946 {
7947     mat4 m1;
7948     layout(row_major) mat4 m2;
7949 } ubo;
7950 
7951 layout(std140, row_major, binding = 0) buffer Ssbo
7952 {
7953     layout(column_major) mat4 m1;
7954     mat4 m2;
7955 } ssbo;
7956 
7957 layout(std140, binding = 1) buffer Result
7958 {
7959     uint success;
7960 } resultOut;
7961 
7962 void main()
7963 {
7964     bool result = true;
7965 
7966     // Only assign to SSBO from a single invocation.
7967     if (gl_GlobalInvocationID.x == 0u)
7968     {
7969         if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
7970         {
7971             result = false;
7972         }
7973 
7974         resultOut.success = uint(result);
7975     }
7976 })";
7977 
7978     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
7979     EXPECT_GL_NO_ERROR();
7980 
7981     constexpr size_t kMatrixCount                                     = 2;
7982     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
7983         {4, 4},
7984         {4, 4},
7985     };
7986     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
7987         true,
7988         false,
7989     };
7990 
7991     float data[kMatrixCount * 4 * 4]  = {};
7992     float zeros[kMatrixCount * 4 * 4] = {};
7993 
7994     const uint32_t size =
7995         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
7996 
7997     GLBuffer ubo, ssbo;
7998 
7999     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
8000     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
8001     EXPECT_GL_NO_ERROR();
8002 
8003     GLBuffer outputBuffer;
8004     CreateOutputBuffer(&outputBuffer, 1);
8005 
8006     glUseProgram(program);
8007     glDispatchCompute(1, 1, 1);
8008     EXPECT_GL_NO_ERROR();
8009     EXPECT_TRUE(VerifySuccess(outputBuffer));
8010 
8011     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
8012 }
8013 
8014 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)8015 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
8016 {
8017     // Fails on windows AMD on GL: http://anglebug.com/3838
8018     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
8019 
8020     // Fails on D3D due to mistranslation: http://anglebug.com/3841
8021     ANGLE_SKIP_TEST_IF(IsD3D11());
8022 
8023     // Fails compiling shader on Android/Vulkan.  http://anglebug.com/4290
8024     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
8025 
8026     // Fails on ARM on Vulkan.  http://anglebug.com/4492
8027     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
8028 
8029     constexpr char kCS[] = R"(#version 310 es
8030 precision highp float;
8031 layout(local_size_x=1) in;
8032 
8033 layout(std140, column_major) uniform Ubo
8034 {
8035     mat4 m1;
8036     layout(row_major) mat4 m2[2][3];
8037 } ubo;
8038 
8039 layout(std140, row_major, binding = 0) buffer Ssbo
8040 {
8041     layout(column_major) mat4 m1;
8042     mat4 m2[2][3];
8043 } ssbo;
8044 
8045 layout(std140, binding = 1) buffer Result
8046 {
8047     uint success;
8048 } resultOut;
8049 
8050 void main()
8051 {
8052     bool result = true;
8053 
8054     // Only assign to SSBO from a single invocation.
8055     if (gl_GlobalInvocationID.x == 0u)
8056     {
8057         ssbo.m1 = ubo.m1;
8058         ssbo.m2 = ubo.m2;
8059 
8060         resultOut.success = uint(result);
8061     }
8062 })";
8063 
8064     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
8065     EXPECT_GL_NO_ERROR();
8066 
8067     constexpr size_t kMatrixCount                                     = 7;
8068     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
8069         {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
8070     };
8071     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
8072         true, false, false, false, false, false, false,
8073     };
8074 
8075     float data[kMatrixCount * 4 * 4]  = {};
8076     float zeros[kMatrixCount * 4 * 4] = {};
8077 
8078     const uint32_t size =
8079         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
8080 
8081     GLBuffer ubo, ssbo;
8082 
8083     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
8084     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
8085     EXPECT_GL_NO_ERROR();
8086 
8087     GLBuffer outputBuffer;
8088     CreateOutputBuffer(&outputBuffer, 1);
8089 
8090     glUseProgram(program);
8091     glDispatchCompute(1, 1, 1);
8092     EXPECT_GL_NO_ERROR();
8093     EXPECT_TRUE(VerifySuccess(outputBuffer));
8094 
8095     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
8096 }
8097 
8098 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)8099 TEST_P(GLSLTest_ES3, PreciseNotReserved)
8100 {
8101     // Skip in ES3.1+ as the precise keyword is reserved/core.
8102     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
8103                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
8104 
8105     constexpr char kFS[] = R"(#version 300 es
8106 precision mediump float;
8107 in float precise;
8108 out vec4 my_FragColor;
8109 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
8110 
8111     constexpr char kVS[] = R"(#version 300 es
8112 in vec4 a_position;
8113 out float precise;
8114 void main() { precise = a_position.x; gl_Position = a_position; })";
8115 
8116     GLuint program = CompileProgram(kVS, kFS);
8117     EXPECT_NE(0u, program);
8118 }
8119 
8120 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)8121 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
8122 {
8123     // Skip if EXT_gpu_shader5 is enabled.
8124     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
8125     // Skip in ES3.2+ as the precise keyword is core.
8126     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
8127                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
8128 
8129     constexpr char kFS[] = R"(#version 310 es
8130 precision mediump float;
8131 in float v_varying;
8132 out vec4 my_FragColor;
8133 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
8134 
8135     constexpr char kVS[] = R"(#version 310 es
8136 in vec4 a_position;
8137 precise out float v_varying;
8138 void main() { v_varying = a_position.x; gl_Position = a_position; })";
8139 
8140     // Should fail, as precise is a reserved keyword when the extension is not enabled.
8141     GLuint program = CompileProgram(kVS, kFS);
8142     EXPECT_EQ(0u, program);
8143 }
8144 
8145 // Test that reusing the same variable name for different uses across stages links fine.  Glslang
8146 // wrapper's SPIR-V transformation should ignore all names for non-shader-interface variables and
8147 // not get confused by them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)8148 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
8149 {
8150     // Fails to compile the fragment shader with error "undeclared identifier '_g'"
8151     // http://anglebug.com/4404
8152     ANGLE_SKIP_TEST_IF(IsD3D11());
8153 
8154     constexpr char kVS[] = R"(#version 310 es
8155 precision mediump float;
8156 uniform highp vec4 a;
8157 in highp vec4 b;
8158 in highp vec4 c;
8159 in highp vec4 d;
8160 out highp vec4 e;
8161 
8162 vec4 f(vec4 a)
8163 {
8164     return a;
8165 }
8166 
8167 vec4 g(vec4 f)
8168 {
8169     return f + f;
8170 }
8171 
8172 void main() {
8173     e = f(b) + a;
8174     gl_Position = g(c) + f(d);
8175 }
8176 )";
8177 
8178     constexpr char kFS[] = R"(#version 310 es
8179 precision mediump float;
8180 in highp vec4 e;
8181 uniform sampler2D f;
8182 layout(rgba8) uniform highp readonly image2D g;
8183 uniform A
8184 {
8185     vec4 x;
8186 } c;
8187 layout(std140, binding=0) buffer B
8188 {
8189     vec4 x;
8190 } d[2];
8191 out vec4 col;
8192 
8193 vec4 h(vec4 c)
8194 {
8195     return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
8196 }
8197 
8198 vec4 i(vec4 x, vec4 y)
8199 {
8200     return vec4(x.xy, y.zw);
8201 }
8202 
8203 void main() {
8204     col = h(e) + i(c.x, d[0].x) + d[1].x;
8205 }
8206 )";
8207 
8208     GLuint program = CompileProgram(kVS, kFS);
8209     EXPECT_NE(0u, program);
8210 }
8211 }  // anonymous namespace
8212 
8213 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
8214 // tests should be run against.
8215 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTest);
8216 
8217 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
8218 
8219 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
8220 // tests should be run against.
8221 ANGLE_INSTANTIATE_TEST_ES3(GLSLTest_ES3);
8222 
8223 ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
8224 
8225 ANGLE_INSTANTIATE_TEST_ES31(GLSLTest_ES31);
8226