• 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 
BuildBigInitialStackShader(int length)518 std::string BuildBigInitialStackShader(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     constexpr char kFS[] = R"(precision mediump float;
677 
678 struct T
679 {
680     float f;
681 };
682 
683 void main()
684 {
685     T a;
686 
687     struct T
688     {
689         float q;
690     };
691 
692     T b;
693 
694     gl_FragColor = vec4(1, 0, 0, 1);
695     gl_FragColor.a += a.f;
696     gl_FragColor.a += b.q;
697 })";
698 
699     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
700 }
701 
702 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
703 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)704 TEST_P(GLSLTest, ScopedStructsOrderBug2)
705 {
706     constexpr char kFS[] = R"(precision mediump float;
707 
708 uniform struct T
709 {
710     float f;
711 } x;
712 
713 void main()
714 {
715     T a;
716 
717     struct T
718     {
719         float q;
720     };
721 
722     T b;
723 
724     gl_FragColor = vec4(1, 0, 0, 1);
725     gl_FragColor.a += a.f;
726     gl_FragColor.a += b.q;
727 })";
728 
729     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
730 }
731 
732 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)733 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
734 {
735     constexpr char kVS[] = R"(
736 struct S {
737     float member;
738 }, a;
739 void main() {
740     a.member = 0.0;
741     gl_Position = vec4(a.member);
742 })";
743 
744     constexpr char kFS[] = R"(precision mediump float;
745 precision mediump float;
746 void main()
747 {
748     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
749 })";
750 
751     ANGLE_GL_PROGRAM(program, kVS, kFS);
752 }
753 
754 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)755 TEST_P(GLSLTest, StructConstantFoldingBug)
756 {
757     constexpr char kVS[] = R"(
758 void main()
759 {
760 
761    const struct s2 {
762        int i;
763        vec3 v3;
764        bvec4 bv4;
765    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
766 
767    struct s4 {
768        int ii;
769        vec4 v4;
770       };
771 
772    const struct s1 {
773       s2 ss;
774       int i;
775       float f;
776       mat4 m;
777       s4 s44;
778    } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
779 
780   const int field3 = s11.i * s11.ss.i;  // constant folding (int * int)
781   const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
782  // 49, 64, 81, 100
783   const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]);  // 10.0, 5.0, 16.0, 81.0
784   gl_Position = v4;
785 })";
786 
787     constexpr char kFS[] = R"(precision mediump float;
788 precision mediump float;
789 void main()
790 {
791     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
792 })";
793 
794     ANGLE_GL_PROGRAM(program, kVS, kFS);
795 }
796 
797 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)798 TEST_P(GLSLTest, StructConstantFoldingBug2)
799 {
800     constexpr char kVS[] = R"(
801 uniform vec4 u;
802 
803 void main()
804 {
805 
806    const struct s2 {
807        int i;
808        vec3 v3;
809        bvec4 bv4;
810    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
811 
812    s2 x;
813    x.v3 = u.xyz;
814 
815    gl_Position = vec4(x.v3, float(s22.i));
816 })";
817 
818     constexpr char kFS[] = R"(precision mediump float;
819 precision mediump float;
820 void main()
821 {
822     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
823 })";
824 
825     ANGLE_GL_PROGRAM(program, kVS, kFS);
826 }
827 
TEST_P(GLSLTest,ScopedStructsBug)828 TEST_P(GLSLTest, ScopedStructsBug)
829 {
830     constexpr char kFS[] = R"(precision mediump float;
831 
832 struct T_0
833 {
834     float f;
835 };
836 
837 void main()
838 {
839     gl_FragColor = vec4(1, 0, 0, 1);
840 
841     struct T
842     {
843         vec2 v;
844     };
845 
846     T_0 a;
847     T b;
848 
849     gl_FragColor.a += a.f;
850     gl_FragColor.a += b.v.x;
851 })";
852 
853     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
854 }
855 
TEST_P(GLSLTest,DxPositionBug)856 TEST_P(GLSLTest, DxPositionBug)
857 {
858     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
859 varying float dx_Position;
860 void main()
861 {
862     gl_Position = vec4(inputAttribute);
863     dx_Position = 0.0;
864 })";
865 
866     constexpr char kFS[] = R"(precision mediump float;
867 
868 varying float dx_Position;
869 
870 void main()
871 {
872     gl_FragColor = vec4(dx_Position, 0, 0, 1);
873 })";
874 
875     ANGLE_GL_PROGRAM(program, kVS, kFS);
876 }
877 
878 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)879 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
880 {
881     // http://anglebug.com/4092
882     ANGLE_SKIP_TEST_IF(isSwiftshader());
883     constexpr int kStartIndex  = 0;
884     constexpr int kArrayLength = 5;
885     constexpr char kVS[]       = R"(#version 300 es
886 precision highp float;
887 void main() {
888     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
889     gl_PointSize = 3.0;
890 })";
891 
892     constexpr char kFS[] = R"(#version 300 es
893 precision highp float;
894 out vec4 outColor;
895 void main() {
896     outColor = vec4(1.0, 0.0, 0.0, 1.0);
897 })";
898 
899     ANGLE_GL_PROGRAM(program, kVS, kFS);
900 
901     glUseProgram(program);
902     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
903 
904     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
905     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
906     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
907     {
908         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
909         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
910                               static_cast<int>(pointCenterY), GLColor::red);
911     }
912 }
913 
914 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)915 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
916 {
917     glDrawArrays(GL_POINTS, first, count);
918 
919     int pixel[4];
920     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
921     // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
922     // pixels.
923     if (err == static_cast<GLenum>(GL_NO_ERROR))
924     {
925         EXPECT_GL_NO_ERROR();
926         EXPECT_EQ(pixel[0], first + count - 1);
927     }
928     else
929     {
930         // If we call this function with err set, we will allow the error, but check the pixels if
931         // the error hasn't occurred.
932         GLenum glError = glGetError();
933         if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
934         {
935             EXPECT_EQ(pixel[0], first + count - 1);
936         }
937     }
938 }
939 
940 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
941 // is based off the WebGL test:
942 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)943 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
944 {
945     // http://anglebug.com/4092
946     ANGLE_SKIP_TEST_IF(isSwiftshader());
947     // http://anglebug.com/5232
948     ANGLE_SKIP_TEST_IF(IsMetal());
949     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
950     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
951     // TODO(anglebug.com/5491): Failing on iOS, probably related to the ARM Mac failure above.
952     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
953     // Have to set a large point size because the window size is much larger than the texture
954     constexpr char kVS[] = R"(#version 300 es
955 flat out highp int vVertexID;
956 void main() {
957     vVertexID = gl_VertexID;
958     gl_Position = vec4(0,0,0,1);
959     gl_PointSize = 1000.0;
960 })";
961 
962     constexpr char kFS[] = R"(#version 300 es
963 flat in highp int vVertexID;
964 out highp int oVertexID;
965 void main() {
966     oVertexID = vVertexID;
967 })";
968 
969     ANGLE_GL_PROGRAM(program, kVS, kFS);
970     glUseProgram(program);
971 
972     GLTexture texture;
973     glBindTexture(GL_TEXTURE_2D, texture);
974     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
975     GLFramebuffer fbo;
976     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
977     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
978     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
979     EXPECT_GL_NO_ERROR();
980 
981     // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
982     GLint val[4] = {42};
983     glClearBufferiv(GL_COLOR, 0, val);
984     int pixel[4];
985     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
986     EXPECT_EQ(pixel[0], val[0]);
987 
988     GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
989     GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
990     GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
991     GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
992     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
993     GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
994     GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
995     GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
996     GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
997     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
998 
999     int32_t int32Max = 0x7FFFFFFF;
1000     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1001     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1002     GLVertexIDIntegerTextureDrawArrays_helper(int32Max, 1, GL_OUT_OF_MEMORY);
1003 }
1004 
1005 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1006 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1007 {
1008     // http://anglebug.com/4092
1009     ANGLE_SKIP_TEST_IF(isSwiftshader());
1010     // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
1011     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1012 
1013     constexpr int kStartIndex  = 5;
1014     constexpr int kArrayLength = 5;
1015     constexpr char kVS[]       = R"(#version 300 es
1016 precision highp float;
1017 void main() {
1018     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1019     gl_PointSize = 3.0;
1020 })";
1021 
1022     constexpr char kFS[] = R"(#version 300 es
1023 precision highp float;
1024 out vec4 outColor;
1025 void main() {
1026     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1027 })";
1028 
1029     ANGLE_GL_PROGRAM(program, kVS, kFS);
1030 
1031     glUseProgram(program);
1032     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1033 
1034     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1035     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1036     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1037     {
1038         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1039         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1040                               static_cast<int>(pointCenterY), GLColor::red);
1041     }
1042 }
1043 
TEST_P(GLSLTest,ElseIfRewriting)1044 TEST_P(GLSLTest, ElseIfRewriting)
1045 {
1046     constexpr char kVS[] =
1047         "attribute vec4 a_position;\n"
1048         "varying float v;\n"
1049         "void main() {\n"
1050         "  gl_Position = a_position;\n"
1051         "  v = 1.0;\n"
1052         "  if (a_position.x <= 0.5) {\n"
1053         "    v = 0.0;\n"
1054         "  } else if (a_position.x >= 0.5) {\n"
1055         "    v = 2.0;\n"
1056         "  }\n"
1057         "}\n";
1058 
1059     constexpr char kFS[] =
1060         "precision highp float;\n"
1061         "varying float v;\n"
1062         "void main() {\n"
1063         "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1064         "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1065         "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1066         "  gl_FragColor = color;\n"
1067         "}\n";
1068 
1069     ANGLE_GL_PROGRAM(program, kVS, kFS);
1070 
1071     drawQuad(program, "a_position", 0.5f);
1072 
1073     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1074     EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1075 }
1076 
TEST_P(GLSLTest,TwoElseIfRewriting)1077 TEST_P(GLSLTest, TwoElseIfRewriting)
1078 {
1079     constexpr char kVS[] =
1080         "attribute vec4 a_position;\n"
1081         "varying float v;\n"
1082         "void main() {\n"
1083         "  gl_Position = a_position;\n"
1084         "  if (a_position.x == 0.0) {\n"
1085         "    v = 1.0;\n"
1086         "  } else if (a_position.x > 0.5) {\n"
1087         "    v = 0.0;\n"
1088         "  } else if (a_position.x > 0.75) {\n"
1089         "    v = 0.5;\n"
1090         "  }\n"
1091         "}\n";
1092 
1093     constexpr char kFS[] =
1094         "precision highp float;\n"
1095         "varying float v;\n"
1096         "void main() {\n"
1097         "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1098         "}\n";
1099 
1100     ANGLE_GL_PROGRAM(program, kVS, kFS);
1101 }
1102 
TEST_P(GLSLTest,FrontFacingAndVarying)1103 TEST_P(GLSLTest, FrontFacingAndVarying)
1104 {
1105     EGLPlatformParameters platform = GetParam().eglParameters;
1106 
1107     constexpr char kVS[] = R"(attribute vec4 a_position;
1108 varying float v_varying;
1109 void main()
1110 {
1111     v_varying = a_position.x;
1112     gl_Position = a_position;
1113 })";
1114 
1115     constexpr char kFS[] = R"(precision mediump float;
1116 varying float v_varying;
1117 void main()
1118 {
1119     vec4 c;
1120 
1121     if (gl_FrontFacing)
1122     {
1123         c = vec4(v_varying, 0, 0, 1.0);
1124     }
1125     else
1126     {
1127         c = vec4(0, v_varying, 0, 1.0);
1128     }
1129     gl_FragColor = c;
1130 })";
1131 
1132     GLuint program = CompileProgram(kVS, kFS);
1133 
1134     // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1135     if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1136     {
1137         if (platform.majorVersion == 9 && platform.minorVersion == 3)
1138         {
1139             EXPECT_EQ(0u, program);
1140             return;
1141         }
1142     }
1143 
1144     // Otherwise, compilation should succeed
1145     EXPECT_NE(0u, program);
1146 }
1147 
1148 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1149 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1150 {
1151     // Draw with the first program.
1152     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1153     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1154     ASSERT_GL_NO_ERROR();
1155     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1156 
1157     // Clear and release shader compiler.
1158     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1159     glClear(GL_COLOR_BUFFER_BIT);
1160     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1161     glReleaseShaderCompiler();
1162     ASSERT_GL_NO_ERROR();
1163 
1164     // Draw with a second program.
1165     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1166     drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1167     ASSERT_GL_NO_ERROR();
1168     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1169 }
1170 
1171 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1172 TEST_P(GLSLTest_ES3, VersionMismatch)
1173 {
1174     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1175     EXPECT_EQ(0u, program);
1176 
1177     program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1178     EXPECT_EQ(0u, program);
1179 }
1180 
1181 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1182 TEST_P(GLSLTest, InvariantVaryingOut)
1183 {
1184     constexpr char kFS[] =
1185         "precision mediump float;\n"
1186         "varying float v_varying;\n"
1187         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1188 
1189     constexpr char kVS[] =
1190         "attribute vec4 a_position;\n"
1191         "invariant varying float v_varying;\n"
1192         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1193 
1194     GLuint program = CompileProgram(kVS, kFS);
1195     EXPECT_EQ(0u, program);
1196 }
1197 
1198 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1199 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1200 {
1201     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1202     // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1203     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1204 
1205     constexpr char kFS[] =
1206         "#version 300 es\n"
1207         "precision mediump float;\n"
1208         "in float v_varying;\n"
1209         "out vec4 my_FragColor;\n"
1210         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1211 
1212     constexpr char kVS[] =
1213         "#version 300 es\n"
1214         "in vec4 a_position;\n"
1215         "invariant out float v_varying;\n"
1216         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1217 
1218     GLuint program = CompileProgram(kVS, kFS);
1219     EXPECT_NE(0u, program);
1220 }
1221 
1222 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1223 TEST_P(GLSLTest, InvariantVaryingIn)
1224 {
1225     constexpr char kFS[] =
1226         "precision mediump float;\n"
1227         "invariant varying float v_varying;\n"
1228         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1229 
1230     constexpr char kVS[] =
1231         "attribute vec4 a_position;\n"
1232         "varying float v_varying;\n"
1233         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1234 
1235     GLuint program = CompileProgram(kVS, kFS);
1236     EXPECT_EQ(0u, program);
1237 }
1238 
1239 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1240 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1241 {
1242     constexpr char kFS[] =
1243         "#version 300 es\n"
1244         "precision mediump float;\n"
1245         "invariant in float v_varying;\n"
1246         "out vec4 my_FragColor;\n"
1247         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1248 
1249     constexpr char kVS[] =
1250         "#version 300 es\n"
1251         "in vec4 a_position;\n"
1252         "out float v_varying;\n"
1253         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1254 
1255     GLuint program = CompileProgram(kVS, kFS);
1256     EXPECT_EQ(0u, program);
1257 }
1258 
1259 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1260 TEST_P(GLSLTest, InvariantVaryingBoth)
1261 {
1262     constexpr char kFS[] =
1263         "precision mediump float;\n"
1264         "invariant varying float v_varying;\n"
1265         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1266 
1267     constexpr char kVS[] =
1268         "attribute vec4 a_position;\n"
1269         "invariant varying float v_varying;\n"
1270         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1271 
1272     GLuint program = CompileProgram(kVS, kFS);
1273     EXPECT_NE(0u, program);
1274 }
1275 
1276 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1277 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1278 {
1279     constexpr char kFS[] =
1280         "#version 300 es\n"
1281         "precision mediump float;\n"
1282         "invariant in float v_varying;\n"
1283         "out vec4 my_FragColor;\n"
1284         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1285 
1286     constexpr char kVS[] =
1287         "#version 300 es\n"
1288         "in vec4 a_position;\n"
1289         "invariant out float v_varying;\n"
1290         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1291 
1292     GLuint program = CompileProgram(kVS, kFS);
1293     EXPECT_EQ(0u, program);
1294 }
1295 
1296 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1297 TEST_P(GLSLTest, InvariantGLPosition)
1298 {
1299     constexpr char kFS[] =
1300         "precision mediump float;\n"
1301         "varying float v_varying;\n"
1302         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1303 
1304     constexpr char kVS[] =
1305         "attribute vec4 a_position;\n"
1306         "invariant gl_Position;\n"
1307         "varying float v_varying;\n"
1308         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1309 
1310     GLuint program = CompileProgram(kVS, kFS);
1311     EXPECT_NE(0u, program);
1312 }
1313 
1314 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1315 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1316 {
1317     constexpr char kFS[] =
1318         "#version 300 es\n"
1319         "precision mediump float;\n"
1320         "in float v_varying;\n"
1321         "out vec4 my_FragColor;\n"
1322         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1323 
1324     constexpr char kVS[] =
1325         "#version 300 es\n"
1326         "in vec4 a_position;\n"
1327         "invariant gl_Position;\n"
1328         "out float v_varying;\n"
1329         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1330 
1331     GLuint program = CompileProgram(kVS, kFS);
1332     EXPECT_NE(0u, program);
1333 }
1334 
1335 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1336 TEST_P(GLSLTest, InvariantAllBoth)
1337 {
1338     constexpr char kFS[] =
1339         "#pragma STDGL invariant(all)\n"
1340         "precision mediump float;\n"
1341         "varying float v_varying;\n"
1342         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1343 
1344     constexpr char kVS[] =
1345         "#pragma STDGL invariant(all)\n"
1346         "attribute vec4 a_position;\n"
1347         "varying float v_varying;\n"
1348         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1349 
1350     GLuint program = CompileProgram(kVS, kFS);
1351     EXPECT_EQ(0u, program);
1352 }
1353 
1354 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1355 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1356 {
1357     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1358 
1359     constexpr char kVS[] = R"(#version 310 es
1360 #extension GL_EXT_shader_io_blocks : require
1361 
1362 struct S
1363 {
1364     vec4 s;
1365 };
1366 
1367 out Output
1368 {
1369     vec4 x;
1370     invariant S s;
1371 };
1372 
1373 out S s2;
1374 
1375 void main(){
1376     x = vec4(0);
1377     s.s = vec4(1);
1378     s2.s = vec4(2);
1379     S s3 = s;
1380     s.s = s3.s;
1381 })";
1382 
1383     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1384     EXPECT_NE(0u, shader);
1385     glDeleteShader(shader);
1386 }
1387 
1388 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)1389 TEST_P(GLSLTest, MissingReturnFloat)
1390 {
1391     constexpr char kVS[] =
1392         "varying float v_varying;\n"
1393         "float f() { if (v_varying > 0.0) return 1.0; }\n"
1394         "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
1395 
1396     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1397     EXPECT_NE(0u, program);
1398 }
1399 
1400 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)1401 TEST_P(GLSLTest, MissingReturnVec2)
1402 {
1403     constexpr char kVS[] =
1404         "varying float v_varying;\n"
1405         "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
1406         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1407 
1408     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1409     EXPECT_NE(0u, program);
1410 }
1411 
1412 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)1413 TEST_P(GLSLTest, MissingReturnVec3)
1414 {
1415     constexpr char kVS[] =
1416         "varying float v_varying;\n"
1417         "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1418         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1419 
1420     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1421     EXPECT_NE(0u, program);
1422 }
1423 
1424 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)1425 TEST_P(GLSLTest, MissingReturnVec4)
1426 {
1427     constexpr char kVS[] =
1428         "varying float v_varying;\n"
1429         "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1430         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1431 
1432     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1433     EXPECT_NE(0u, program);
1434 }
1435 
1436 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)1437 TEST_P(GLSLTest, MissingReturnIVec4)
1438 {
1439     constexpr char kVS[] =
1440         "varying float v_varying;\n"
1441         "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1442         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1443 
1444     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1445     EXPECT_NE(0u, program);
1446 }
1447 
1448 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)1449 TEST_P(GLSLTest, MissingReturnMat4)
1450 {
1451     constexpr char kVS[] =
1452         "varying float v_varying;\n"
1453         "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1454         "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1455 
1456     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1457     EXPECT_NE(0u, program);
1458 }
1459 
1460 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)1461 TEST_P(GLSLTest, MissingReturnStruct)
1462 {
1463     constexpr char kVS[] =
1464         "varying float v_varying;\n"
1465         "struct s { float a; int b; vec2 c; };\n"
1466         "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1467         "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1468 
1469     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1470     EXPECT_NE(0u, program);
1471 }
1472 
1473 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)1474 TEST_P(GLSLTest_ES3, MissingReturnArray)
1475 {
1476     constexpr char kVS[] =
1477         "#version 300 es\n"
1478         "in float v_varying;\n"
1479         "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1480         "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1481 
1482     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1483     EXPECT_NE(0u, program);
1484 }
1485 
1486 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)1487 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1488 {
1489     constexpr char kVS[] =
1490         "#version 300 es\n"
1491         "in float v_varying;\n"
1492         "struct s { float a; int b; vec2 c; };\n"
1493         "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1494         "vec2(1.0, 1.0))); } }\n"
1495         "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1496 
1497     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1498     EXPECT_NE(0u, program);
1499 }
1500 
1501 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)1502 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1503 {
1504     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
1505     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
1506 
1507     constexpr char kVS[] =
1508         "#version 300 es\n"
1509         "in float v_varying;\n"
1510         "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1511         "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1512         "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1513         "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1514 
1515     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1516     EXPECT_NE(0u, program);
1517 }
1518 
1519 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)1520 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
1521 {
1522     constexpr char kVS[] = R"(#version 300 es
1523 in float v_varying;
1524 struct s { float a; int b; vec2 c; };
1525 s[2] f()
1526 {
1527     return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
1528 }
1529 void main()
1530 {
1531     gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
1532 })";
1533 
1534     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1535     EXPECT_NE(0u, program);
1536 }
1537 
1538 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)1539 TEST_P(GLSLTest_ES3, InvariantAllBoth)
1540 {
1541     constexpr char kFS[] =
1542         "#version 300 es\n"
1543         "#pragma STDGL invariant(all)\n"
1544         "precision mediump float;\n"
1545         "in float v_varying;\n"
1546         "out vec4 my_FragColor;\n"
1547         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1548 
1549     constexpr char kVS[] =
1550         "#version 300 es\n"
1551         "#pragma STDGL invariant(all)\n"
1552         "in vec4 a_position;\n"
1553         "out float v_varying;\n"
1554         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1555 
1556     GLuint program = CompileProgram(kVS, kFS);
1557     EXPECT_EQ(0u, program);
1558 }
1559 
1560 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)1561 TEST_P(GLSLTest, InvariantAllIn)
1562 {
1563     constexpr char kFS[] =
1564         "#pragma STDGL invariant(all)\n"
1565         "precision mediump float;\n"
1566         "varying float v_varying;\n"
1567         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1568 
1569     constexpr char kVS[] =
1570         "attribute vec4 a_position;\n"
1571         "varying float v_varying;\n"
1572         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1573 
1574     GLuint program = CompileProgram(kVS, kFS);
1575     EXPECT_NE(0u, program);
1576 }
1577 
1578 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)1579 TEST_P(GLSLTest_ES3, InvariantAllIn)
1580 {
1581     constexpr char kFS[] =
1582         "#version 300 es\n"
1583         "#pragma STDGL invariant(all)\n"
1584         "precision mediump float;\n"
1585         "in float v_varying;\n"
1586         "out vec4 my_FragColor;\n"
1587         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1588 
1589     constexpr char kVS[] =
1590         "#version 300 es\n"
1591         "in vec4 a_position;\n"
1592         "out float v_varying;\n"
1593         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1594 
1595     GLuint program = CompileProgram(kVS, kFS);
1596     EXPECT_EQ(0u, program);
1597 }
1598 
1599 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)1600 TEST_P(GLSLTest, InvariantAllOut)
1601 {
1602     constexpr char kFS[] =
1603         "precision mediump float;\n"
1604         "varying float v_varying;\n"
1605         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1606 
1607     constexpr char kVS[] =
1608         "#pragma STDGL invariant(all)\n"
1609         "attribute vec4 a_position;\n"
1610         "varying float v_varying;\n"
1611         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1612 
1613     GLuint program = CompileProgram(kVS, kFS);
1614     EXPECT_EQ(0u, program);
1615 }
1616 
1617 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)1618 TEST_P(GLSLTest_ES3, InvariantAllOut)
1619 {
1620     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1621     // for varyings which are invariant in vertex shader,
1622     // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
1623     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1624 
1625     constexpr char kFS[] =
1626         "#version 300 es\n"
1627         "precision mediump float;\n"
1628         "in float v_varying;\n"
1629         "out vec4 my_FragColor;\n"
1630         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1631 
1632     constexpr char kVS[] =
1633         "#version 300 es\n"
1634         "#pragma STDGL invariant(all)\n"
1635         "in vec4 a_position;\n"
1636         "out float v_varying;\n"
1637         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1638 
1639     GLuint program = CompileProgram(kVS, kFS);
1640     EXPECT_NE(0u, program);
1641 }
1642 
TEST_P(GLSLTest,MaxVaryingVec4)1643 TEST_P(GLSLTest, MaxVaryingVec4)
1644 {
1645     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1646     // (http://anglebug.com/1291)
1647     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1648 
1649     GLint maxVaryings = 0;
1650     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1651 
1652     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1653 }
1654 
1655 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)1656 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
1657 {
1658     GLint maxVaryings = 0;
1659     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1660 
1661     // Generate shader code that uses gl_FragCoord.
1662     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
1663 }
1664 
1665 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)1666 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
1667 {
1668     GLint maxVaryings = 0;
1669     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1670 
1671     // Generate shader code that uses gl_FragCoord and gl_PointCoord.
1672     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1673 }
1674 
1675 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)1676 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
1677 {
1678     GLint maxVaryings = 0;
1679     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1680 
1681     // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1682     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
1683 }
1684 
1685 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1686 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)1687 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
1688 {
1689     ANGLE_SKIP_TEST_IF(!IsD3D9());
1690 
1691     GLint maxVaryings = 0;
1692     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1693 
1694     VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
1695     VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
1696     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
1697 
1698     // Special case for gl_PointSize: we get it for free on D3D9.
1699     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
1700 }
1701 
1702 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1703 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)1704 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
1705 {
1706     GLint maxVaryings = 0;
1707     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1708 
1709     // Generate shader code that uses gl_FragCoord.
1710     VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
1711 }
1712 
TEST_P(GLSLTest,MaxVaryingVec3)1713 TEST_P(GLSLTest, MaxVaryingVec3)
1714 {
1715     GLint maxVaryings = 0;
1716     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1717 
1718     VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
1719 }
1720 
TEST_P(GLSLTest,MaxVaryingVec3Array)1721 TEST_P(GLSLTest, MaxVaryingVec3Array)
1722 {
1723     GLint maxVaryings = 0;
1724     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1725 
1726     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
1727 }
1728 
1729 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)1730 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
1731 {
1732     GLint maxVaryings = 0;
1733     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1734 
1735     VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
1736 }
1737 
1738 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)1739 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
1740 {
1741     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
1742     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsMetal());
1743 
1744     GLint maxVaryings = 0;
1745     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1746 
1747     VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
1748 }
1749 
1750 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)1751 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
1752 {
1753     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1754     // (http://anglebug.com/3849)
1755     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
1756 
1757     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1758     // (http://anglebug.com/1291)
1759     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1760 
1761     GLint maxVaryings = 0;
1762     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1763 
1764     VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
1765 }
1766 
1767 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)1768 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
1769 {
1770     ANGLE_SKIP_TEST_IF(IsD3DSM3());
1771 
1772     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1773     ANGLE_SKIP_TEST_IF(IsOpenGLES());
1774 
1775     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1776     // (http://anglebug.com/1291)
1777     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1778 
1779     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
1780     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsMetal());
1781 
1782     GLint maxVaryings = 0;
1783     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1784 
1785     // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1786     // we should be aware that when we're packing into an odd number of varying registers the
1787     // last row will be empty and can not fit the final vec2 arrary.
1788     GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1789 
1790     VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
1791 }
1792 
1793 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)1794 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
1795 {
1796     // (http://anglebug.com/4439)
1797     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
1798 
1799     // http://anglebug.com/4446
1800     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
1801 
1802     GLint maxVaryings = 0;
1803     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1804 
1805     std::stringstream vertexShaderSource;
1806     std::stringstream fragmentShaderSource;
1807 
1808     // substract 1 here for gl_PointSize
1809     const GLint vec4Count     = maxVaryings - 1;
1810     unsigned int varyingCount = 0;
1811     std::string varyingDeclaration;
1812     for (GLint i = 0; i < vec4Count; i++)
1813     {
1814         varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
1815         varyingCount += 1;
1816     }
1817     // Generate the vertex shader
1818     vertexShaderSource.clear();
1819     vertexShaderSource << varyingDeclaration;
1820     vertexShaderSource << "\nattribute vec4 a_position;\n";
1821     vertexShaderSource << "\nvoid main()\n{\n";
1822     unsigned int currentVSVarying = 0;
1823     for (GLint i = 0; i < vec4Count; i++)
1824     {
1825         vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
1826         currentVSVarying += 1;
1827     }
1828     vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
1829     vertexShaderSource << "\tgl_PointSize = 1.0;\n";
1830     vertexShaderSource << "}\n";
1831 
1832     // Generate the fragment shader
1833     fragmentShaderSource.clear();
1834     fragmentShaderSource << "precision highp float;\n";
1835     fragmentShaderSource << varyingDeclaration;
1836     fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
1837     unsigned int currentFSVarying = 0;
1838     // Make use of the vec4 varyings
1839     fragmentShaderSource << "\tretColor += ";
1840     for (GLint i = 0; i < vec4Count; i++)
1841     {
1842         fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
1843         currentFSVarying += 1;
1844     }
1845     fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
1846     constexpr GLuint testValue = 234;
1847     fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
1848                          << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
1849     fragmentShaderSource << "}\n";
1850 
1851     std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
1852     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
1853                                         fragmentShaderSource.str().c_str(), tfVaryings,
1854                                         GL_INTERLEAVED_ATTRIBS);
1855 
1856     GLBuffer xfbBuffer;
1857     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1858     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
1859                  GL_STATIC_DRAW);
1860 
1861     GLTransformFeedback xfb;
1862     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1863     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1864 
1865     glUseProgram(program1);
1866 
1867     const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
1868     GLBuffer vertexBuffer;
1869     // need to shift half pixel to make sure the line covers the center of the pixel
1870     const Vector3 vertices[2] = {
1871         {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
1872         {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
1873     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1874     glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
1875     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1876     glEnableVertexAttribArray(positionLocation);
1877 
1878     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
1879     glClear(GL_COLOR_BUFFER_BIT);
1880 
1881     glBeginTransformFeedback(GL_LINES);
1882     glDrawArrays(GL_LINES, 0, 2);
1883     glEndTransformFeedback();
1884 
1885     ASSERT_GL_NO_ERROR();
1886 
1887     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
1888 }
1889 
1890 // Verify shader source with a fixed length that is less than the null-terminated length will
1891 // compile.
TEST_P(GLSLTest,FixedShaderLength)1892 TEST_P(GLSLTest, FixedShaderLength)
1893 {
1894     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1895 
1896     const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
1897     const std::string source   = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1898     const char *sourceArray[1] = {source.c_str()};
1899     GLint lengths[1]           = {static_cast<GLint>(source.length() - appendGarbage.length())};
1900     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1901     glCompileShader(shader);
1902 
1903     GLint compileResult;
1904     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1905     EXPECT_NE(compileResult, 0);
1906 }
1907 
1908 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)1909 TEST_P(GLSLTest, NegativeShaderLength)
1910 {
1911     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1912 
1913     const char *sourceArray[1] = {essl1_shaders::fs::Red()};
1914     GLint lengths[1]           = {-10};
1915     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1916     glCompileShader(shader);
1917 
1918     GLint compileResult;
1919     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1920     EXPECT_NE(compileResult, 0);
1921 }
1922 
1923 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)1924 TEST_P(GLSLTest, InvalidFieldFirstChar)
1925 {
1926     GLuint shader      = glCreateShader(GL_VERTEX_SHADER);
1927     const char *source = "void main() {vec4 x; x.}";
1928     glShaderSource(shader, 1, &source, 0);
1929     glCompileShader(shader);
1930 
1931     GLint compileResult;
1932     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1933     EXPECT_EQ(0, compileResult);
1934 }
1935 
1936 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)1937 TEST_P(GLSLTest, MixedShaderLengths)
1938 {
1939     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1940 
1941     const char *sourceArray[] = {
1942         "void main()",
1943         "{",
1944         "    gl_FragColor = vec4(0, 0, 0, 0);",
1945         "}",
1946     };
1947     GLint lengths[] = {
1948         -10,
1949         1,
1950         static_cast<GLint>(strlen(sourceArray[2])),
1951         -1,
1952     };
1953     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1954 
1955     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1956     glCompileShader(shader);
1957 
1958     GLint compileResult;
1959     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1960     EXPECT_NE(compileResult, 0);
1961 }
1962 
1963 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)1964 TEST_P(GLSLTest, ZeroShaderLength)
1965 {
1966     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1967 
1968     const char *sourceArray[] = {
1969         "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
1970     };
1971     GLint lengths[] = {
1972         0, 0, -1, 0, 0,
1973     };
1974     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1975 
1976     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1977     glCompileShader(shader);
1978 
1979     GLint compileResult;
1980     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1981     EXPECT_NE(compileResult, 0);
1982 }
1983 
1984 // Tests that bad index expressions don't crash ANGLE's translator.
1985 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)1986 TEST_P(GLSLTest, BadIndexBug)
1987 {
1988     constexpr char kFSSourceVec[] =
1989         "precision mediump float;\n"
1990         "uniform vec4 uniformVec;\n"
1991         "void main()\n"
1992         "{\n"
1993         "    gl_FragColor = vec4(uniformVec[int()]);\n"
1994         "}";
1995 
1996     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
1997     EXPECT_EQ(0u, shader);
1998 
1999     if (shader != 0)
2000     {
2001         glDeleteShader(shader);
2002     }
2003 
2004     constexpr char kFSSourceMat[] =
2005         "precision mediump float;\n"
2006         "uniform mat4 uniformMat;\n"
2007         "void main()\n"
2008         "{\n"
2009         "    gl_FragColor = vec4(uniformMat[int()]);\n"
2010         "}";
2011 
2012     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2013     EXPECT_EQ(0u, shader);
2014 
2015     if (shader != 0)
2016     {
2017         glDeleteShader(shader);
2018     }
2019 
2020     constexpr char kFSSourceArray[] =
2021         "precision mediump float;\n"
2022         "uniform vec4 uniformArray;\n"
2023         "void main()\n"
2024         "{\n"
2025         "    gl_FragColor = vec4(uniformArray[int()]);\n"
2026         "}";
2027 
2028     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2029     EXPECT_EQ(0u, shader);
2030 
2031     if (shader != 0)
2032     {
2033         glDeleteShader(shader);
2034     }
2035 }
2036 
2037 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2038 TEST_P(GLSLTest, StructSpecifiersUniforms)
2039 {
2040     constexpr char kFS[] = R"(precision mediump float;
2041 
2042 uniform struct S { float field; } s;
2043 
2044 void main()
2045 {
2046     gl_FragColor = vec4(1, 0, 0, 1);
2047     gl_FragColor.a += s.field;
2048 })";
2049 
2050     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2051     EXPECT_NE(0u, program);
2052 }
2053 
2054 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2055 TEST_P(GLSLTest, StructWithInitializer)
2056 {
2057     constexpr char kFS[] = R"(precision mediump float;
2058 
2059 struct S { float a; } s = S(1.0);
2060 
2061 void main()
2062 {
2063     gl_FragColor = vec4(0, 0, 0, 1);
2064     gl_FragColor.r += s.a;
2065 })";
2066 
2067     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2068     glUseProgram(program);
2069 
2070     // Test drawing, should be red.
2071     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2072 
2073     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2074     EXPECT_GL_NO_ERROR();
2075 }
2076 
2077 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2078 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2079 {
2080     constexpr char kFS[] = R"(precision mediump float;
2081 
2082 struct S { float a; };
2083 uniform S u_s;
2084 
2085 void main()
2086 {
2087     gl_FragColor = vec4(u_s.a);
2088 })";
2089 
2090     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2091     glUseProgram(program);
2092 
2093     // Test drawing, should be red.
2094     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2095 
2096     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2097     EXPECT_GL_NO_ERROR();
2098 }
2099 
2100 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2101 TEST_P(GLSLTest, StructWithUniformInitializer)
2102 {
2103     constexpr char kFS[] = R"(precision mediump float;
2104 
2105 struct S { float a; } s = S(1.0);
2106 uniform S us;
2107 
2108 void main()
2109 {
2110     gl_FragColor = vec4(0, 0, 0, 1);
2111     gl_FragColor.r += s.a;
2112     gl_FragColor.g += us.a;
2113 })";
2114 
2115     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2116     glUseProgram(program);
2117 
2118     // Test drawing, should be red.
2119     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2120 
2121     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2122     EXPECT_GL_NO_ERROR();
2123 }
2124 
2125 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2126 // beginning with "gl_" are filtered out by our validation logic, we must
2127 // bypass the validation to test the behaviour of the implementation.
2128 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2129 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2130 {
2131     constexpr char kFS[] = R"(precision mediump float;
2132 
2133 void main()
2134 {
2135     gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2136 })";
2137 
2138     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2139 
2140     // We need to bypass validation for this call.
2141     GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
2142     EXPECT_EQ(-1, nearIndex);
2143 
2144     // Test drawing does not throw an exception.
2145     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2146 
2147     EXPECT_GL_NO_ERROR();
2148 }
2149 
GenerateSmallPowShader(double base,double exponent)2150 std::string GenerateSmallPowShader(double base, double exponent)
2151 {
2152     std::stringstream stream;
2153 
2154     stream.precision(8);
2155 
2156     double result = pow(base, exponent);
2157 
2158     stream << "precision highp float;\n"
2159            << "float fun(float arg)\n"
2160            << "{\n"
2161            << "    return pow(arg, " << std::fixed << exponent << ");\n"
2162            << "}\n"
2163            << "\n"
2164            << "void main()\n"
2165            << "{\n"
2166            << "    const float a = " << std::scientific << base << ";\n"
2167            << "    float b = fun(a);\n"
2168            << "    if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2169            << "    {\n"
2170            << "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2171            << "    }\n"
2172            << "    else\n"
2173            << "    {\n"
2174            << "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2175            << "    }\n"
2176            << "}\n";
2177 
2178     return stream.str();
2179 }
2180 
2181 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2182 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)2183 TEST_P(GLSLTest, PowOfSmallConstant)
2184 {
2185     // Test with problematic exponents that are close to an integer.
2186     std::vector<double> testExponents;
2187     std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2188     for (double epsilonMultiplier : epsilonMultipliers)
2189     {
2190         for (int i = -4; i <= 5; ++i)
2191         {
2192             if (i >= -1 && i <= 1)
2193                 continue;
2194             const double epsilon = 1.0e-8;
2195             double bad           = static_cast<double>(i) + epsilonMultiplier * epsilon;
2196             testExponents.push_back(bad);
2197         }
2198     }
2199 
2200     // Also test with a few exponents that are not close to an integer.
2201     testExponents.push_back(3.6);
2202     testExponents.push_back(3.4);
2203 
2204     for (double testExponent : testExponents)
2205     {
2206         const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2207 
2208         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2209 
2210         drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2211 
2212         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2213         EXPECT_GL_NO_ERROR();
2214     }
2215 }
2216 
2217 // Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
2218 // below
2219 // fail with a specific error message.
2220 // Additionally test that the same fragment shader compiles successfully with feature levels greater
2221 // than FL9_3.
TEST_P(GLSLTest,LoopIndexingValidation)2222 TEST_P(GLSLTest, LoopIndexingValidation)
2223 {
2224     constexpr char kFS[] = R"(precision mediump float;
2225 
2226 uniform float loopMax;
2227 
2228 void main()
2229 {
2230     gl_FragColor = vec4(1, 0, 0, 1);
2231     for (float l = 0.0; l < loopMax; l++)
2232     {
2233         if (loopMax > 3.0)
2234         {
2235             gl_FragColor.a += 0.1;
2236         }
2237     }
2238 })";
2239 
2240     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2241 
2242     const char *sourceArray[1] = {kFS};
2243     glShaderSource(shader, 1, sourceArray, nullptr);
2244     glCompileShader(shader);
2245 
2246     GLint compileResult;
2247     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2248 
2249     // If the test is configured to run limited to Feature Level 9_3, then it is
2250     // assumed that shader compilation will fail with an expected error message containing
2251     // "Loop index cannot be compared with non-constant expression"
2252     if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
2253     {
2254         if (compileResult != 0)
2255         {
2256             FAIL() << "Shader compilation succeeded, expected failure";
2257         }
2258         else
2259         {
2260             GLint infoLogLength;
2261             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2262 
2263             std::string infoLog;
2264             infoLog.resize(infoLogLength);
2265             glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2266 
2267             if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2268                 std::string::npos)
2269             {
2270                 FAIL() << "Shader compilation failed with unexpected error message";
2271             }
2272         }
2273     }
2274     else
2275     {
2276         EXPECT_NE(0, compileResult);
2277     }
2278 
2279     if (shader != 0)
2280     {
2281         glDeleteShader(shader);
2282     }
2283 }
2284 
2285 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2286 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2287 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2288 {
2289     // crbug.com/680631
2290     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2291 
2292     int maxUniforms = 10000;
2293     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2294     EXPECT_GL_NO_ERROR();
2295     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2296 
2297     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2298 }
2299 
2300 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2301 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2302 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2303 {
2304     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2305 
2306     // Times out on D3D11 on test infra. http://anglebug.com/5076
2307     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2308 
2309     int maxUniforms = 10000;
2310     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2311     EXPECT_GL_NO_ERROR();
2312     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2313 
2314     int maxTextureImageUnits = 0;
2315     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2316 
2317     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2318 }
2319 
2320 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2321 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2322 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2323 {
2324     int maxUniforms = 10000;
2325     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2326     EXPECT_GL_NO_ERROR();
2327     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2328 
2329     CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2330 }
2331 
2332 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2333 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2334 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2335 {
2336     // crbug.com/680631
2337     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2338 
2339     int maxUniforms = 10000;
2340     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2341     EXPECT_GL_NO_ERROR();
2342     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2343 
2344     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2345 }
2346 
2347 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2348 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2349 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2350 {
2351     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2352 
2353     int maxUniforms = 10000;
2354     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2355     EXPECT_GL_NO_ERROR();
2356 
2357     int maxTextureImageUnits = 0;
2358     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2359 
2360     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2361 }
2362 
2363 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2364 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2365 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2366 {
2367     int maxUniforms = 10000;
2368     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2369     EXPECT_GL_NO_ERROR();
2370     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2371               << std::endl;
2372 
2373     CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2374 }
2375 
2376 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2377 TEST_P(GLSLTest, TextureLOD)
2378 {
2379     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2380 
2381     constexpr char kFS[] =
2382         "#extension GL_EXT_shader_texture_lod : require\n"
2383         "uniform sampler2D u_texture;\n"
2384         "void main() {\n"
2385         "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2386         "0.0));\n"
2387         "}\n";
2388 
2389     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2390     ASSERT_NE(0u, shader);
2391     glDeleteShader(shader);
2392 }
2393 
2394 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2395 // function calls to use them in vertex shaders.  http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2396 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2397 {
2398     constexpr char kVS[] = R"(
2399   precision highp float;
2400   uniform int uni;
2401   uniform sampler2D texture;
2402 
2403   vec4 A();
2404 
2405   vec4 B() {
2406     vec4 a;
2407     for(int r=0; r<14; r++){
2408       if (r < uni) return vec4(0.0);
2409       a = A();
2410     }
2411     return a;
2412   }
2413 
2414   vec4 A() {
2415     return texture2D(texture, vec2(0.0, 0.0));
2416   }
2417 
2418   void main() {
2419     gl_Position = B();
2420   })";
2421 
2422     constexpr char kFS[] = R"(
2423 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
2424 )";
2425 
2426     ANGLE_GL_PROGRAM(program, kVS, kFS);
2427 }
2428 
2429 // Test to verify the a shader can have a sampler unused in a vertex shader
2430 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)2431 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
2432 {
2433     constexpr char kVS[] = R"(
2434 attribute vec2 position;
2435 varying mediump vec2 texCoord;
2436 uniform sampler2D tex;
2437 void main()
2438 {
2439     gl_Position = vec4(position, 0, 1);
2440     texCoord = position * 0.5 + vec2(0.5);
2441 })";
2442 
2443     constexpr char kFS[] = R"(
2444 varying mediump vec2 texCoord;
2445 uniform sampler2D tex;
2446 void main()
2447 {
2448     gl_FragColor = texture2D(tex, texCoord);
2449 })";
2450 
2451     ANGLE_GL_PROGRAM(program, kVS, kFS);
2452 
2453     // Initialize basic red texture.
2454     const std::vector<GLColor> redColors(4, GLColor::red);
2455     GLTexture texture;
2456     glBindTexture(GL_TEXTURE_2D, texture);
2457     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
2458     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2459     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2460     ASSERT_GL_NO_ERROR();
2461 
2462     drawQuad(program, "position", 0.0f);
2463 
2464     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
2465 }
2466 
2467 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)2468 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
2469 {
2470     constexpr char kFS[] =
2471         "precision mediump float;\n"
2472         "struct Data { mediump sampler2D data[2]; };\n"
2473         "uniform Data test[2];\n"
2474         "void main() {\n"
2475         "    gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
2476         "                        texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
2477         "                        texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
2478         "                        texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
2479         "}\n";
2480 
2481     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2482     glUseProgram(program.get());
2483     GLTexture textures[4];
2484     GLColor expected = MakeGLColor(32, 64, 96, 255);
2485     GLubyte data[8]  = {};  // 4 bytes of padding, so that texture can be initialized with 4 bytes
2486     memcpy(data, expected.data(), sizeof(expected));
2487     for (int i = 0; i < 4; i++)
2488     {
2489         int outerIdx = i % 2;
2490         int innerIdx = i / 2;
2491         glActiveTexture(GL_TEXTURE0 + i);
2492         glBindTexture(GL_TEXTURE_2D, textures[i]);
2493         // Each element provides two components.
2494         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
2495         std::stringstream uniformName;
2496         uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
2497         // Then send it as a uniform
2498         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
2499         // The uniform should be active.
2500         EXPECT_NE(uniformLocation, -1);
2501 
2502         glUniform1i(uniformLocation, 3 - i);
2503     }
2504     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2505     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
2506 }
2507 
2508 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
2509 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)2510 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
2511 {
2512     constexpr const char *kFS = R"(
2513 #if __VERSION__ >= 300
2514     inout mediump vec4 fragData;
2515 #else
2516     #extension GL_EXT_shader_texture_lod :enable
2517 #endif
2518 
2519 void main()
2520 {
2521 }
2522     )";
2523 
2524     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2525     EXPECT_NE(0u, shader);
2526 }
2527 
2528 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
2529 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)2530 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
2531 {
2532     constexpr char kVS[] =
2533         "#version 300 es\n"
2534         "precision highp float;\n"
2535         "in vec4 a_vec;\n"
2536         "in mat2 a_mat;\n"
2537         "void main()\n"
2538         "{\n"
2539         "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
2540         "}";
2541 
2542     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2543     EXPECT_NE(0u, program);
2544 }
2545 
2546 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
2547 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
2548 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)2549 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
2550 {
2551     constexpr char kVS[] =
2552         "#version 300 es\n"
2553         "precision highp float;\n"
2554         "in mat3x2 a_matA;\n"
2555         "in mat2x3 a_matB;\n"
2556         "void main()\n"
2557         "{\n"
2558         "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
2559         "}";
2560 
2561     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2562     EXPECT_NE(0u, program);
2563 }
2564 
2565 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)2566 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
2567 {
2568     constexpr char kVS[] =
2569         "#version 300 es\n"
2570         "precision highp float;\n"
2571         "in vec4 a_vec;\n"
2572         "in mat2 a_mat;\n"
2573         "vec4 foo(vec4 a)\n"
2574         "{\n"
2575         "    return a;\n"
2576         "}\n"
2577         "vec4 foo(mat2 a)\n"
2578         "{\n"
2579         "    return vec4(a[0][0]);\n"
2580         "}\n"
2581         "void main()\n"
2582         "{\n"
2583         "    gl_Position = foo(a_vec) + foo(a_mat);\n"
2584         "}";
2585 
2586     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2587     EXPECT_NE(0u, program);
2588 }
2589 
2590 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)2591 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
2592 {
2593     constexpr char kFS[] = R"(#version 300 es
2594 precision highp float;
2595 out vec4 color;
2596 
2597 uniform int i;
2598 uniform uint u;
2599 
2600 void main()
2601 {
2602     bool b = i > 10;
2603 
2604     mat3x2 mi = mat3x2(i);
2605     mat4 mu = mat4(u);
2606     mat2x4 mb = mat2x4(b);
2607 
2608     mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
2609 
2610     color = vec4(mi[0][0] == float(i) ? 1 : 0,
2611                  mu[2][2] == float(u) ? 1 : 0,
2612                  mb[1][1] == float(b) ? 1 : 0,
2613                  m[0][1] == float(i) && m[1][0] == float(u) && m[2][0] == float(b) ? 1 : 0);
2614 })";
2615 
2616     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2617     glUseProgram(program);
2618 
2619     GLint iloc = glGetUniformLocation(program, "i");
2620     GLint uloc = glGetUniformLocation(program, "u");
2621     ASSERT_NE(iloc, -1);
2622     ASSERT_NE(uloc, -1);
2623     glUniform1i(iloc, -123);
2624     glUniform1ui(uloc, 456);
2625 
2626     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2627     EXPECT_GL_NO_ERROR();
2628 
2629     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2630 }
2631 
2632 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)2633 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
2634 {
2635     constexpr char kFS[] = R"(#version 300 es
2636 precision highp float;
2637 out vec4 color;
2638 
2639 uniform float f;
2640 
2641 void main()
2642 {
2643     mat4 m = mat4(f);
2644     ivec3 vi = ivec3(m);
2645     uvec2 vu = uvec2(m);
2646     bvec4 vb = bvec4(m);
2647 
2648     color = vec4(vi.x == int(f) ? 1 : 0,
2649                  vu.x == uint(f) ? 1 : 0,
2650                  vb.x == bool(f) ? 1 : 0,
2651                  1);
2652 })";
2653 
2654     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2655     glUseProgram(program);
2656 
2657     GLint floc = glGetUniformLocation(program, "f");
2658     ASSERT_NE(floc, -1);
2659     glUniform1f(floc, 123);
2660 
2661     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2662     EXPECT_GL_NO_ERROR();
2663 
2664     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2665 }
2666 
2667 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)2668 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
2669 {
2670     constexpr char kFS[] = R"(#version 300 es
2671 precision highp float;
2672 out vec4 color;
2673 
2674 uniform float f;
2675 uniform int i;
2676 uniform uint u;
2677 
2678 void main()
2679 {
2680     mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
2681     mat3x2 m32_2 = mat3x2(m32_1);
2682     mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
2683     mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
2684     mat2x3 m23_2 = mat2x3(m23_1);
2685     mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
2686     vec2 v2_1 = m32_1[0];
2687     vec2 v2_2 = m32_2[0];
2688     ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
2689     ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
2690     uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
2691     uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
2692 
2693     color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
2694                  v2_1 == v2_2 ? 1 : 0,
2695                  (v3_1 == v3_2 ? 0.5 : 0.0) +
2696                     (v4_1 == v4_2 ? 0.5 : 0.0),
2697                  (m32_1 != m32_3 ? 0.125 : 0.0) +
2698                     (m23_1 != m23_3 ? 0.125 : 0.0) +
2699                     (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
2700                     (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
2701                     (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
2702 })";
2703 
2704     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2705     glUseProgram(program);
2706 
2707     GLint floc = glGetUniformLocation(program, "f");
2708     GLint iloc = glGetUniformLocation(program, "i");
2709     GLint uloc = glGetUniformLocation(program, "u");
2710     ASSERT_NE(floc, -1);
2711     ASSERT_NE(iloc, -1);
2712     ASSERT_NE(uloc, -1);
2713     glUniform1f(floc, 1.5);
2714     glUniform1i(iloc, -123);
2715     glUniform1ui(uloc, 456);
2716 
2717     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2718     EXPECT_GL_NO_ERROR();
2719 
2720     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2721 }
2722 
2723 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)2724 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
2725 {
2726     constexpr char kFS[] = R"(#version 310 es
2727 precision highp float;
2728 out vec4 color;
2729 
2730 uniform float f;
2731 uniform int i;
2732 uniform uint u;
2733 
2734 struct S
2735 {
2736     float f;
2737     int i;
2738     uint u;
2739     vec4 v;
2740     ivec3 iv;
2741     uvec2 uv;
2742     mat3x2 m32;
2743     mat2x3 m23;
2744     float fa[3][4][5];
2745     int ia[4];
2746     uint ua[6][2];
2747 };
2748 
2749 struct T
2750 {
2751     S s1;
2752     S s2[3][2];
2753 };
2754 
2755 void main()
2756 {
2757     float fa[5] = float[5](f, f, f, f, f);
2758     int ia[4] = int[4](i, i, i, i);
2759     uint ua[2] = uint[2](u, u);
2760 
2761     S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
2762              mat3x2(vec2(f), vec2(i), vec2(u)),
2763              mat2x3(vec3(f), vec3(i)),
2764              float[3][4][5](
2765                             float[4][5](fa, fa, fa, fa),
2766                             float[4][5](fa, fa, fa, fa),
2767                             float[4][5](fa, fa, fa, fa)),
2768              ia,
2769              uint[6][2](ua, ua, ua, ua, ua, ua));
2770 
2771     S s2[2] = S[2](s1, s1);
2772     s2[1].fa[0][1][2] = float(i);
2773 
2774     T t1 = T(s1, S[3][2](s2, s2, s2));
2775     T t2 = T(s2[1], S[3][2](s2, s2, s2));
2776 
2777     T ta1[2] = T[2](t1, t2);
2778     T ta2[2] = T[2](t1, t2);
2779     T ta3[2] = T[2](t2, t1);
2780 
2781     color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
2782                  (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
2783                  (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
2784                  (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
2785 })";
2786 
2787     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
2788     glUseProgram(program);
2789 
2790     GLint floc = glGetUniformLocation(program, "f");
2791     GLint iloc = glGetUniformLocation(program, "i");
2792     GLint uloc = glGetUniformLocation(program, "u");
2793     ASSERT_NE(floc, -1);
2794     ASSERT_NE(iloc, -1);
2795     ASSERT_NE(uloc, -1);
2796     glUniform1f(floc, 1.5);
2797     glUniform1i(iloc, -123);
2798     glUniform1ui(uloc, 456);
2799 
2800     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2801     EXPECT_GL_NO_ERROR();
2802 
2803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2804 }
2805 
2806 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
2807 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)2808 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
2809 {
2810     std::stringstream vertexShaderStream;
2811     // Note: SPIR-V doesn't allow more than 255 parameters to a function.
2812     const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
2813 
2814     vertexShaderStream << "#version 300 es\n"
2815                           "precision highp float;\n"
2816                           "in vec4 a_vec;\n"
2817                           "vec4 lotsOfVec4Parameters(";
2818     for (unsigned int i = 0; i < paramCount - 1; ++i)
2819     {
2820         vertexShaderStream << "vec4 a" << i << ", ";
2821     }
2822     vertexShaderStream << "vec4 aLast)\n"
2823                           "{\n"
2824                           "    vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
2825     for (unsigned int i = 0; i < paramCount - 1; ++i)
2826     {
2827         vertexShaderStream << "    sum += a" << i << ";\n";
2828     }
2829     vertexShaderStream << "    sum += aLast;\n"
2830                           "    return sum;\n "
2831                           "}\n"
2832                           "void main()\n"
2833                           "{\n"
2834                           "    gl_Position = lotsOfVec4Parameters(";
2835     for (unsigned int i = 0; i < paramCount - 1; ++i)
2836     {
2837         vertexShaderStream << "a_vec, ";
2838     }
2839     vertexShaderStream << "a_vec);\n"
2840                           "}";
2841 
2842     GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
2843     EXPECT_NE(0u, program);
2844 }
2845 
2846 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
2847 // Test a shader where a global constant array is initialized with an expression containing array
2848 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2849 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
2850 // Also includes multiple array initializers in one declaration, where only the second one has
2851 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
2852 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)2853 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2854 {
2855     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2856     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2857 
2858     constexpr char kFS[] =
2859         "#version 300 es\n"
2860         "precision highp float;\n"
2861         "out vec4 my_FragColor;\n"
2862         "const highp float f[2] = float[2](0.1, 0.2);\n"
2863         "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2864         "void main()\n"
2865         "{\n"
2866         "    my_FragColor = vec4(h[1]);\n"
2867         "}";
2868 
2869     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2870     EXPECT_NE(0u, program);
2871 }
2872 
2873 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)2874 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2875 {
2876     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
2877 
2878     constexpr char kFS[] =
2879         "precision mediump float;\n"
2880         "uniform sampler2D uni[2];\n"
2881         "\n"
2882         "float zero(int x)\n"
2883         "{\n"
2884         "    return float(x) - float(x);\n"
2885         "}\n"
2886         "\n"
2887         "void main()\n"
2888         "{\n"
2889         "    vec4 c = vec4(0,0,0,0);\n"
2890         "    for (int ii = 1; ii < 3; ++ii) {\n"
2891         "        if (c.x > 255.0) {\n"
2892         "            c.x = 255.0 + zero(ii);\n"
2893         "            break;\n"
2894         "        }\n"
2895         // Index the sampler array with a predictable loop index (index-constant) as opposed to
2896         // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2897         // without an extension.
2898         "        c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2899         "    }\n"
2900         "    gl_FragColor = c;\n"
2901         "}";
2902 
2903     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2904     EXPECT_NE(0u, program);
2905 }
2906 
2907 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2908 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2909 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)2910 TEST_P(GLSLTest, PragmaDirective)
2911 {
2912     constexpr char kVS[] =
2913         "#pragma STDGL invariant(all)\n"
2914         "void main()\n"
2915         "{\n"
2916         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2917         "}\n";
2918 
2919     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2920     EXPECT_NE(0u, program);
2921 }
2922 
2923 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2924 // The function call that returns the array needs to be evaluated after ++j for the expression to
2925 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)2926 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2927 {
2928     constexpr char kFS[] =
2929         "#version 300 es\n"
2930         "precision mediump float;\n"
2931         "out vec4 my_FragColor; \n"
2932         "int[2] func(int param) {\n"
2933         "    return int[2](param, param);\n"
2934         "}\n"
2935         "void main() {\n"
2936         "    int a[2]; \n"
2937         "    for (int i = 0; i < 2; ++i) {\n"
2938         "        a[i] = 1;\n"
2939         "    }\n"
2940         "    int j = 0; \n"
2941         "    bool result = ((++j), (a == func(j)));\n"
2942         "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2943         "}\n";
2944 
2945     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2946     ASSERT_NE(0u, program);
2947 
2948     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2949 
2950     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2951 }
2952 
2953 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2954 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2955 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)2956 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2957 {
2958     constexpr char kFS[] =
2959         "#version 300 es\n"
2960         "precision mediump float;\n"
2961         "out vec4 my_FragColor; \n"
2962         "void main() {\n"
2963         "    int j = 0; \n"
2964         "    bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2965         "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2966         "}\n";
2967 
2968     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2969     ASSERT_NE(0u, program);
2970 
2971     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2972 
2973     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2974 }
2975 
2976 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2977 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)2978 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2979 {
2980     constexpr char kFS[] =
2981         "#version 300 es\n"
2982         "precision mediump float;\n"
2983         "out vec4 my_FragColor;\n"
2984         "uniform int u_zero;\n"
2985         "int sideEffectCount = 0;\n"
2986         "float func() {\n"
2987         "    ++sideEffectCount;\n"
2988         "    return -1.0;\n"
2989         "}\n"
2990         "void main() {\n"
2991         "    vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2992         "    float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2993         "    bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2994         "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2995         "}\n";
2996 
2997     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2998     ASSERT_NE(0u, program);
2999 
3000     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3001 
3002     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3003 }
3004 
3005 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3006 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3007 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)3008 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3009 {
3010     constexpr char kVS[] =
3011         "attribute vec2 aPosition;\n"
3012         "void main()\n"
3013         "{\n"
3014         "    gl_Position = vec4(aPosition, 0, 1);\n"
3015         "    gl_PointSize = 1.0;\n"
3016         "}";
3017     constexpr char kFS[] =
3018         "void main()\n"
3019         "{\n"
3020         "    gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3021         "    gl_FragColor = vec4(0, 1, 0, 1);\n"
3022         "}";
3023 
3024     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3025     drawQuad(prog.get(), "aPosition", 0.5f);
3026     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3027 }
3028 
3029 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3030 TEST_P(GLSLTest, NestedPowStatements)
3031 {
3032     // https://crbug.com/1127866 - possible NVIDIA driver issue
3033     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3034 
3035     constexpr char kFS[] =
3036         "precision mediump float;\n"
3037         "float func(float v)\n"
3038         "{\n"
3039         "   float f1 = pow(v, 2.0);\n"
3040         "   return pow(f1 + v, 2.0);\n"
3041         "}\n"
3042         "void main()\n"
3043         "{\n"
3044         "    float v = func(2.0);\n"
3045         "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3046         "}";
3047 
3048     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3049     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3050     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3051 }
3052 
3053 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3054 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3055 {
3056     constexpr char kFS[] =
3057         "#version 300 es\n"
3058         "out highp vec4 o_color;\n"
3059         "void main() {\n"
3060         "    highp float f = -1.0;\n"
3061         "    // atan(tan(0.5), -f) should be 0.5.\n"
3062         "    highp float v = atan(tan(0.5), -f);\n"
3063         "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3064         "}\n";
3065 
3066     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3067     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3068     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3069 }
3070 
3071 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3072 TEST_P(GLSLTest_ES3, AtanVec2)
3073 {
3074     constexpr char kFS[] =
3075         "#version 300 es\n"
3076         "out highp vec4 o_color;\n"
3077         "void main() {\n"
3078         "    highp float f = 1.0;\n"
3079         "    // atan(tan(0.5), f) should be 0.5.\n"
3080         "    highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3081         "    o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3082         "vec4(1, 0, 0, 1);\n"
3083         "}\n";
3084 
3085     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3086     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3087     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3088 }
3089 
3090 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3091 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3092 {
3093     // http://anglebug.com/5242
3094     ANGLE_SKIP_TEST_IF(IsMetal() && IsIntel());
3095 
3096     constexpr char kVS[] =
3097         "#version 300 es\n"
3098         "in highp vec4 position;\n"
3099         "out mediump vec4 v_color;\n"
3100         "uniform int ui_one;\n"
3101         "uniform int ui_two;\n"
3102         "uniform int ui_three;\n"
3103         "void main() {\n"
3104         "    int s[3];\n"
3105         "    s[0] = ui_one;\n"
3106         "    s[1] = -(-(-ui_two + 1) + 1);\n"  // s[1] = -ui_two
3107         "    s[2] = ui_three;\n"
3108         "    int result = 0;\n"
3109         "    for (int i = 0; i < ui_three; i++) {\n"
3110         "        result += s[i];\n"
3111         "    }\n"
3112         "    v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3113         "    gl_Position = position;\n"
3114         "}\n";
3115     constexpr char kFS[] =
3116         "#version 300 es\n"
3117         "in mediump vec4 v_color;\n"
3118         "layout(location=0) out mediump vec4 o_color;\n"
3119         "void main() {\n"
3120         "    o_color = v_color;\n"
3121         "}\n";
3122 
3123     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3124 
3125     GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3126     ASSERT_NE(-1, oneIndex);
3127     GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3128     ASSERT_NE(-1, twoIndex);
3129     GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3130     ASSERT_NE(-1, threeIndex);
3131     glUseProgram(prog.get());
3132     glUniform1i(oneIndex, 1);
3133     glUniform1i(twoIndex, 2);
3134     glUniform1i(threeIndex, 3);
3135 
3136     drawQuad(prog.get(), "position", 0.5f);
3137     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3138 }
3139 
3140 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3141 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3142 {
3143     // http://anglebug.com/5242
3144     ANGLE_SKIP_TEST_IF(IsMetal() && IsIntel());
3145 
3146     constexpr char kVS[] =
3147         "#version 300 es\n"
3148         "in highp vec4 position;\n"
3149         "out mediump vec4 v_color;\n"
3150         "uniform uint ui_one;\n"
3151         "uniform uint ui_two;\n"
3152         "uniform uint ui_three;\n"
3153         "void main() {\n"
3154         "    uint s[3];\n"
3155         "    s[0] = ui_one;\n"
3156         "    s[1] = -(-(-ui_two + 1u) + 1u);\n"  // s[1] = -ui_two
3157         "    s[2] = ui_three;\n"
3158         "    uint result = 0u;\n"
3159         "    for (uint i = 0u; i < ui_three; i++) {\n"
3160         "        result += s[i];\n"
3161         "    }\n"
3162         "    v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3163         "    gl_Position = position;\n"
3164         "}\n";
3165     constexpr char kFS[] =
3166         "#version 300 es\n"
3167         "in mediump vec4 v_color;\n"
3168         "layout(location=0) out mediump vec4 o_color;\n"
3169         "void main() {\n"
3170         "    o_color = v_color;\n"
3171         "}\n";
3172 
3173     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3174 
3175     GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3176     ASSERT_NE(-1, oneIndex);
3177     GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3178     ASSERT_NE(-1, twoIndex);
3179     GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3180     ASSERT_NE(-1, threeIndex);
3181     glUseProgram(prog.get());
3182     glUniform1ui(oneIndex, 1u);
3183     glUniform1ui(twoIndex, 2u);
3184     glUniform1ui(threeIndex, 3u);
3185 
3186     drawQuad(prog.get(), "position", 0.5f);
3187     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3188 }
3189 
3190 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3191 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3192 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3193 {
3194     // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3195     // its default value false.
3196     constexpr char kFS[] =
3197         "precision mediump float;\n"
3198         "uniform bool keep_flop_positive;\n"
3199         "float flop;\n"
3200         "void main() {\n"
3201         "    flop = -1.0,\n"
3202         "    (flop *= -1.0,\n"
3203         "    keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3204         "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
3205         "}";
3206 
3207     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3208     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3209     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3210 }
3211 
3212 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)3213 TEST_P(GLSLTest, ExternalAnd2DSampler)
3214 {
3215     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
3216 
3217     constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
3218 precision mediump float;
3219 uniform samplerExternalOES tex0;
3220 uniform sampler2D tex1;
3221 void main(void)
3222 {
3223     vec2 uv = vec2(0.0, 0.0);
3224     gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
3225 })";
3226 
3227     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3228 }
3229 
3230 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)3231 TEST_P(GLSLTest, VaryingMatrixArray)
3232 {
3233     constexpr char kVS[] =
3234         "uniform vec2 u_a1;\n"
3235         "uniform vec2 u_a2;\n"
3236         "attribute vec4 a_position;\n"
3237         "varying mat2 v_mat[2];\n"
3238         "void main() {\n"
3239         "    v_mat[0] = mat2(u_a1, u_a2);\n"
3240         "    v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
3241         "    gl_Position = a_position;\n"
3242         "}";
3243 
3244     constexpr char kFS[] =
3245         "precision mediump float;\n"
3246         "varying mat2 v_mat[2];\n"
3247         "void main(void)\n"
3248         "{\n"
3249         "    gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
3250         "}";
3251 
3252     ANGLE_GL_PROGRAM(program, kVS, kFS);
3253 
3254     GLint oneIndex = glGetUniformLocation(program, "u_a1");
3255     ASSERT_NE(-1, oneIndex);
3256     GLint twoIndex = glGetUniformLocation(program, "u_a2");
3257     ASSERT_NE(-1, twoIndex);
3258     glUseProgram(program);
3259     glUniform2f(oneIndex, 1, 0.5f);
3260     glUniform2f(twoIndex, 0.25f, 0.125f);
3261 
3262     drawQuad(program, "a_position", 0.5f);
3263     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3264 }
3265 
3266 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)3267 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
3268 {
3269     // TODO(anglebug.com/5491): Skipping initial failures so we can set up a passing iOS test bot.
3270     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
3271 
3272     constexpr char kVS[] =
3273         "#version 300 es\n"
3274         "uniform vec2 u_a1;\n"
3275         "uniform vec2 u_a2;\n"
3276         "in vec4 a_position;\n"
3277         "centroid out mat3x2 v_mat[2];\n"
3278         "void main() {\n"
3279         "    v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
3280         "    v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
3281         "    gl_Position = a_position;\n"
3282         "}";
3283 
3284     constexpr char kFS[] =
3285         "#version 300 es\n"
3286         "precision mediump float;\n"
3287         "centroid in mat3x2 v_mat[2];\n"
3288         "layout(location = 0) out vec4 out_color;\n"
3289         "void main(void)\n"
3290         "{\n"
3291         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
3292         "}";
3293 
3294     ANGLE_GL_PROGRAM(program, kVS, kFS);
3295 
3296     GLint oneIndex = glGetUniformLocation(program, "u_a1");
3297     ASSERT_NE(-1, oneIndex);
3298     GLint twoIndex = glGetUniformLocation(program, "u_a2");
3299     ASSERT_NE(-1, twoIndex);
3300     glUseProgram(program);
3301     glUniform2f(oneIndex, 1, 0.5f);
3302     glUniform2f(twoIndex, 0.25f, 0.125f);
3303 
3304     drawQuad(program, "a_position", 0.5f);
3305     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3306 }
3307 
3308 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)3309 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
3310 {
3311     constexpr char kVS[] =
3312         "#version 300 es\n"
3313         "uniform vec2 u_a1;\n"
3314         "uniform vec2 u_a2;\n"
3315         "in vec4 a_position;\n"
3316         "flat out mat2 v_mat[2];\n"
3317         "void main() {\n"
3318         "    v_mat[0] = mat2(u_a1, u_a2);\n"
3319         "    v_mat[1] = mat2(u_a2, u_a1);\n"
3320         "    gl_Position = a_position;\n"
3321         "}";
3322 
3323     constexpr char kFS[] =
3324         "#version 300 es\n"
3325         "precision mediump float;\n"
3326         "flat in mat2 v_mat[2];\n"
3327         "layout(location = 0) out vec4 out_color;\n"
3328         "void main(void)\n"
3329         "{\n"
3330         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
3331         "}";
3332 
3333     ANGLE_GL_PROGRAM(program, kVS, kFS);
3334 
3335     GLint oneIndex = glGetUniformLocation(program, "u_a1");
3336     ASSERT_NE(-1, oneIndex);
3337     GLint twoIndex = glGetUniformLocation(program, "u_a2");
3338     ASSERT_NE(-1, twoIndex);
3339     glUseProgram(program);
3340     glUniform2f(oneIndex, 1, 0.5f);
3341     glUniform2f(twoIndex, 0.25f, 0.125f);
3342 
3343     drawQuad(program, "a_position", 0.5f);
3344     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
3345 }
3346 
3347 // Test that literal infinity can be written out from the shader translator.
3348 // 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)3349 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
3350 {
3351     constexpr char kFS[] =
3352         "#version 300 es\n"
3353         "precision highp float;\n"
3354         "out vec4 out_color;\n"
3355         "uniform float u;\n"
3356         "void main()\n"
3357         "{\n"
3358         "   float infVar = 1.0e40 - u;\n"
3359         "   bool correct = isinf(infVar) && infVar > 0.0;\n"
3360         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3361         "}\n";
3362 
3363     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3364     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3365     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3366 }
3367 
3368 // Test that literal negative infinity can be written out from the shader translator.
3369 // 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)3370 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
3371 {
3372     constexpr char kFS[] =
3373         "#version 300 es\n"
3374         "precision highp float;\n"
3375         "out vec4 out_color;\n"
3376         "uniform float u;\n"
3377         "void main()\n"
3378         "{\n"
3379         "   float infVar = -1.0e40 + u;\n"
3380         "   bool correct = isinf(infVar) && infVar < 0.0;\n"
3381         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3382         "}\n";
3383 
3384     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3385     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3386     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3387 }
3388 
3389 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
3390 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
3391 // a unittest for them. Instead we add the tests as end2end so will in particular test
3392 // TranslatorHLSL when run on Windows.
3393 
3394 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)3395 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
3396 {
3397     constexpr char kFS[] = R"(#version 300 es
3398 precision mediump float;
3399 out vec4 color;
3400 
3401 uniform float u;
3402 float c = 0.0;
3403 float sideEffect()
3404 {
3405     c = u;
3406     return c;
3407 }
3408 
3409 void main(void)
3410 {
3411     float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
3412     color = vec4(b + c);
3413 })";
3414 
3415     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3416 }
3417 
3418 // Test that passes splitting multiple declarations and comma operators and for loops are
3419 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)3420 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
3421 {
3422     constexpr char kFS[] = R"(#version 300 es
3423 precision mediump float;
3424 out vec4 color;
3425 
3426 uniform float u;
3427 float c = 0.0;
3428 float sideEffect()
3429 {
3430     c = u;
3431     return c;
3432 }
3433 
3434 void main(void)
3435 {
3436     for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
3437     {
3438         b += 1.0;
3439         color = vec4(b);
3440     }
3441 })";
3442 
3443     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3444 }
3445 
3446 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)3447 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
3448 {
3449     constexpr char kFS[] =
3450         "#version 300 es\n"
3451         "precision mediump float;\n"
3452         "out vec4 color;\n"
3453         "void main(void)\n"
3454         "{\n"
3455         " for(float a = 0.0, b = 1.0;; a++)\n"
3456         " {\n"
3457         "  b += 1.0;\n"
3458         "  if (a > 10.0) {break;}\n"
3459         "  color = vec4(b);\n"
3460         " }\n"
3461         "}\n";
3462 
3463     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3464 }
3465 
3466 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)3467 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
3468 {
3469     constexpr char kFS[] =
3470         "#version 300 es\n"
3471         "precision mediump float;\n"
3472         "out vec4 color;\n"
3473         "void main(void)\n"
3474         "{\n"
3475         " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
3476         " {\n"
3477         "  b += 1.0;\n"
3478         "  a += 1.0;\n"
3479         "  color = vec4(b);\n"
3480         " }\n"
3481         "}\n";
3482 
3483     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3484 }
3485 
3486 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
3487 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)3488 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
3489 {
3490     constexpr char kFS[] =
3491         "#version 300 es\n"
3492         "precision mediump float;\n"
3493         "out vec4 my_FragColor;\n"
3494         "uniform int u_zero;\n"
3495         "void main() {\n"
3496         "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
3497         "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
3498         "    float f = m[1][1];\n"
3499         "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
3500         "}\n";
3501 
3502     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3503     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3504     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3505 }
3506 
3507 class WebGLGLSLTest : public GLSLTest
3508 {
3509   protected:
WebGLGLSLTest()3510     WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
3511 };
3512 
3513 class WebGL2GLSLTest : public GLSLTest
3514 {
3515   protected:
WebGL2GLSLTest()3516     WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
3517 };
3518 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)3519 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
3520 {
3521     GLint maxVaryings = 0;
3522     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3523 
3524     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
3525     // This test should fail, since we are really using (maxVaryings + 1) varyings.
3526     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
3527 }
3528 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)3529 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
3530 {
3531     GLint maxVaryings = 0;
3532     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3533 
3534     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
3535     // This test should fail, since we are really using (maxVaryings + 1) varyings.
3536     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
3537 }
3538 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)3539 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
3540 {
3541     GLint maxVaryings = 0;
3542     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3543 
3544     VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
3545 }
3546 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)3547 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
3548 {
3549     GLint maxVaryings = 0;
3550     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3551 
3552     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
3553 }
3554 
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)3555 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
3556 {
3557     GLint maxVaryings = 0;
3558     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3559 
3560     VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
3561 }
3562 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)3563 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
3564 {
3565     GLint maxVaryings = 0;
3566     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3567 
3568     VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
3569 }
3570 
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)3571 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
3572 {
3573     GLint maxVaryings = 0;
3574     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3575 
3576     VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
3577                     false);
3578 }
3579 
3580 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)3581 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
3582 {
3583     // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
3584     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
3585 
3586     // Failing on N5X Oreo http://anglebug.com/2304
3587     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3588 
3589     constexpr char kFS[] =
3590         "#version 310 es\n"
3591         "precision mediump float;\n"
3592         "out vec4 my_FragColor;\n"
3593         "uniform int u_zero;\n"
3594         "void main() {\n"
3595         "    if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
3596         "    {\n"
3597         "        my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3598         "    }\n"
3599         "    else\n"
3600         "    {\n"
3601         "        my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
3602         "    }\n"
3603         "}\n";
3604 
3605     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3606     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3607     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3608 }
3609 
3610 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)3611 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
3612 {
3613     // http://anglebug.com/1924
3614     ANGLE_SKIP_TEST_IF(IsOpenGL());
3615 
3616     // The shader first assigns v.x to v.z (1.0)
3617     // Then v.y to v.y (2.0)
3618     // Then v.z to v.x (1.0)
3619     constexpr char kFS[] =
3620         "#version 300 es\n"
3621         "precision highp float;\n"
3622         "out vec4 my_FragColor;\n"
3623         "void main() {\n"
3624         "    vec3 v = vec3(1.0, 2.0, 3.0);\n"
3625         "    for (int i = 0; i < 3; i++) {\n"
3626         "        v.zyx[i] = v[i];\n"
3627         "    }\n"
3628         "    my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
3629         "0, 0, 1);\n"
3630         "}\n";
3631 
3632     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3633     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3634     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3635 }
3636 
3637 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)3638 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
3639 {
3640     // Crashes on an assertion.  The driver reports no atomic counter buffers when queried from the
3641     // program, but ANGLE believes there to be one.
3642     //
3643     // This is likely due to the fact that ANGLE generates the following code, as a side effect of
3644     // the code on which .length() is being called:
3645     //
3646     //     _uac1[(_uvalue = _utestSideEffectValue)];
3647     //
3648     // The driver is optimizing the subscription out, and calling the atomic counter inactive.  This
3649     // was observed on nvidia, mesa and amd/windows.
3650     //
3651     // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
3652     // driver says don't.
3653     //
3654     // http://anglebug.com/3782
3655     ANGLE_SKIP_TEST_IF(IsOpenGL());
3656 
3657     constexpr char kCS[] = R"(#version 310 es
3658 precision mediump float;
3659 layout(local_size_x=1) in;
3660 
3661 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
3662 uniform uint testSideEffectValue;
3663 
3664 layout(binding = 1, std140) buffer Result
3665 {
3666     uint value;
3667 } result;
3668 
3669 void main() {
3670     bool passed = true;
3671     if (ac1.length() != 2)
3672     {
3673         passed = false;
3674     }
3675     uint value = 0u;
3676     if (ac1[value = testSideEffectValue].length() != 3)
3677     {
3678         passed = false;
3679     }
3680     if (value != testSideEffectValue)
3681     {
3682         passed = false;
3683     }
3684     if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
3685     {
3686         passed = false;
3687     }
3688     if (value != testSideEffectValue + 1u)
3689     {
3690         passed = false;
3691     }
3692     result.value = passed ? 255u : 127u;
3693 })";
3694 
3695     constexpr unsigned int kUniformTestValue     = 17;
3696     constexpr unsigned int kExpectedSuccessValue = 255;
3697     constexpr unsigned int kAtomicCounterRows    = 2;
3698     constexpr unsigned int kAtomicCounterCols    = 3;
3699 
3700     GLint maxAtomicCounters = 0;
3701     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
3702     EXPECT_GL_NO_ERROR();
3703 
3704     // Required minimum is 8 by the spec
3705     EXPECT_GE(maxAtomicCounters, 8);
3706     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
3707                        kAtomicCounterRows * kAtomicCounterCols);
3708 
3709     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3710     glUseProgram(program.get());
3711 
3712     constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
3713     GLBuffer atomicCounterBuffer;
3714     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
3715     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
3716     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
3717 
3718     constexpr unsigned int kOutputInitValue = 0;
3719     GLBuffer shaderStorageBuffer;
3720     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3721     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
3722                  GL_STATIC_DRAW);
3723     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
3724 
3725     GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
3726     EXPECT_NE(uniformLocation, -1);
3727     glUniform1ui(uniformLocation, kUniformTestValue);
3728     EXPECT_GL_NO_ERROR();
3729 
3730     glDispatchCompute(1, 1, 1);
3731 
3732     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3733 
3734     const GLuint *ptr = reinterpret_cast<const GLuint *>(
3735         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
3736     EXPECT_EQ(*ptr, kExpectedSuccessValue);
3737     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3738 }
3739 
3740 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)3741 TEST_P(GLSLTest_ES31, InactiveImages)
3742 {
3743     ANGLE_SKIP_TEST_IF(IsD3D11());
3744 
3745     constexpr char kCS[] = R"(#version 310 es
3746 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3747 layout(rgba32ui) uniform highp readonly uimage2D image1;
3748 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
3749 void main()
3750 {
3751 })";
3752 
3753     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3754 
3755     glUseProgram(program.get());
3756     glDispatchCompute(1, 1, 1);
3757     EXPECT_GL_NO_ERROR();
3758 
3759     // Verify that the images are indeed inactive.
3760     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
3761     EXPECT_GL_NO_ERROR();
3762     EXPECT_EQ(GL_INVALID_INDEX, index);
3763 
3764     index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
3765     EXPECT_GL_NO_ERROR();
3766     EXPECT_EQ(GL_INVALID_INDEX, index);
3767 }
3768 
3769 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)3770 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
3771 {
3772     constexpr char kCS[] = R"(#version 310 es
3773 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3774 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
3775 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
3776 void main()
3777 {
3778 })";
3779 
3780     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3781 
3782     glUseProgram(program.get());
3783     glDispatchCompute(1, 1, 1);
3784     EXPECT_GL_NO_ERROR();
3785 
3786     // Verify that the atomic counters are indeed inactive.
3787     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
3788     EXPECT_GL_NO_ERROR();
3789     EXPECT_EQ(GL_INVALID_INDEX, index);
3790 
3791     index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
3792     EXPECT_GL_NO_ERROR();
3793     EXPECT_EQ(GL_INVALID_INDEX, index);
3794 }
3795 
3796 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)3797 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
3798 {
3799     constexpr char kCS[] = R"(#version 310 es
3800 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3801 struct S
3802 {
3803     vec4 v;
3804     sampler2D t[10];
3805 };
3806 uniform S s;
3807 void main()
3808 {
3809 })";
3810 
3811     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3812 
3813     glUseProgram(program.get());
3814     glDispatchCompute(1, 1, 1);
3815     EXPECT_GL_NO_ERROR();
3816 }
3817 
3818 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)3819 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
3820 {
3821     constexpr char kFS[] =
3822         "#version 310 es\n"
3823         "precision mediump float;\n"
3824         "out vec4 my_FragColor;\n"
3825         "uniform ivec2 test[2][2];\n"
3826         "void main() {\n"
3827         "    bool passed = true;\n"
3828         "    for (int i = 0; i < 2; i++) {\n"
3829         "        for (int j = 0; j < 2; j++) {\n"
3830         "            if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
3831         "                passed = false;\n"
3832         "            }\n"
3833         "        }\n"
3834         "    }\n"
3835         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3836         "}\n";
3837 
3838     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3839     glUseProgram(program.get());
3840     for (int i = 0; i < 2; i++)
3841     {
3842         for (int j = 0; j < 2; j++)
3843         {
3844             std::stringstream uniformName;
3845             uniformName << "test[" << i << "][" << j << "]";
3846             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3847             // All array indices should be used.
3848             EXPECT_NE(uniformLocation, -1);
3849             glUniform2i(uniformLocation, i + 1, j + 1);
3850         }
3851     }
3852     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3853     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3854 }
3855 
3856 // Test that array indices for arrays of arrays of basic types work as expected
3857 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)3858 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
3859 {
3860     // anglebug.com/3821 - fails on AMD Windows
3861     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3862     constexpr char kFS[] =
3863         "#version 310 es\n"
3864         "precision mediump float;\n"
3865         "out vec4 my_FragColor;\n"
3866         "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
3867         "void main() {\n"
3868         "    bool passed = true;\n"
3869         "    for (int i = 0; i < 2; i++) {\n"
3870         "        for (int j = 0; j < 2; j++) {\n"
3871         "            if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
3872         "                passed = false;\n"
3873         "            }\n"
3874         "        }\n"
3875         "    }\n"
3876         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3877         "}\n";
3878 
3879     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3880     glUseProgram(program.get());
3881     // Use interface queries to determine buffer size and offset
3882     GLuint uboBlockIndex   = glGetProgramResourceIndex(program.get(), GL_UNIFORM_BLOCK, "UBO");
3883     GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
3884     GLint uboDataSize;
3885     glGetProgramResourceiv(program.get(), GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
3886                            nullptr, &uboDataSize);
3887     std::unique_ptr<char[]> uboData(new char[uboDataSize]);
3888     for (int i = 0; i < 2; i++)
3889     {
3890         std::stringstream resourceName;
3891         resourceName << "UBO.test[" << i << "][0]";
3892         GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
3893         struct
3894         {
3895             GLint stride;
3896             GLint offset;
3897         } values;
3898         GLuint resourceIndex =
3899             glGetProgramResourceIndex(program.get(), GL_UNIFORM, resourceName.str().c_str());
3900         ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
3901         glGetProgramResourceiv(program.get(), GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2,
3902                                nullptr, &values.stride);
3903         for (int j = 0; j < 2; j++)
3904         {
3905             GLint(&dataPtr)[2] =
3906                 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
3907             dataPtr[0] = i + 1;
3908             dataPtr[1] = j + 1;
3909         }
3910     }
3911     GLBuffer ubo;
3912     glBindBuffer(GL_UNIFORM_BUFFER, ubo.get());
3913     glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
3914     GLuint ubo_index = glGetUniformBlockIndex(program.get(), "UBO");
3915     ASSERT_NE(ubo_index, GL_INVALID_INDEX);
3916     glUniformBlockBinding(program.get(), ubo_index, 5);
3917     glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo.get());
3918     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3919     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3920 }
3921 
3922 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)3923 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
3924 {
3925     constexpr char kFS[] =
3926         "#version 310 es\n"
3927         "precision mediump float;\n"
3928         "out vec4 my_FragColor;\n"
3929         "uniform mediump isampler2D test[2][2];\n"
3930         "void main() {\n"
3931         "    bool passed = true;\n"
3932         "#define DO_CHECK(i,j) \\\n"
3933         "    if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
3934         "        passed = false; \\\n"
3935         "    }\n"
3936         "    DO_CHECK(0, 0)\n"
3937         "    DO_CHECK(0, 1)\n"
3938         "    DO_CHECK(1, 0)\n"
3939         "    DO_CHECK(1, 1)\n"
3940         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3941         "}\n";
3942 
3943     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3944     glUseProgram(program.get());
3945     GLTexture textures[2][2];
3946     for (int i = 0; i < 2; i++)
3947     {
3948         for (int j = 0; j < 2; j++)
3949         {
3950             // First generate the texture
3951             int textureUnit = i * 2 + j;
3952             glActiveTexture(GL_TEXTURE0 + textureUnit);
3953             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
3954             GLint texData[2] = {i + 1, j + 1};
3955             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
3956             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3957             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3958             // Then send it as a uniform
3959             std::stringstream uniformName;
3960             uniformName << "test[" << i << "][" << j << "]";
3961             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3962             // All array indices should be used.
3963             EXPECT_NE(uniformLocation, -1);
3964             glUniform1i(uniformLocation, textureUnit);
3965         }
3966     }
3967     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3968     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3969 }
3970 
3971 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)3972 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
3973 {
3974     // http://anglebug.com/5072
3975     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3976 
3977     // Fails on D3D due to mistranslation.
3978     ANGLE_SKIP_TEST_IF(IsD3D());
3979 
3980     // Fails on Android on GLES.
3981     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3982 
3983     GLint maxTextures, maxComputeImageUniforms;
3984     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
3985     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
3986     ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
3987     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
3988 
3989     constexpr char kComputeShader[] = R"(#version 310 es
3990         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3991         layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
3992         layout(binding = 1, std430) buffer Output {
3993             uint image_value;
3994         } outbuf;
3995 
3996         void main(void)
3997         {
3998             outbuf.image_value = uint(0.0);
3999             outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
4000             outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
4001             outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
4002             outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
4003             outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
4004             outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
4005         })";
4006     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4007     EXPECT_GL_NO_ERROR();
4008 
4009     glUseProgram(program);
4010 
4011     GLuint outputInitData[1] = {10};
4012     GLBuffer outputBuffer;
4013     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4014     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
4015     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
4016     EXPECT_GL_NO_ERROR();
4017 
4018     GLuint imageData = 200u;
4019     GLTexture images[1][2][3];
4020     for (int i = 0; i < 1; i++)
4021     {
4022         for (int j = 0; j < 2; j++)
4023         {
4024             for (int k = 0; k < 3; k++)
4025             {
4026                 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
4027                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4028                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4029                                 &imageData);
4030                 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
4031                                    GL_R32UI);
4032                 EXPECT_GL_NO_ERROR();
4033             }
4034         }
4035     }
4036 
4037     glDispatchCompute(1, 1, 1);
4038     EXPECT_GL_NO_ERROR();
4039 
4040     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4041 
4042     // read back
4043     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4044         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
4045     memcpy(outputInitData, ptr, sizeof(outputInitData));
4046     EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
4047     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4048 }
4049 
4050 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)4051 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
4052 {
4053     // http://anglebug.com/5072
4054     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4055 
4056     // Fails on D3D due to mistranslation.
4057     ANGLE_SKIP_TEST_IF(IsD3D());
4058 
4059     constexpr GLsizei kImage1Layers = 3;
4060     constexpr GLsizei kImage1Rows   = 2;
4061     constexpr GLsizei kImage1Cols   = 1;
4062     constexpr GLsizei kImage2Rows   = 2;
4063     constexpr GLsizei kImage2Cols   = 4;
4064 
4065     constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
4066     constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
4067     constexpr GLsizei kImage3Units = 1;
4068 
4069     constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
4070 
4071     GLint maxTextures, maxComputeImageUniforms;
4072     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4073     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4074     ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
4075     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
4076 
4077     constexpr char kComputeShader[] = R"(#version 310 es
4078         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4079         layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
4080         layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
4081         layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
4082         layout(binding = 0, std430) buffer Output {
4083             uint image_value;
4084         } outbuf;
4085 
4086         void main(void)
4087         {
4088             outbuf.image_value = uint(0.0);
4089 
4090             outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
4091             outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
4092             outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
4093             outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
4094             outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
4095             outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
4096 
4097             outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
4098             outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
4099             outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
4100             outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
4101             outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
4102             outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
4103             outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
4104             outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
4105 
4106             outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
4107         })";
4108     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4109     EXPECT_GL_NO_ERROR();
4110 
4111     glUseProgram(program);
4112 
4113     constexpr GLuint kOutputInitData = 10;
4114     GLBuffer outputBuffer;
4115     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4116     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
4117                  GL_STATIC_DRAW);
4118     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4119     EXPECT_GL_NO_ERROR();
4120 
4121     constexpr GLsizei kImage1Binding = 0;
4122     constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
4123     constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
4124 
4125     constexpr GLuint kImage1Data = 13;
4126     GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
4127     for (int layer = 0; layer < kImage1Layers; layer++)
4128     {
4129         for (int row = 0; row < kImage1Rows; row++)
4130         {
4131             for (int col = 0; col < kImage1Cols; col++)
4132             {
4133                 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
4134                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4135                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4136                                 &kImage1Data);
4137                 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
4138                                    images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
4139                                    GL_R32UI);
4140                 EXPECT_GL_NO_ERROR();
4141             }
4142         }
4143     }
4144 
4145     constexpr GLuint kImage2Data = 17;
4146     GLTexture images2[kImage2Rows][kImage2Cols];
4147     for (int row = 0; row < kImage2Rows; row++)
4148     {
4149         for (int col = 0; col < kImage2Cols; col++)
4150         {
4151             glBindTexture(GL_TEXTURE_2D, images2[row][col]);
4152             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4153             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4154                             &kImage2Data);
4155             glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
4156                                GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4157             EXPECT_GL_NO_ERROR();
4158         }
4159     }
4160 
4161     constexpr GLuint kImage3Data = 19;
4162     GLTexture image3;
4163     glBindTexture(GL_TEXTURE_2D, image3);
4164     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4165     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
4166     glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4167     EXPECT_GL_NO_ERROR();
4168 
4169     glDispatchCompute(1, 1, 1);
4170     EXPECT_GL_NO_ERROR();
4171 
4172     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4173 
4174     // read back
4175     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4176         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4177     EXPECT_EQ(*ptr,
4178               kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
4179     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4180 }
4181 
4182 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)4183 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
4184 {
4185     // Skip if GL_OES_shader_image_atomic is not enabled.
4186     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
4187 
4188     // http://anglebug.com/5072
4189     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4190 
4191     // Fails on D3D due to mistranslation.
4192     ANGLE_SKIP_TEST_IF(IsD3D());
4193 
4194     // Fails on Android on GLES.
4195     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4196 
4197     // http://anglebug.com/5353
4198     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
4199 
4200     GLint maxComputeImageUniforms;
4201     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4202     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
4203 
4204     constexpr char kComputeShader[] = R"(#version 310 es
4205 #extension GL_OES_shader_image_atomic : require
4206 
4207 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4208 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
4209 layout(binding = 6, r32f) uniform highp image2D image2;
4210 
4211 void testFunction(image2D imageOut[2][3])
4212 {
4213     // image1 is an array of 1x1 images.
4214     // image2 is a 1x4 image with the following data:
4215     //
4216     // (0, 0): 234.5
4217     // (0, 1): 4.0
4218     // (0, 2): 456.0
4219     // (0, 3): 987.0
4220 
4221 
4222     // Write to [0][0]
4223     imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
4224 
4225     // Write to [0][1]
4226     imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
4227 
4228     // Write to [0][2]
4229     imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
4230 
4231     // Write to [1][0]
4232     imageStore(imageOut[1][0], ivec2(0,
4233                  imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
4234                 ), vec4(678.0));
4235 
4236     // Write to [1][1]
4237     imageStore(imageOut[1][1], ivec2(0, 0),
4238                 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
4239 
4240     // Write to [1][2]
4241     imageStore(imageOut[1][2], ivec2(0, 0),
4242                     imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
4243 }
4244 
4245 void main(void)
4246 {
4247     testFunction(image1);
4248 })";
4249     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4250     EXPECT_GL_NO_ERROR();
4251 
4252     glUseProgram(program);
4253 
4254     constexpr GLsizei kImageRows = 2;
4255     constexpr GLsizei kImageCols = 3;
4256     constexpr GLfloat kImageData = 0;
4257     GLTexture images[kImageRows][kImageCols];
4258     for (size_t row = 0; row < kImageRows; row++)
4259     {
4260         for (size_t col = 0; col < kImageCols; col++)
4261         {
4262             glBindTexture(GL_TEXTURE_2D, images[row][col]);
4263             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
4264             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
4265             glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
4266                                GL_READ_WRITE, GL_R32F);
4267             EXPECT_GL_NO_ERROR();
4268         }
4269     }
4270 
4271     constexpr GLsizei kImage2Size                          = 4;
4272     constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
4273         234.5f,
4274         4.0f,
4275         456.0f,
4276         987.0f,
4277     };
4278     GLTexture image2;
4279     glBindTexture(GL_TEXTURE_2D, image2);
4280     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
4281     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
4282     glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4283     EXPECT_GL_NO_ERROR();
4284 
4285     glDispatchCompute(1, 1, 1);
4286     EXPECT_GL_NO_ERROR();
4287 
4288     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4289 
4290     // Verify the previous dispatch with another dispatch
4291     constexpr char kVerifyShader[] = R"(#version 310 es
4292 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4293 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
4294 layout(binding = 6, r32f) uniform highp readonly image2D image2;
4295 layout(binding = 0, std430) buffer Output {
4296     float image2Data[4];
4297     float image1Data[6];
4298 } outbuf;
4299 
4300 void main(void)
4301 {
4302     for (int i = 0; i < 4; ++i)
4303     {
4304         outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
4305     }
4306     outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
4307     outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
4308     outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
4309     outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
4310     outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
4311     outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
4312 })";
4313     ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
4314     EXPECT_GL_NO_ERROR();
4315 
4316     glUseProgram(verifyProgram);
4317 
4318     constexpr std::array<GLfloat, kImage2Size + kImageRows *kImageCols> kOutputInitData = {};
4319     GLBuffer outputBuffer;
4320     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4321     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4322                  GL_STATIC_DRAW);
4323     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4324     EXPECT_GL_NO_ERROR();
4325 
4326     glDispatchCompute(1, 1, 1);
4327     EXPECT_GL_NO_ERROR();
4328 
4329     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4330 
4331     // Verify
4332     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
4333         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4334 
4335     EXPECT_EQ(ptr[0], kImage2Data[0]);
4336     EXPECT_EQ(ptr[1], kImage2Data[1]);
4337     EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
4338     EXPECT_EQ(ptr[3], kImage2Data[3]);
4339 
4340     EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
4341     EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
4342     EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
4343     EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
4344     EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
4345     EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
4346 
4347     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4348 }
4349 
4350 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)4351 TEST_P(GLSLTest_ES31, StructArraySampler)
4352 {
4353     constexpr char kFS[] =
4354         "#version 310 es\n"
4355         "precision mediump float;\n"
4356         "out vec4 my_FragColor;\n"
4357         "struct Data { mediump sampler2D data[2]; };\n"
4358         "uniform Data test;\n"
4359         "void main() {\n"
4360         "    my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
4361         "                        texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
4362         "}\n";
4363 
4364     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4365     glUseProgram(program.get());
4366     GLTexture textures[2];
4367     GLColor expected = MakeGLColor(32, 64, 96, 255);
4368     GLubyte data[6]  = {};  // Two bytes of padding, so that texture can be initialized with 4 bytes
4369     memcpy(data, expected.data(), sizeof(expected));
4370     for (int i = 0; i < 2; i++)
4371     {
4372         glActiveTexture(GL_TEXTURE0 + i);
4373         glBindTexture(GL_TEXTURE_2D, textures[i]);
4374         // Each element provides two components.
4375         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
4376         std::stringstream uniformName;
4377         uniformName << "test.data[" << i << "]";
4378         // Then send it as a uniform
4379         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4380         // The uniform should be active.
4381         EXPECT_NE(uniformLocation, -1);
4382         glUniform1i(uniformLocation, i);
4383     }
4384     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4385     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
4386 }
4387 
4388 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)4389 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
4390 {
4391     constexpr char kFS[] =
4392         "#version 310 es\n"
4393         "precision mediump float;\n"
4394         "out vec4 my_FragColor;\n"
4395         "struct Data { mediump isampler2D data[2][2]; };\n"
4396         "uniform Data test;\n"
4397         "void main() {\n"
4398         "    bool passed = true;\n"
4399         "#define DO_CHECK(i,j) \\\n"
4400         "    if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4401         "        passed = false; \\\n"
4402         "    }\n"
4403         "    DO_CHECK(0, 0)\n"
4404         "    DO_CHECK(0, 1)\n"
4405         "    DO_CHECK(1, 0)\n"
4406         "    DO_CHECK(1, 1)\n"
4407         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4408         "}\n";
4409 
4410     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4411     glUseProgram(program.get());
4412     GLTexture textures[2][2];
4413     for (int i = 0; i < 2; i++)
4414     {
4415         for (int j = 0; j < 2; j++)
4416         {
4417             // First generate the texture
4418             int textureUnit = i * 2 + j;
4419             glActiveTexture(GL_TEXTURE0 + textureUnit);
4420             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4421             GLint texData[2] = {i + 1, j + 1};
4422             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4423             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4424             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4425             // Then send it as a uniform
4426             std::stringstream uniformName;
4427             uniformName << "test.data[" << i << "][" << j << "]";
4428             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4429             // All array indices should be used.
4430             EXPECT_NE(uniformLocation, -1);
4431             glUniform1i(uniformLocation, textureUnit);
4432         }
4433     }
4434     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4435     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4436 }
4437 
4438 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)4439 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
4440 {
4441     GLint numTextures;
4442     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4443     ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
4444     constexpr char kFS[] =
4445         "#version 310 es\n"
4446         "precision mediump float;\n"
4447         "out vec4 my_FragColor;\n"
4448         "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
4449         "uniform Data test[2];\n"
4450         "void main() {\n"
4451         "    bool passed = true;\n"
4452         "#define DO_CHECK_ikl(i,k,l) \\\n"
4453         "    if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
4454         "        passed = false; \\\n"
4455         "    } \\\n"
4456         "    if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
4457         "        passed = false; \\\n"
4458         "    }\n"
4459         "#define DO_CHECK_ik(i,k) \\\n"
4460         "    DO_CHECK_ikl(i, k, 0) \\\n"
4461         "    DO_CHECK_ikl(i, k, 1)\n"
4462         "#define DO_CHECK_i(i) \\\n"
4463         "    DO_CHECK_ik(i, 0) \\\n"
4464         "    DO_CHECK_ik(i, 1)\n"
4465         "    DO_CHECK_i(0)\n"
4466         "    DO_CHECK_i(1)\n"
4467         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4468         "}\n";
4469 
4470     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4471     glUseProgram(program.get());
4472     GLTexture textures[2][2][2][2];
4473     for (int i = 0; i < 2; i++)
4474     {
4475         for (int j = 0; j < 2; j++)
4476         {
4477             for (int k = 0; k < 2; k++)
4478             {
4479                 for (int l = 0; l < 2; l++)
4480                 {
4481                     // First generate the texture
4482                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
4483                     glActiveTexture(GL_TEXTURE0 + textureUnit);
4484                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
4485                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
4486                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4487                                  &texData[0]);
4488                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4489                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4490                     // Then send it as a uniform
4491                     std::stringstream uniformName;
4492                     uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
4493                     GLint uniformLocation =
4494                         glGetUniformLocation(program.get(), uniformName.str().c_str());
4495                     // All array indices should be used.
4496                     EXPECT_NE(uniformLocation, -1);
4497                     glUniform1i(uniformLocation, textureUnit);
4498                 }
4499             }
4500         }
4501     }
4502     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4503     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4504 }
4505 
4506 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)4507 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
4508 {
4509     GLint numTextures;
4510     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4511     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
4512     constexpr char kFS[] =
4513         "#version 310 es\n"
4514         "precision mediump float;\n"
4515         "out vec4 my_FragColor;\n"
4516         "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
4517         "uniform Data test[2][3];\n"
4518         "const vec2 ZERO = vec2(0.0, 0.0);\n"
4519         "void main() {\n"
4520         "    bool passed = true;\n"
4521         "#define DO_CHECK_INNER0(i,j,l) \\\n"
4522         "    if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
4523         "        passed = false; \\\n"
4524         "    }\n"
4525         "#define DO_CHECK_INNER1(i,j,l) \\\n"
4526         "    if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
4527         "        passed = false; \\\n"
4528         "    }\n"
4529         "#define DO_CHECK(i,j) \\\n"
4530         "    DO_CHECK_INNER0(i, j, 0) \\\n"
4531         "    DO_CHECK_INNER0(i, j, 1) \\\n"
4532         "    DO_CHECK_INNER1(i, j, 0) \\\n"
4533         "    DO_CHECK_INNER1(i, j, 1) \\\n"
4534         "    DO_CHECK_INNER1(i, j, 2)\n"
4535         "    DO_CHECK(0, 0)\n"
4536         "    DO_CHECK(0, 1)\n"
4537         "    DO_CHECK(0, 2)\n"
4538         "    DO_CHECK(1, 0)\n"
4539         "    DO_CHECK(1, 1)\n"
4540         "    DO_CHECK(1, 2)\n"
4541         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4542         "}\n";
4543 
4544     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4545     glUseProgram(program.get());
4546     struct Data
4547     {
4548         GLTexture data1[2];
4549         GLTexture data2[3];
4550     };
4551     Data textures[2][3];
4552     for (int i = 0; i < 2; i++)
4553     {
4554         for (int j = 0; j < 3; j++)
4555         {
4556             GLTexture *arrays[]     = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
4557             size_t arrayLengths[]   = {2, 3};
4558             size_t arrayOffsets[]   = {0, 2};
4559             size_t totalArrayLength = 5;
4560             for (int k = 0; k < 2; k++)
4561             {
4562                 GLTexture *array   = arrays[k];
4563                 size_t arrayLength = arrayLengths[k];
4564                 size_t arrayOffset = arrayOffsets[k];
4565                 for (int l = 0; l < static_cast<int>(arrayLength); l++)
4566                 {
4567                     // First generate the texture
4568                     int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
4569                     glActiveTexture(GL_TEXTURE0 + textureUnit);
4570                     glBindTexture(GL_TEXTURE_2D, array[l]);
4571                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
4572                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4573                                  &texData[0]);
4574                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4575                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4576                     // Then send it as a uniform
4577                     std::stringstream uniformName;
4578                     uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
4579                     GLint uniformLocation =
4580                         glGetUniformLocation(program.get(), uniformName.str().c_str());
4581                     // All array indices should be used.
4582                     EXPECT_NE(uniformLocation, -1);
4583                     glUniform1i(uniformLocation, textureUnit);
4584                 }
4585             }
4586         }
4587     }
4588     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4589     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4590 }
4591 
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)4592 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
4593 {
4594     GLint numTextures;
4595     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4596     ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
4597     constexpr char kFS[] =
4598         "#version 310 es\n"
4599         "precision mediump float;\n"
4600         "out vec4 my_FragColor;\n"
4601         "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
4602         "uniform Data test[3];\n"
4603         "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
4604         "void main() {\n"
4605         "    bool passed = true;\n"
4606         "#define DO_CHECK_ik(i,k) \\\n"
4607         "    if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
4608         "        passed = false; \\\n"
4609         "    } \\\n"
4610         "    if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
4611         "        passed = false; \\\n"
4612         "    }\n"
4613         "#define DO_CHECK_i(i) \\\n"
4614         "    DO_CHECK_ik(i, 0) \\\n"
4615         "    DO_CHECK_ik(i, 1)\n"
4616         "    DO_CHECK_i(0)\n"
4617         "    DO_CHECK_i(1)\n"
4618         "    DO_CHECK_i(2)\n"
4619         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4620         "}\n";
4621 
4622     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4623     glUseProgram(program.get());
4624     GLTexture textures[3][2][2];
4625     for (int i = 0; i < 3; i++)
4626     {
4627         for (int j = 0; j < 2; j++)
4628         {
4629             for (int k = 0; k < 2; k++)
4630             {
4631                 // First generate the texture
4632                 int textureUnit = k + 2 * (j + 2 * i);
4633                 glActiveTexture(GL_TEXTURE0 + textureUnit);
4634                 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
4635                 GLint texData[4]        = {i + 1, j + 1, k + 1, 1};
4636                 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
4637                                            static_cast<GLubyte>((j + 1) * 64 - 1),
4638                                            static_cast<GLubyte>((k + 1) * 64 - 1), 64};
4639                 if (j == 0)
4640                 {
4641                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4642                                  &texData[0]);
4643                 }
4644                 else
4645                 {
4646                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4647                                  &texDataFloat[0]);
4648                 }
4649                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4650                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4651                 // Then send it as a uniform
4652                 std::stringstream uniformName;
4653                 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
4654                 GLint uniformLocation =
4655                     glGetUniformLocation(program.get(), uniformName.str().c_str());
4656                 // All array indices should be used.
4657                 EXPECT_NE(uniformLocation, -1);
4658                 glUniform1i(uniformLocation, textureUnit);
4659             }
4660         }
4661     }
4662     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4663     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4664 }
4665 
4666 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)4667 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
4668 {
4669     // anglebug.com/3832 - no sampler array params on Android
4670     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4671 
4672     constexpr char kFS[] =
4673         "#version 310 es\n"
4674         "precision mediump float;\n"
4675         "out vec4 my_FragColor;\n"
4676         "uniform mediump isampler2D test[2][3];\n"
4677         "const vec2 ZERO = vec2(0.0, 0.0);\n"
4678         "\n"
4679         "bool check(isampler2D data[2][3]);\n"
4680         "bool check(isampler2D data[2][3]) {\n"
4681         "#define DO_CHECK(i,j) \\\n"
4682         "    if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
4683         "        return false; \\\n"
4684         "    }\n"
4685         "    DO_CHECK(0, 0)\n"
4686         "    DO_CHECK(0, 1)\n"
4687         "    DO_CHECK(0, 2)\n"
4688         "    DO_CHECK(1, 0)\n"
4689         "    DO_CHECK(1, 1)\n"
4690         "    DO_CHECK(1, 2)\n"
4691         "    return true;\n"
4692         "}\n"
4693         "void main() {\n"
4694         "    bool passed = check(test);\n"
4695         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4696         "}\n";
4697 
4698     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4699     glUseProgram(program.get());
4700     GLTexture textures[2][3];
4701     for (int i = 0; i < 2; i++)
4702     {
4703         for (int j = 0; j < 3; j++)
4704         {
4705             // First generate the texture
4706             int textureUnit = i * 3 + j;
4707             glActiveTexture(GL_TEXTURE0 + textureUnit);
4708             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4709             GLint texData[2] = {i + 1, j + 1};
4710             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4711             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4712             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4713             // Then send it as a uniform
4714             std::stringstream uniformName;
4715             uniformName << "test[" << i << "][" << j << "]";
4716             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4717             // All array indices should be used.
4718             EXPECT_NE(uniformLocation, -1);
4719             glUniform1i(uniformLocation, textureUnit);
4720         }
4721     }
4722     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4723     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4724 }
4725 
4726 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)4727 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
4728 {
4729     // anglebug.com/3832 - no sampler array params on Android
4730     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4731 
4732     constexpr char kFS[] =
4733         "#version 310 es\n"
4734         "precision mediump float;\n"
4735         "out vec4 my_FragColor;\n"
4736         "struct Data { mediump isampler2D data[2][3]; };\n"
4737         "uniform Data test;\n"
4738         "const vec2 ZERO = vec2(0.0, 0.0);\n"
4739         "\n"
4740         "bool check(Data data) {\n"
4741         "#define DO_CHECK(i,j) \\\n"
4742         "    if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
4743         "        return false; \\\n"
4744         "    }\n"
4745         "    DO_CHECK(0, 0)\n"
4746         "    DO_CHECK(0, 1)\n"
4747         "    DO_CHECK(0, 2)\n"
4748         "    DO_CHECK(1, 0)\n"
4749         "    DO_CHECK(1, 1)\n"
4750         "    DO_CHECK(1, 2)\n"
4751         "    return true;\n"
4752         "}\n"
4753         "void main() {\n"
4754         "    bool passed = check(test);\n"
4755         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4756         "}\n";
4757 
4758     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4759     glUseProgram(program.get());
4760     GLTexture textures[2][3];
4761     for (int i = 0; i < 2; i++)
4762     {
4763         for (int j = 0; j < 3; j++)
4764         {
4765             // First generate the texture
4766             int textureUnit = i * 3 + j;
4767             glActiveTexture(GL_TEXTURE0 + textureUnit);
4768             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4769             GLint texData[2] = {i + 1, j + 1};
4770             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4771             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4772             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4773             // Then send it as a uniform
4774             std::stringstream uniformName;
4775             uniformName << "test.data[" << i << "][" << j << "]";
4776             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4777             // All array indices should be used.
4778             EXPECT_NE(uniformLocation, -1);
4779             glUniform1i(uniformLocation, textureUnit);
4780         }
4781     }
4782     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4783     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4784 }
4785 
4786 // Test that arrays of arrays of structs with arrays of arrays of samplers
4787 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)4788 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
4789 {
4790     // anglebug.com/3832 - no sampler array params on Android
4791     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4792 
4793     GLint numTextures;
4794     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4795     ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
4796     constexpr char kFS[] =
4797         "#version 310 es\n"
4798         "precision mediump float;\n"
4799         "out vec4 my_FragColor;\n"
4800         "struct Data { mediump isampler2D data[2][2]; };\n"
4801         "uniform Data test[3][2];\n"
4802         "const vec2 ZERO = vec2(0.0, 0.0);\n"
4803         "\n"
4804         "bool check(Data data[3][2]) {\n"
4805         "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
4806         "    if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
4807         "        return false; \\\n"
4808         "    }\n"
4809         "#define DO_CHECK_ij(i,j) \\\n"
4810         "    DO_CHECK_ijkl(i, j, 0, 0) \\\n"
4811         "    DO_CHECK_ijkl(i, j, 0, 1) \\\n"
4812         "    DO_CHECK_ijkl(i, j, 1, 0) \\\n"
4813         "    DO_CHECK_ijkl(i, j, 1, 1)\n"
4814         "    DO_CHECK_ij(0, 0)\n"
4815         "    DO_CHECK_ij(1, 0)\n"
4816         "    DO_CHECK_ij(2, 0)\n"
4817         "    DO_CHECK_ij(0, 1)\n"
4818         "    DO_CHECK_ij(1, 1)\n"
4819         "    DO_CHECK_ij(2, 1)\n"
4820         "    return true;\n"
4821         "}\n"
4822         "void main() {\n"
4823         "    bool passed = check(test);\n"
4824         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4825         "}\n";
4826 
4827     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4828     glUseProgram(program.get());
4829     GLTexture textures[3][2][2][2];
4830     for (int i = 0; i < 3; i++)
4831     {
4832         for (int j = 0; j < 2; j++)
4833         {
4834             for (int k = 0; k < 2; k++)
4835             {
4836                 for (int l = 0; l < 2; l++)
4837                 {
4838                     // First generate the texture
4839                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
4840                     glActiveTexture(GL_TEXTURE0 + textureUnit);
4841                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
4842                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
4843                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4844                                  &texData[0]);
4845                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4846                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4847                     // Then send it as a uniform
4848                     std::stringstream uniformName;
4849                     uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
4850                     GLint uniformLocation =
4851                         glGetUniformLocation(program.get(), uniformName.str().c_str());
4852                     // All array indices should be used.
4853                     EXPECT_NE(uniformLocation, -1);
4854                     glUniform1i(uniformLocation, textureUnit);
4855                 }
4856             }
4857         }
4858     }
4859     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4860     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4861 }
4862 
4863 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)4864 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
4865 {
4866     GLint numTextures;
4867     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4868     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
4869 
4870     // anglebug.com/3832 - no sampler array params on Android
4871     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4872 
4873     // http://anglebug.com/5546
4874     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
4875 
4876     constexpr char kFS[] =
4877         "#version 310 es\n"
4878         "precision mediump float;\n"
4879         "out vec4 my_FragColor;\n"
4880         "uniform mediump isampler2D test[2][3][4];\n"
4881         "uniform mediump isampler2D test2[4];\n"
4882         "const vec2 ZERO = vec2(0.0, 0.0);\n"
4883         "\n"
4884         "bool check1D(isampler2D arr[4], int x, int y) {\n"
4885         "    if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
4886         "    if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
4887         "    if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
4888         "    if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
4889         "    return true;\n"
4890         "}\n"
4891         "bool check2D(isampler2D arr[3][4], int x) {\n"
4892         "    if (!check1D(arr[0], x, 0)) return false;\n"
4893         "    if (!check1D(arr[1], x, 1)) return false;\n"
4894         "    if (!check1D(arr[2], x, 2)) return false;\n"
4895         "    return true;\n"
4896         "}\n"
4897         "bool check3D(isampler2D arr[2][3][4]) {\n"
4898         "    if (!check2D(arr[0], 0)) return false;\n"
4899         "    if (!check2D(arr[1], 1)) return false;\n"
4900         "    return true;\n"
4901         "}\n"
4902         "void main() {\n"
4903         "    bool passed = check3D(test) && check1D(test2, 7, 8);\n"
4904         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4905         "}\n";
4906 
4907     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4908     glUseProgram(program.get());
4909     GLTexture textures1[2][3][4];
4910     GLTexture textures2[4];
4911     for (int i = 0; i < 2; i++)
4912     {
4913         for (int j = 0; j < 3; j++)
4914         {
4915             for (int k = 0; k < 4; k++)
4916             {
4917                 // First generate the texture
4918                 int textureUnit = k + 4 * (j + 3 * i);
4919                 glActiveTexture(GL_TEXTURE0 + textureUnit);
4920                 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
4921                 GLint texData[3] = {i + 1, j + 1, k + 1};
4922                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
4923                              &texData[0]);
4924                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4925                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4926                 // Then send it as a uniform
4927                 std::stringstream uniformName;
4928                 uniformName << "test[" << i << "][" << j << "][" << k << "]";
4929                 GLint uniformLocation =
4930                     glGetUniformLocation(program.get(), uniformName.str().c_str());
4931                 // All array indices should be used.
4932                 EXPECT_NE(uniformLocation, -1);
4933                 glUniform1i(uniformLocation, textureUnit);
4934             }
4935         }
4936     }
4937     for (int k = 0; k < 4; k++)
4938     {
4939         // First generate the texture
4940         int textureUnit = 2 * 3 * 4 + k;
4941         glActiveTexture(GL_TEXTURE0 + textureUnit);
4942         glBindTexture(GL_TEXTURE_2D, textures2[k]);
4943         GLint texData[3] = {7 + 1, 8 + 1, k + 1};
4944         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
4945         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4946         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4947         // Then send it as a uniform
4948         std::stringstream uniformName;
4949         uniformName << "test2[" << k << "]";
4950         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4951         // All array indices should be used.
4952         EXPECT_NE(uniformLocation, -1);
4953         glUniform1i(uniformLocation, textureUnit);
4954     }
4955     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4956     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4957 }
4958 
4959 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)4960 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
4961 {
4962     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/3604 - rewriter can create name collisions
4963     GLint numTextures;
4964     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4965     ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
4966     // anglebug.com/3832 - no sampler array params on Android
4967     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4968     constexpr char kFS[] =
4969         "#version 310 es\n"
4970         "precision mediump sampler2D;\n"
4971         "precision mediump float;\n"
4972         "uniform sampler2D test_field1_field2[2][2];\n"
4973         "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
4974         "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
4975         "vec4 func1(sampler2D param_field1_field2[2][2],\n"
4976         "           int param_field1_field2_offset,\n"
4977         "           S1 param_field1,\n"
4978         "           S2 param) {\n"
4979         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
4980         "}\n"
4981         "out vec4 my_FragColor;\n"
4982         "void main() {\n"
4983         "    my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
4984         "    my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
4985         "    vec2 uv = vec2(0.0);\n"
4986         "    my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
4987         "                    texture(test_field1.field2[0][0], uv) +\n"
4988         "                    texture(test.field1_field2[0][0], uv);\n"
4989         "}\n";
4990     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4991     glActiveTexture(GL_TEXTURE0);
4992     GLTexture tex;
4993     glBindTexture(GL_TEXTURE_2D, tex);
4994     GLint zero = 0;
4995     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
4996     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4997     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4998 }
4999 
5000 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)5001 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
5002 {
5003     constexpr char kFS[] =
5004         "#version 310 es\n"
5005         "precision mediump sampler2D;\n"
5006         "precision mediump float;\n"
5007         "uniform sampler2D sampler_array[2][2];\n"
5008         "uniform int array[3][2];\n"
5009         "vec4 func1(int param[2],\n"
5010         "           int param2[3]) {\n"
5011         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
5012         "}\n"
5013         "out vec4 my_FragColor;\n"
5014         "void main() {\n"
5015         "    my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
5016         "    my_FragColor += func1(array[1], int[](1, 2, 3));\n"
5017         "}\n";
5018     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5019     glActiveTexture(GL_TEXTURE0);
5020     GLTexture tex;
5021     glBindTexture(GL_TEXTURE_2D, tex);
5022     GLint zero = 0;
5023     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
5024     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5025     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5026 }
5027 
5028 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
5029 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)5030 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
5031 {
5032     // This seems to be bugged on some version of Android. Might not affect the newest versions.
5033     // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
5034     // Test skipped on Android because of bug with Nexus 5X.
5035     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5036 
5037     constexpr char kVS[] =
5038         "#version 300 es\n"
5039         "out vec2 texCoord;\n"
5040         "in vec2 position;\n"
5041         "void main()\n"
5042         "{\n"
5043         "    gl_Position = vec4(position, 0, 1);\n"
5044         "    texCoord = position * 0.5 + vec2(0.5);\n"
5045         "}\n";
5046 
5047     constexpr char kSimpleFS[] =
5048         "#version 300 es\n"
5049         "in mediump vec2 texCoord;\n"
5050         "out mediump vec4 fragColor;\n"
5051         "void main()\n"
5052         "{\n"
5053         "    fragColor = vec4(texCoord, 0, 1);\n"
5054         "}\n";
5055 
5056     constexpr char kNestedFS[] =
5057         "#version 300 es\n"
5058         "uniform mediump sampler2D samplerA;\n"
5059         "uniform mediump sampler2D samplerB;\n"
5060         "in mediump vec2 texCoord;\n"
5061         "out mediump vec4 fragColor;\n"
5062         "void main ()\n"
5063         "{\n"
5064         "    fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
5065         "}\n";
5066 
5067     ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
5068     ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
5069 
5070     // Initialize a first texture with default texCoord data.
5071     GLTexture texA;
5072     glActiveTexture(GL_TEXTURE0);
5073     glBindTexture(GL_TEXTURE_2D, texA);
5074     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
5075                  GL_UNSIGNED_BYTE, nullptr);
5076     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5077     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5078 
5079     GLFramebuffer fbo;
5080     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5081     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
5082 
5083     drawQuad(initProg, "position", 0.5f);
5084     ASSERT_GL_NO_ERROR();
5085 
5086     // Initialize a second texture with a simple color pattern.
5087     GLTexture texB;
5088     glActiveTexture(GL_TEXTURE1);
5089     glBindTexture(GL_TEXTURE_2D, texB);
5090 
5091     std::array<GLColor, 4> simpleColors = {
5092         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5093     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5094                  simpleColors.data());
5095     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5096     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5097 
5098     // Draw with the nested program, using the first texture to index the second.
5099     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5100     glUseProgram(nestedProg);
5101     GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
5102     ASSERT_NE(-1, samplerALoc);
5103     glUniform1i(samplerALoc, 0);
5104     GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
5105     ASSERT_NE(-1, samplerBLoc);
5106     glUniform1i(samplerBLoc, 1);
5107 
5108     drawQuad(nestedProg, "position", 0.5f);
5109     ASSERT_GL_NO_ERROR();
5110 
5111     // Compute four texel centers.
5112     Vector2 windowSize(getWindowWidth(), getWindowHeight());
5113     Vector2 quarterWindowSize = windowSize / 4;
5114     Vector2 ul                = quarterWindowSize;
5115     Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
5116     Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
5117     Vector2 lr = windowSize - quarterWindowSize;
5118 
5119     EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
5120     EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
5121     EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
5122     EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
5123 }
5124 
5125 // Tests that using a constant declaration as the only statement in a for loop without curly braces
5126 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)5127 TEST_P(GLSLTest, ConstantStatementInForLoop)
5128 {
5129     constexpr char kVS[] =
5130         "void main()\n"
5131         "{\n"
5132         "    for (int i = 0; i < 10; ++i)\n"
5133         "        const int b = 0;\n"
5134         "}\n";
5135 
5136     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5137     EXPECT_NE(0u, shader);
5138     glDeleteShader(shader);
5139 }
5140 
5141 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
5142 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)5143 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
5144 {
5145     constexpr char kVS[] =
5146         "void main()\n"
5147         "{\n"
5148         "    for (const int i = 0; i < 0;) {}\n"
5149         "}\n";
5150 
5151     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5152     EXPECT_NE(0u, shader);
5153     glDeleteShader(shader);
5154 }
5155 
5156 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)5157 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
5158 {
5159     // Test skipped on Android GLES because local variable initialization is disabled.
5160     // http://anglebug.com/2046
5161     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5162 
5163     constexpr char kFS[] =
5164         "#version 300 es\n"
5165         "precision mediump float;\n"
5166         "out vec4 my_FragColor;\n"
5167         "int result = 0;\n"
5168         "void main()\n"
5169         "{\n"
5170         "    int u;\n"
5171         "    result += u;\n"
5172         "    int k = 0;\n"
5173         "    for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
5174         "    {\n"
5175         "        result += j;\n"
5176         "    }\n"
5177         "    if (result == 2)\n"
5178         "    {\n"
5179         "        my_FragColor = vec4(0, 1, 0, 1);\n"
5180         "    }\n"
5181         "    else\n"
5182         "    {\n"
5183         "        my_FragColor = vec4(1, 0, 0, 1);\n"
5184         "    }\n"
5185         "}\n";
5186 
5187     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5188 
5189     // [WebGL 1.0]
5190     // DrawArrays or drawElements will generate an INVALID_OPERATION error
5191     // if a vertex attribute is enabled as an array via enableVertexAttribArray
5192     // but no buffer is bound to that attribute.
5193     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5194     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5195 }
5196 
5197 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
5198 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)5199 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
5200 {
5201     // Test skipped on Android GLES because local variable initialization is disabled.
5202     // http://anglebug.com/2046
5203     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5204 
5205     constexpr char kFS[] =
5206         "precision mediump float;\n"
5207         "struct T\n"
5208         "{\n"
5209         "    int a[2];\n"
5210         "};\n"
5211         "struct S\n"
5212         "{\n"
5213         "    T t[2];\n"
5214         "};\n"
5215         "void main()\n"
5216         "{\n"
5217         "    S s;\n"
5218         "    S s2;\n"
5219         "    if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
5220         "    {\n"
5221         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
5222         "    }\n"
5223         "    else\n"
5224         "    {\n"
5225         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
5226         "    }\n"
5227         "}\n";
5228 
5229     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5230     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5231     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5232 }
5233 
5234 // Verify that two shaders with the same uniform name and members but different structure names will
5235 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)5236 TEST_P(GLSLTest, StructureNameMatchingTest)
5237 {
5238     const char *vsSource =
5239         "// Structures must have the same name, sequence of type names, and\n"
5240         "// type definitions, and field names to be considered the same type.\n"
5241         "// GLSL 1.017 4.2.4\n"
5242         "precision mediump float;\n"
5243         "struct info {\n"
5244         "  vec4 pos;\n"
5245         "  vec4 color;\n"
5246         "};\n"
5247         "\n"
5248         "uniform info uni;\n"
5249         "void main()\n"
5250         "{\n"
5251         "    gl_Position = uni.pos;\n"
5252         "}\n";
5253 
5254     GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
5255     ASSERT_NE(0u, vs);
5256     glDeleteShader(vs);
5257 
5258     const char *fsSource =
5259         "// Structures must have the same name, sequence of type names, and\n"
5260         "// type definitions, and field names to be considered the same type.\n"
5261         "// GLSL 1.017 4.2.4\n"
5262         "precision mediump float;\n"
5263         "struct info1 {\n"
5264         "  vec4 pos;\n"
5265         "  vec4 color;\n"
5266         "};\n"
5267         "\n"
5268         "uniform info1 uni;\n"
5269         "void main()\n"
5270         "{\n"
5271         "    gl_FragColor = uni.color;\n"
5272         "}\n";
5273 
5274     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
5275     ASSERT_NE(0u, fs);
5276     glDeleteShader(fs);
5277 
5278     GLuint program = CompileProgram(vsSource, fsSource);
5279     EXPECT_EQ(0u, program);
5280 }
5281 
5282 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)5283 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
5284 {
5285     // Test skipped on Android GLES because local variable initialization is disabled.
5286     // http://anglebug.com/2046
5287     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5288 
5289     constexpr char kFS[] =
5290         "#version 300 es\n"
5291         "precision highp float;\n"
5292         "out vec4 my_FragColor;\n"
5293         "void main()\n"
5294         "{\n"
5295         "    my_FragColor = vec4(1, 0, 0, 1);\n"
5296         "    for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
5297         "        my_FragColor = vec4(0, 1, 0, 1);\n"
5298         "    }\n"
5299         "}\n";
5300 
5301     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5302     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5303     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5304 }
5305 
5306 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)5307 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
5308 {
5309     // http://anglebug.com/2862
5310     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
5311 
5312     constexpr char kFS[] =
5313         "precision mediump float;\n"
5314         "int result;\n"
5315         "int i[2], j = i[0] + 1;\n"
5316         "void main()\n"
5317         "{\n"
5318         "    result += j;\n"
5319         "    if (result == 1)\n"
5320         "    {\n"
5321         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
5322         "    }\n"
5323         "    else\n"
5324         "    {\n"
5325         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
5326         "    }\n"
5327         "}\n";
5328 
5329     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5330     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5331     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5332 }
5333 
5334 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)5335 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
5336 {
5337     constexpr char kFS[] =
5338         "precision mediump float;\n"
5339         "struct { float q; } b;\n"
5340         "void main()\n"
5341         "{\n"
5342         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
5343         "    if (b.q == 0.0)\n"
5344         "    {\n"
5345         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
5346         "    }\n"
5347         "}\n";
5348 
5349     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5350     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5351     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5352 }
5353 
5354 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)5355 TEST_P(GLSLTest, EmbeddedStructUniform)
5356 {
5357     const char kFragmentShader[] = R"(precision mediump float;
5358 uniform struct { float q; } b;
5359 void main()
5360 {
5361     gl_FragColor = vec4(1, 0, 0, 1);
5362     if (b.q == 0.5)
5363     {
5364         gl_FragColor = vec4(0, 1, 0, 1);
5365     }
5366 })";
5367 
5368     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5369     glUseProgram(program);
5370     GLint uniLoc = glGetUniformLocation(program, "b.q");
5371     ASSERT_NE(-1, uniLoc);
5372     glUniform1f(uniLoc, 0.5f);
5373 
5374     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5375     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5376 }
5377 
5378 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)5379 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
5380 {
5381     const char kVertexShader[] = R"(attribute vec2 position;
5382 varying vec2 texCoord;
5383 void main()
5384 {
5385     gl_Position = vec4(position, 0, 1);
5386     texCoord = position * 0.5 + vec2(0.5);
5387 })";
5388 
5389     const char kFragmentShader[] = R"(precision mediump float;
5390 struct S { sampler2D samp; bool b; };
5391 uniform S uni;
5392 varying vec2 texCoord;
5393 void main()
5394 {
5395     if (uni.b)
5396     {
5397         gl_FragColor = texture2D(uni.samp, texCoord);
5398     }
5399     else
5400     {
5401         gl_FragColor = vec4(1, 0, 0, 1);
5402     }
5403 })";
5404 
5405     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
5406     glUseProgram(program);
5407 
5408     GLint bLoc = glGetUniformLocation(program, "uni.b");
5409     ASSERT_NE(-1, bLoc);
5410     GLint sampLoc = glGetUniformLocation(program, "uni.samp");
5411     ASSERT_NE(-1, sampLoc);
5412 
5413     glUniform1i(bLoc, 1);
5414 
5415     std::array<GLColor, 4> kGreenPixels = {
5416         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
5417 
5418     GLTexture tex;
5419     glBindTexture(GL_TEXTURE_2D, tex);
5420     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5421                  kGreenPixels.data());
5422     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5423     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5424     ASSERT_GL_NO_ERROR();
5425 
5426     drawQuad(program, "position", 0.5f);
5427     ASSERT_GL_NO_ERROR();
5428 
5429     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5430 }
5431 
5432 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)5433 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
5434 {
5435     const char kFragmentShader[] = R"(precision mediump float;
5436 uniform struct { float q; } b, c;
5437 void main()
5438 {
5439     gl_FragColor = vec4(1, 0, 0, 1);
5440     if (b.q == 0.5 && c.q == 1.0)
5441     {
5442         gl_FragColor = vec4(0, 1, 0, 1);
5443     }
5444 })";
5445 
5446     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5447     glUseProgram(program);
5448 
5449     GLint uniLocB = glGetUniformLocation(program, "b.q");
5450     ASSERT_NE(-1, uniLocB);
5451     glUniform1f(uniLocB, 0.5f);
5452 
5453     GLint uniLocC = glGetUniformLocation(program, "c.q");
5454     ASSERT_NE(-1, uniLocC);
5455     glUniform1f(uniLocC, 1.0f);
5456 
5457     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5458     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5459 }
5460 
5461 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)5462 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
5463 {
5464     constexpr char kFS[] =
5465         "#version 300 es\n"
5466         "precision highp float;\n"
5467         "out vec4 my_FragColor;\n"
5468         "void main()\n"
5469         "{\n"
5470         "    float i = 0.0;\n"
5471         "    while (bool foo = (i < 1.5))\n"
5472         "    {\n"
5473         "        if (!foo)\n"
5474         "        {\n"
5475         "            ++i;\n"
5476         "        }\n"
5477         "        if (i > 3.5)\n"
5478         "        {\n"
5479         "            break;\n"
5480         "        }\n"
5481         "        ++i;\n"
5482         "    }\n"
5483         "    my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
5484         "}\n";
5485 
5486     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5487     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5488     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5489 }
5490 
5491 // Test that a variable hides a user-defined function with the same name after its initializer.
5492 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
5493 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)5494 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
5495 {
5496     constexpr char kFS[] =
5497         "precision mediump float;\n"
5498         "uniform vec4 u;\n"
5499         "vec4 foo()\n"
5500         "{\n"
5501         "    return u;\n"
5502         "}\n"
5503         "void main()\n"
5504         "{\n"
5505         "    vec4 foo = foo();\n"
5506         "    gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
5507         "}\n";
5508 
5509     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5510     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
5511     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5512 }
5513 
5514 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)5515 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
5516 {
5517     constexpr char kFS[] =
5518         "precision mediump float;\n"
5519         "uniform float u_zero;\n"
5520         "struct S { float foo; };\n"
5521         "struct S2 { float foo; };\n"
5522         "float get(S s) { return s.foo + u_zero; }\n"
5523         "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
5524         "void main()\n"
5525         "{\n"
5526         "    S s;\n"
5527         "    s.foo = 0.5;\n"
5528         "    S2 s2;\n"
5529         "    s2.foo = 0.25;\n"
5530         "    gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
5531         "}\n";
5532 
5533     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5534     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
5535     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5536 }
5537 
5538 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
5539 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)5540 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
5541 {
5542     // http://anglebug.com/4820
5543     ANGLE_SKIP_TEST_IF((IsOSX() && IsOpenGL()) || (IsIOS() && IsOpenGLES()));
5544 
5545     constexpr char kVS[] =
5546         "attribute vec4 inputAttribute;\n"
5547         "varying vec4 varColor;\n"
5548         "void main()\n"
5549         "{\n"
5550         "    gl_Position = inputAttribute;\n"
5551         "}\n";
5552 
5553     constexpr char kFS[] =
5554         "precision mediump float;\n"
5555         "varying vec4 varColor;\n"
5556         "void main()\n"
5557         "{\n"
5558         "    gl_FragColor = varColor;\n"
5559         "}\n";
5560 
5561     ANGLE_GL_PROGRAM(program, kVS, kFS);
5562     drawQuad(program.get(), "inputAttribute", 0.5f);
5563     ASSERT_GL_NO_ERROR();
5564 }
5565 
5566 // Test that a varying struct that's not statically used in the fragment shader works.
5567 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)5568 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
5569 {
5570     constexpr char kVS[] =
5571         "#version 300 es\n"
5572         "struct S {\n"
5573         "    vec4 field;\n"
5574         "};\n"
5575         "out S varStruct;\n"
5576         "void main()\n"
5577         "{\n"
5578         "    gl_Position = vec4(1.0);\n"
5579         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
5580         "}\n";
5581 
5582     constexpr char kFS[] =
5583         "#version 300 es\n"
5584         "precision mediump float;\n"
5585         "struct S {\n"
5586         "    vec4 field;\n"
5587         "};\n"
5588         "in S varStruct;\n"
5589         "out vec4 col;\n"
5590         "void main()\n"
5591         "{\n"
5592         "    col = vec4(1.0);\n"
5593         "}\n";
5594 
5595     ANGLE_GL_PROGRAM(program, kVS, kFS);
5596 }
5597 
5598 // Test that a shader IO block varying that's not declared in the fragment shader links
5599 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)5600 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
5601 {
5602     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
5603 
5604     constexpr char kVS[] =
5605         R"(#version 310 es
5606         #extension GL_EXT_shader_io_blocks : require
5607 
5608         precision highp float;
5609         in vec4 inputAttribute;
5610         out Block_inout { vec4 value; } user_out;
5611 
5612         void main()
5613         {
5614             gl_Position    = inputAttribute;
5615             user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
5616         })";
5617 
5618     constexpr char kFS[] =
5619         R"(#version 310 es
5620         #extension GL_EXT_shader_io_blocks : require
5621 
5622         precision highp float;
5623         layout(location = 0) out mediump vec4 color;
5624         void main()
5625         {
5626             color = vec4(1, 0, 0, 1);
5627         })";
5628 
5629     ANGLE_GL_PROGRAM(program, kVS, kFS);
5630     drawQuad(program.get(), "inputAttribute", 0.5f);
5631     ASSERT_GL_NO_ERROR();
5632 
5633     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5634 }
5635 
5636 // Test that a shader IO block varying that's not declared in the vertex shader links
5637 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)5638 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
5639 {
5640     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
5641 
5642     constexpr char kVS[] =
5643         R"(#version 310 es
5644         #extension GL_EXT_shader_io_blocks : require
5645 
5646         precision highp float;
5647         in vec4 inputAttribute;
5648 
5649         void main()
5650         {
5651             gl_Position = inputAttribute;
5652         })";
5653 
5654     constexpr char kFS[] =
5655         R"(#version 310 es
5656         #extension GL_EXT_shader_io_blocks : require
5657 
5658         precision highp float;
5659         in Block_inout { vec4 value; } user_in;
5660         layout(location = 0) out mediump vec4 color;
5661 
5662         void main()
5663         {
5664             color = vec4(1, 0, 0, 1);
5665         })";
5666 
5667     ANGLE_GL_PROGRAM(program, kVS, kFS);
5668     drawQuad(program.get(), "inputAttribute", 0.5f);
5669     ASSERT_GL_NO_ERROR();
5670 
5671     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5672 }
5673 
5674 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)5675 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
5676 {
5677     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
5678     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
5679 
5680     constexpr char kVS[] =
5681         R"(#version 310 es
5682         #extension GL_OES_shader_multisample_interpolation : require
5683 
5684         precision highp float;
5685         in vec4 inputAttribute;
5686 
5687         sample out mediump float tc_in;
5688         void main()
5689         {
5690             tc_in = inputAttribute[0];
5691             gl_Position = inputAttribute;
5692         })";
5693 
5694     constexpr char kTCS[] =
5695         R"(#version 310 es
5696         #extension GL_EXT_tessellation_shader : require
5697         #extension GL_OES_shader_multisample_interpolation : require
5698         layout (vertices=3) out;
5699 
5700         sample in mediump float tc_in[];
5701         sample out mediump float tc_out[];
5702         void main()
5703         {
5704             tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
5705             gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
5706             gl_TessLevelInner[0] = 2.0;
5707             gl_TessLevelInner[1] = 2.0;
5708             gl_TessLevelOuter[0] = 2.0;
5709             gl_TessLevelOuter[1] = 2.0;
5710             gl_TessLevelOuter[2] = 2.0;
5711             gl_TessLevelOuter[3] = 2.0;
5712         })";
5713 
5714     constexpr char kTES[] =
5715         R"(#version 310 es
5716         #extension GL_EXT_tessellation_shader : require
5717         #extension GL_OES_shader_multisample_interpolation : require
5718         layout (triangles) in;
5719 
5720         sample in mediump float tc_out[];
5721         sample out mediump float te_out;
5722         void main()
5723         {
5724             te_out = tc_out[2];
5725             gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
5726         })";
5727 
5728     constexpr char kFS[] =
5729         R"(#version 310 es
5730         #extension GL_OES_shader_multisample_interpolation : require
5731 
5732         precision highp float;
5733         sample in mediump float te_out;
5734         layout(location = 0) out mediump vec4 color;
5735 
5736         void main()
5737         {
5738             float out0 = te_out;
5739             color = vec4(1, 0, 0, 1);
5740         })";
5741 
5742     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
5743     drawPatches(program.get(), "inputAttribute", 0.5f, 1.0f, GL_FALSE);
5744     ASSERT_GL_NO_ERROR();
5745 }
5746 
5747 // Test that a varying struct that's not declared in the fragment shader links successfully.
5748 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)5749 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
5750 {
5751     constexpr char kVS[] =
5752         "#version 300 es\n"
5753         "struct S {\n"
5754         "    vec4 field;\n"
5755         "};\n"
5756         "out S varStruct;\n"
5757         "void main()\n"
5758         "{\n"
5759         "    gl_Position = vec4(1.0);\n"
5760         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
5761         "}\n";
5762 
5763     constexpr char kFS[] =
5764         "#version 300 es\n"
5765         "precision mediump float;\n"
5766         "out vec4 col;\n"
5767         "void main()\n"
5768         "{\n"
5769         "    col = vec4(1.0);\n"
5770         "}\n";
5771 
5772     ANGLE_GL_PROGRAM(program, kVS, kFS);
5773 }
5774 
5775 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
5776 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)5777 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
5778 {
5779     // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
5780     // going to use it.  See section 9.1 in
5781     // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
5782     // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
5783     //
5784     // However, nvidia OpenGL ES drivers fail to link this program.
5785     //
5786     // http://anglebug.com/3413
5787     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
5788 
5789     constexpr char kVS[] =
5790         "#version 300 es\n"
5791         "void main()\n"
5792         "{\n"
5793         "    gl_Position = vec4(1.0);\n"
5794         "}\n";
5795 
5796     constexpr char kFS[] =
5797         "#version 300 es\n"
5798         "precision mediump float;\n"
5799         "out vec4 col;\n"
5800         "struct S {\n"
5801         "    vec4 field;\n"
5802         "};\n"
5803         "in S varStruct;\n"
5804         "void main()\n"
5805         "{\n"
5806         "    col = vec4(1.0);\n"
5807         "}\n";
5808 
5809     ANGLE_GL_PROGRAM(program, kVS, kFS);
5810 }
5811 
5812 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)5813 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
5814 {
5815     // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
5816     // specification that the varying values are undefined in the fragment stage).  See section 9.1
5817     // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
5818     // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
5819     //
5820     // However, windows and mac OpenGL drivers fail to link this program.  With a message like:
5821     //
5822     // > Input of fragment shader 'varStruct' not written by vertex shader
5823     //
5824     // http://anglebug.com/3413
5825     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || (IsWindows() && !IsNVIDIA())));
5826     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
5827     // struct member. Not sure if it's being overly strict.
5828     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5829 
5830     constexpr char kVS[] =
5831         "#version 300 es\n"
5832         "struct S {\n"
5833         "    vec4 field;\n"
5834         "};\n"
5835         "out S varStruct;\n"
5836         "void main()\n"
5837         "{\n"
5838         "    gl_Position = vec4(1.0);\n"
5839         "}\n";
5840 
5841     constexpr char kFS[] =
5842         "#version 300 es\n"
5843         "precision mediump float;\n"
5844         "out vec4 col;\n"
5845         "struct S {\n"
5846         "    vec4 field;\n"
5847         "};\n"
5848         "in S varStruct;\n"
5849         "void main()\n"
5850         "{\n"
5851         "    col = varStruct.field;\n"
5852         "}\n";
5853 
5854     ANGLE_GL_PROGRAM(program, kVS, kFS);
5855 }
5856 
5857 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)5858 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
5859 {
5860     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
5861     // struct member. Not sure if it's being overly strict.
5862     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5863     constexpr char kVS[] =
5864         "#version 300 es\n"
5865         "in vec4 inputAttribute;\n"
5866         "struct S {\n"
5867         "    vec4 field;\n"
5868         "};\n"
5869         "out S varStruct;\n"
5870         "out S varStruct2;\n"
5871         "void main()\n"
5872         "{\n"
5873         "    gl_Position = inputAttribute;\n"
5874         "    varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
5875         "    varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
5876         "}\n";
5877 
5878     constexpr char kFS[] =
5879         "#version 300 es\n"
5880         "precision mediump float;\n"
5881         "out vec4 col;\n"
5882         "struct S {\n"
5883         "    vec4 field;\n"
5884         "};\n"
5885         "in S varStruct;\n"
5886         "in S varStruct2;\n"
5887         "void main()\n"
5888         "{\n"
5889         "    col = varStruct.field + varStruct2.field;\n"
5890         "}\n";
5891 
5892     ANGLE_GL_PROGRAM(program, kVS, kFS);
5893     drawQuad(program.get(), "inputAttribute", 0.5f);
5894     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5895 }
5896 
5897 // This is a regression test to make sure a red quad is rendered without issues
5898 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)5899 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
5900 {
5901     constexpr char kVS[] =
5902         "precision mediump float;\n"
5903         "attribute vec4 inputAttribute;\n"
5904         "varying mediump vec2 texCoord;\n"
5905         "void main() {\n"
5906         "    texCoord = inputAttribute.xy;\n"
5907         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
5908         "}\n";
5909 
5910     constexpr char kFS[] =
5911         "precision mediump float;\n"
5912         "varying mediump vec2 texCoord;\n"
5913         "uniform sampler2D testSampler;\n"
5914         "vec3 passthrough(vec3 c) {\n"
5915         "    return c;\n"
5916         "}\n"
5917         "void main() {\n"
5918         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
5919         "}\n";
5920     ANGLE_GL_PROGRAM(program, kVS, kFS);
5921 
5922     // Initialize basic red texture.
5923     GLTexture texture;
5924     glBindTexture(GL_TEXTURE_2D, texture);
5925     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5926                  GLColor::red.data());
5927     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5928     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5929     ASSERT_GL_NO_ERROR();
5930 
5931     drawQuad(program.get(), "inputAttribute", 0.5f);
5932     ASSERT_GL_NO_ERROR();
5933     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5934 }
5935 
5936 // This is a regression test to make sure a red quad is rendered without issues
5937 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)5938 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
5939 {
5940     constexpr char kVS[] =
5941         "precision mediump float;\n"
5942         "attribute vec4 inputAttribute;\n"
5943         "varying mediump vec2 texCoord;\n"
5944         "void main() {\n"
5945         "    texCoord = inputAttribute.xy;\n"
5946         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
5947         "}\n";
5948 
5949     constexpr char kFS[] =
5950         "precision mediump float;\n"
5951         "varying mediump vec2 texCoord;\n"
5952         "uniform sampler2D testSampler;\n"
5953         "vec4 passthrough(vec4 c) {\n"
5954         "    return c;\n"
5955         "}\n"
5956         "void main() {\n"
5957         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
5958         "}\n";
5959     ANGLE_GL_PROGRAM(program, kVS, kFS);
5960 
5961     // Initialize basic red texture.
5962     GLTexture texture;
5963     glBindTexture(GL_TEXTURE_2D, texture);
5964     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5965                  GLColor::red.data());
5966     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5967     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5968     ASSERT_GL_NO_ERROR();
5969 
5970     drawQuad(program.get(), "inputAttribute", 0.5f);
5971     ASSERT_GL_NO_ERROR();
5972     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5973 }
5974 
5975 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)5976 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
5977 {
5978     // TODO(syoussefi): fails on android with:
5979     //
5980     // > Internal Vulkan error: A return array was too small for the result
5981     //
5982     // http://anglebug.com/3220
5983     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
5984     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
5985     // struct members. Not sure if it's being overly strict.
5986     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5987 
5988     constexpr char kVS[] =
5989         "#version 300 es\n"
5990         "in vec4 inputAttribute;\n"
5991         "struct S {\n"
5992         "    vec4 field1;\n"
5993         "    vec4 field2;\n"
5994         "};\n"
5995         "out S varStruct;\n"
5996         "out S varStruct2;\n"
5997         "void main()\n"
5998         "{\n"
5999         "    gl_Position = inputAttribute;\n"
6000         "    varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6001         "    varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6002         "    varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6003         "    varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6004         "}\n";
6005 
6006     constexpr char kFS[] =
6007         "#version 300 es\n"
6008         "precision mediump float;\n"
6009         "out vec4 col;\n"
6010         "struct S {\n"
6011         "    vec4 field1;\n"
6012         "    vec4 field2;\n"
6013         "};\n"
6014         "in S varStruct;\n"
6015         "in S varStruct2;\n"
6016         "void main()\n"
6017         "{\n"
6018         "    col = varStruct.field1 + varStruct2.field2;\n"
6019         "}\n";
6020 
6021     ANGLE_GL_PROGRAM(program, kVS, kFS);
6022     drawQuad(program.get(), "inputAttribute", 0.5f);
6023     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6024 }
6025 
6026 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)6027 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
6028 {
6029     constexpr char kVS[] =
6030         "#version 300 es\n"
6031         "in vec4 inputAttribute;\n"
6032         "out vec4 varArray[4];\n"
6033         "void main()\n"
6034         "{\n"
6035         "    gl_Position = inputAttribute;\n"
6036         "    varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
6037         "    varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
6038         "    varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
6039         "    varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
6040         "}\n";
6041 
6042     constexpr char kFS[] =
6043         "#version 300 es\n"
6044         "precision mediump float;\n"
6045         "out vec4 col;\n"
6046         "void main()\n"
6047         "{\n"
6048         "    col = vec4(0.0, 0.0, 0.0, 1.0);\n"
6049         "}\n";
6050 
6051     ANGLE_GL_PROGRAM(program, kVS, kFS);
6052     drawQuad(program.get(), "inputAttribute", 0.5f);
6053     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6054 }
6055 
6056 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)6057 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
6058 {
6059     constexpr char kVS[] =
6060         "#version 300 es\n"
6061         "in vec4 inputAttribute;\n"
6062         "struct S {\n"
6063         "    vec4 field;\n"
6064         "};\n"
6065         "out S varStruct;\n"
6066         "out S varStruct2;\n"
6067         "void main()\n"
6068         "{\n"
6069         "    gl_Position = inputAttribute;\n"
6070         "    varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6071         "    varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6072         "}\n";
6073 
6074     constexpr char kFS[] =
6075         "#version 300 es\n"
6076         "precision mediump float;\n"
6077         "out vec4 col;\n"
6078         "struct S {\n"
6079         "    vec4 field;\n"
6080         "};\n"
6081         "in S varStruct;\n"
6082         "in S varStruct2;\n"
6083         "void main()\n"
6084         "{\n"
6085         "    col = varStruct.field;\n"
6086         "}\n";
6087 
6088     ANGLE_GL_PROGRAM(program, kVS, kFS);
6089     drawQuad(program.get(), "inputAttribute", 0.5f);
6090     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6091 }
6092 
6093 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)6094 TEST_P(GLSLTest_ES3, VaryingMatrices)
6095 {
6096     constexpr char kVS[] =
6097         "#version 300 es\n"
6098         "in vec4 inputAttribute;\n"
6099         "out mat2x2 varMat;\n"
6100         "out mat2x2 varMat2;\n"
6101         "out mat4x3 varMat3;\n"
6102         "void main()\n"
6103         "{\n"
6104         "    gl_Position = inputAttribute;\n"
6105         "    varMat[0] = vec2(1, 1);\n"
6106         "    varMat[1] = vec2(1, 1);\n"
6107         "    varMat2[0] = vec2(0.5, 0.5);\n"
6108         "    varMat2[1] = vec2(0.5, 0.5);\n"
6109         "    varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
6110         "    varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
6111         "    varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
6112         "    varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
6113         "}\n";
6114 
6115     constexpr char kFS[] =
6116         "#version 300 es\n"
6117         "precision mediump float;\n"
6118         "out vec4 col;\n"
6119         "in mat2x2 varMat;\n"
6120         "in mat2x2 varMat2;\n"
6121         "in mat4x3 varMat3;\n"
6122         "void main()\n"
6123         "{\n"
6124         "    col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
6125         "}\n";
6126 
6127     ANGLE_GL_PROGRAM(program, kVS, kFS);
6128     drawQuad(program.get(), "inputAttribute", 0.5f);
6129     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
6130 }
6131 
6132 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)6133 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
6134 {
6135     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6136     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6137 
6138     const char kFragmentShader[] = R"(precision mediump float;
6139 struct S { sampler2D samplerMember; };
6140 uniform S uStruct;
6141 uniform vec2 uTexCoord;
6142 vec4 foo(S structVar)
6143 {
6144     return texture2D(structVar.samplerMember, uTexCoord);
6145 }
6146 void main()
6147 {
6148     gl_FragColor = foo(uStruct);
6149 })";
6150 
6151     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6152 
6153     // Initialize the texture with green.
6154     GLTexture tex;
6155     glActiveTexture(GL_TEXTURE0);
6156     glBindTexture(GL_TEXTURE_2D, tex);
6157     GLubyte texData[] = {0u, 255u, 0u, 255u};
6158     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6159     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6160     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6161     ASSERT_GL_NO_ERROR();
6162 
6163     // Draw
6164     glUseProgram(program);
6165     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6166     ASSERT_NE(-1, samplerMemberLoc);
6167     glUniform1i(samplerMemberLoc, 0);
6168     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6169     ASSERT_NE(-1, texCoordLoc);
6170     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6171 
6172     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6173     ASSERT_GL_NO_ERROR();
6174 
6175     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6176 }
6177 
6178 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)6179 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
6180 {
6181     // Shader failed to compile on Android. http://anglebug.com/2114
6182     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6183 
6184     const char kFragmentShader[] = R"(precision mediump float;
6185 struct S { sampler2D samplerMember; };
6186 uniform S uStruct;
6187 uniform vec2 uTexCoord;
6188 vec4 foo(S structVar);
6189 vec4 foo(S structVar)
6190 {
6191     return texture2D(structVar.samplerMember, uTexCoord);
6192 }
6193 void main()
6194 {
6195     gl_FragColor = foo(uStruct);
6196 })";
6197 
6198     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6199 
6200     // Initialize the texture with green.
6201     GLTexture tex;
6202     glActiveTexture(GL_TEXTURE0);
6203     glBindTexture(GL_TEXTURE_2D, tex);
6204     GLubyte texData[] = {0u, 255u, 0u, 255u};
6205     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6206     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6207     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6208     ASSERT_GL_NO_ERROR();
6209 
6210     // Draw
6211     glUseProgram(program);
6212     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6213     ASSERT_NE(-1, samplerMemberLoc);
6214     glUniform1i(samplerMemberLoc, 0);
6215     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6216     ASSERT_NE(-1, texCoordLoc);
6217     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6218 
6219     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6220     ASSERT_GL_NO_ERROR();
6221 
6222     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6223 }
6224 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)6225 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
6226 {
6227     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6228     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6229 
6230     constexpr char kFS[] =
6231         "precision mediump float;\n"
6232         "struct S\n"
6233         "{\n"
6234         "    sampler2D samplerMember; \n"
6235         "};\n"
6236         "uniform S uStructs[2];\n"
6237         "uniform vec2 uTexCoord;\n"
6238         "\n"
6239         "vec4 foo(S[2] structs)\n"
6240         "{\n"
6241         "    return texture2D(structs[0].samplerMember, uTexCoord);\n"
6242         "}\n"
6243         "void main()\n"
6244         "{\n"
6245         "    gl_FragColor = foo(uStructs);\n"
6246         "}\n";
6247 
6248     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6249 
6250     // Initialize the texture with green.
6251     GLTexture tex;
6252     glActiveTexture(GL_TEXTURE0);
6253     glBindTexture(GL_TEXTURE_2D, tex);
6254     GLubyte texData[] = {0u, 255u, 0u, 255u};
6255     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6256     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6257     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6258     ASSERT_GL_NO_ERROR();
6259 
6260     // Draw
6261     glUseProgram(program);
6262     GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
6263     ASSERT_NE(-1, samplerMemberLoc);
6264     glUniform1i(samplerMemberLoc, 0);
6265     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6266     ASSERT_NE(-1, texCoordLoc);
6267     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6268 
6269     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6270     ASSERT_GL_NO_ERROR();
6271 
6272     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6273 }
6274 
6275 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)6276 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
6277 {
6278     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6279     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6280 
6281     constexpr char kFS[] =
6282         "precision mediump float;\n"
6283         "struct S\n"
6284         "{\n"
6285         "    sampler2D samplerMembers[2];\n"
6286         "};\n"
6287         "uniform S uStruct;\n"
6288         "uniform vec2 uTexCoord;\n"
6289         "\n"
6290         "vec4 foo(S str)\n"
6291         "{\n"
6292         "    return texture2D(str.samplerMembers[0], uTexCoord);\n"
6293         "}\n"
6294         "void main()\n"
6295         "{\n"
6296         "    gl_FragColor = foo(uStruct);\n"
6297         "}\n";
6298 
6299     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6300 
6301     // Initialize the texture with green.
6302     GLTexture tex;
6303     glActiveTexture(GL_TEXTURE0);
6304     glBindTexture(GL_TEXTURE_2D, tex);
6305     GLubyte texData[] = {0u, 255u, 0u, 255u};
6306     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6307     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6308     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6309     ASSERT_GL_NO_ERROR();
6310 
6311     // Draw
6312     glUseProgram(program);
6313     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
6314     ASSERT_NE(-1, samplerMemberLoc);
6315     glUniform1i(samplerMemberLoc, 0);
6316     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6317     ASSERT_NE(-1, texCoordLoc);
6318     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6319 
6320     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6321     ASSERT_GL_NO_ERROR();
6322 
6323     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6324 }
6325 
6326 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)6327 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
6328 {
6329     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6330     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6331 
6332     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
6333     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
6334 
6335     const char kFragmentShader[] = R"(precision mediump float;
6336 struct S { sampler2D samplerMember; };
6337 struct T { S nest; };
6338 uniform T uStruct;
6339 uniform vec2 uTexCoord;
6340 vec4 foo2(S structVar)
6341 {
6342     return texture2D(structVar.samplerMember, uTexCoord);
6343 }
6344 vec4 foo(T structVar)
6345 {
6346     return foo2(structVar.nest);
6347 }
6348 void main()
6349 {
6350     gl_FragColor = foo(uStruct);
6351 })";
6352 
6353     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6354 
6355     // Initialize the texture with green.
6356     GLTexture tex;
6357     glActiveTexture(GL_TEXTURE0);
6358     glBindTexture(GL_TEXTURE_2D, tex);
6359     GLubyte texData[] = {0u, 255u, 0u, 255u};
6360     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6361     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6362     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6363     ASSERT_GL_NO_ERROR();
6364 
6365     // Draw
6366     glUseProgram(program);
6367     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
6368     ASSERT_NE(-1, samplerMemberLoc);
6369     glUniform1i(samplerMemberLoc, 0);
6370     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6371     ASSERT_NE(-1, texCoordLoc);
6372     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6373 
6374     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6375     ASSERT_GL_NO_ERROR();
6376 
6377     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6378 }
6379 
6380 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)6381 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
6382 {
6383     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6384     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6385 
6386     const char kFragmentShader[] = R"(precision mediump float;
6387 struct S { sampler2D samplerMember; bool b; };
6388 uniform S uStruct;
6389 uniform vec2 uTexCoord;
6390 vec4 foo(S structVar)
6391 {
6392     if (structVar.b)
6393         return texture2D(structVar.samplerMember, uTexCoord);
6394     else
6395         return vec4(1, 0, 0, 1);
6396 }
6397 void main()
6398 {
6399     gl_FragColor = foo(uStruct);
6400 })";
6401 
6402     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6403 
6404     // Initialize the texture with green.
6405     GLTexture tex;
6406     glActiveTexture(GL_TEXTURE0);
6407     glBindTexture(GL_TEXTURE_2D, tex);
6408     GLubyte texData[] = {0u, 255u, 0u, 255u};
6409     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6410     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6411     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6412     ASSERT_GL_NO_ERROR();
6413 
6414     // Draw
6415     glUseProgram(program);
6416     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6417     ASSERT_NE(-1, samplerMemberLoc);
6418     glUniform1i(samplerMemberLoc, 0);
6419     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6420     ASSERT_NE(-1, texCoordLoc);
6421     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6422     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
6423     ASSERT_NE(-1, bLoc);
6424     glUniform1i(bLoc, 1);
6425 
6426     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6427     ASSERT_GL_NO_ERROR();
6428 
6429     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6430 }
6431 
6432 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)6433 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
6434 {
6435     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6436     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6437 
6438     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
6439     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
6440 
6441     const char kFragmentShader[] = R"(precision mediump float;
6442 struct S { sampler2D samplerMember; bool b; };
6443 struct T { S nest; bool b; };
6444 uniform T uStruct;
6445 uniform vec2 uTexCoord;
6446 vec4 foo2(S structVar)
6447 {
6448     if (structVar.b)
6449         return texture2D(structVar.samplerMember, uTexCoord);
6450     else
6451         return vec4(1, 0, 0, 1);
6452 }
6453 vec4 foo(T structVar)
6454 {
6455     if (structVar.b)
6456         return foo2(structVar.nest);
6457     else
6458         return vec4(1, 0, 0, 1);
6459 }
6460 void main()
6461 {
6462     gl_FragColor = foo(uStruct);
6463 })";
6464 
6465     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6466 
6467     // Initialize the texture with green.
6468     GLTexture tex;
6469     glActiveTexture(GL_TEXTURE0);
6470     glBindTexture(GL_TEXTURE_2D, tex);
6471     GLubyte texData[] = {0u, 255u, 0u, 255u};
6472     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6473     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6474     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6475     ASSERT_GL_NO_ERROR();
6476 
6477     // Draw
6478     glUseProgram(program);
6479     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
6480     ASSERT_NE(-1, samplerMemberLoc);
6481     glUniform1i(samplerMemberLoc, 0);
6482     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6483     ASSERT_NE(-1, texCoordLoc);
6484     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6485 
6486     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
6487     ASSERT_NE(-1, bLoc);
6488     glUniform1i(bLoc, 1);
6489 
6490     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
6491     ASSERT_NE(-1, nestbLoc);
6492     glUniform1i(nestbLoc, 1);
6493 
6494     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6495     ASSERT_GL_NO_ERROR();
6496 
6497     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6498 }
6499 
6500 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)6501 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
6502 {
6503     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6504     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6505 
6506     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
6507     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
6508 
6509     const char kFragmentShader[] = R"(precision mediump float;
6510 struct S { bool b; sampler2D samplerMember; };
6511 struct T { bool b; S nest; };
6512 uniform T uStruct;
6513 uniform vec2 uTexCoord;
6514 vec4 foo2(S structVar)
6515 {
6516     if (structVar.b)
6517         return texture2D(structVar.samplerMember, uTexCoord);
6518     else
6519         return vec4(1, 0, 0, 1);
6520 }
6521 vec4 foo(T structVar)
6522 {
6523     if (structVar.b)
6524         return foo2(structVar.nest);
6525     else
6526         return vec4(1, 0, 0, 1);
6527 }
6528 void main()
6529 {
6530     gl_FragColor = foo(uStruct);
6531 })";
6532 
6533     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6534 
6535     // Initialize the texture with green.
6536     GLTexture tex;
6537     glActiveTexture(GL_TEXTURE0);
6538     glBindTexture(GL_TEXTURE_2D, tex);
6539     GLubyte texData[] = {0u, 255u, 0u, 255u};
6540     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6541     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6542     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6543     ASSERT_GL_NO_ERROR();
6544 
6545     // Draw
6546     glUseProgram(program);
6547     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
6548     ASSERT_NE(-1, samplerMemberLoc);
6549     glUniform1i(samplerMemberLoc, 0);
6550     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6551     ASSERT_NE(-1, texCoordLoc);
6552     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6553 
6554     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
6555     ASSERT_NE(-1, bLoc);
6556     glUniform1i(bLoc, 1);
6557 
6558     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
6559     ASSERT_NE(-1, nestbLoc);
6560     glUniform1i(nestbLoc, 1);
6561 
6562     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6563     ASSERT_GL_NO_ERROR();
6564 
6565     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6566 }
6567 // Test that a global variable declared after main() works. This is a regression test for an issue
6568 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)6569 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
6570 {
6571     constexpr char kFS[] =
6572         "precision mediump float;\n"
6573         "int getFoo();\n"
6574         "uniform int u_zero;\n"
6575         "void main()\n"
6576         "{\n"
6577         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
6578         "    if (getFoo() == 0)\n"
6579         "    {\n"
6580         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6581         "    }\n"
6582         "}\n"
6583         "int foo;\n"
6584         "int getFoo()\n"
6585         "{\n"
6586         "    foo = u_zero;\n"
6587         "    return foo;\n"
6588         "}\n";
6589 
6590     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6591     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6592     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6593 }
6594 
6595 // Test calling array length() with a "this" expression having side effects inside a loop condition.
6596 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)6597 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
6598 {
6599     // "a" gets doubled three times in the below program.
6600     constexpr char kFS[] = R"(#version 300 es
6601 precision highp float;
6602 out vec4 my_FragColor;
6603 uniform int u_zero;
6604 int a;
6605 int[2] doubleA()
6606 {
6607     a *= 2;
6608     return int[2](a, a);
6609 }
6610 void main()
6611 {
6612     a = u_zero + 1;
6613     for (int i = 0; i < doubleA().length(); ++i)
6614     {}
6615     if (a == 8)
6616     {
6617         my_FragColor = vec4(0, 1, 0, 1);
6618     }
6619     else
6620     {
6621         my_FragColor = vec4(1, 0, 0, 1);
6622     }
6623 })";
6624 
6625     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6626     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6627     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6628 }
6629 
6630 // Test calling array length() with a "this" expression having side effects that interact with side
6631 // effects of another operand of the same sequence operator. The spec says that sequence operator
6632 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)6633 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
6634 {
6635     constexpr char kFS[] = R"(#version 300 es
6636 precision highp float;
6637 out vec4 my_FragColor;
6638 uniform int u_zero;
6639 int a;
6640 int[3] doubleA()
6641 {
6642     a *= 2;
6643     return int[3](a, a, a);
6644 }
6645 void main()
6646 {
6647     a = u_zero;
6648     int b = (a++, doubleA().length());
6649     if (b == 3 && a == 2)
6650     {
6651         my_FragColor = vec4(0, 1, 0, 1);
6652     }
6653     else
6654     {
6655         my_FragColor = vec4(1, 0, 0, 1);
6656     }
6657 })";
6658 
6659     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6660     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6661     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6662 }
6663 
6664 // Test calling array length() with a "this" expression that also contains a call of array length().
6665 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)6666 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
6667 {
6668     constexpr char kFS[] = R"(#version 300 es
6669 precision highp float;
6670 out vec4 my_FragColor;
6671 uniform int u_zero;
6672 int a;
6673 int[3] multiplyA(int multiplier)
6674 {
6675     a *= multiplier;
6676     return int[3](a, a, a);
6677 }
6678 void main()
6679 {
6680     a = u_zero + 1;
6681     int b = multiplyA(multiplyA(2).length()).length();
6682     if (b == 3 && a == 6)
6683     {
6684         my_FragColor = vec4(0, 1, 0, 1);
6685     }
6686     else
6687     {
6688         my_FragColor = vec4(1, 0, 0, 1);
6689     }
6690 })";
6691 
6692     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6693     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6694     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6695 }
6696 
6697 // Test calling array length() with a "this" expression having side effects inside an if condition.
6698 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)6699 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
6700 {
6701     // Bug in the shader translator.  http://anglebug.com/3829
6702     ANGLE_SKIP_TEST_IF(true);
6703 
6704     // "a" shouldn't get modified by this shader.
6705     constexpr char kFS[] = R"(#version 300 es
6706 precision highp float;
6707 out vec4 my_FragColor;
6708 uniform int u_zero;
6709 int a;
6710 int[2] doubleA()
6711 {
6712     a *= 2;
6713     return int[2](a, a);
6714 }
6715 void main()
6716 {
6717     a = u_zero + 1;
6718     if (u_zero != 0 && doubleA().length() == 2)
6719     {
6720         ++a;
6721     }
6722     if (a == 1)
6723     {
6724         my_FragColor = vec4(0, 1, 0, 1);
6725     }
6726     else
6727     {
6728         my_FragColor = vec4(1, 0, 0, 1);
6729     }
6730 })";
6731 
6732     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6733     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6734     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6735 }
6736 
6737 // Test calling array length() with a "this" expression having side effects in a statement where the
6738 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)6739 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
6740 {
6741     // Bug in the shader translator.  http://anglebug.com/3829
6742     ANGLE_SKIP_TEST_IF(true);
6743 
6744     // "a" shouldn't get modified by this shader.
6745     constexpr char kFS[] = R"(#version 300 es
6746 precision highp float;
6747 out vec4 my_FragColor;
6748 uniform int u_zero;
6749 int a;
6750 int[2] doubleA()
6751 {
6752     a *= 2;
6753     return int[2](a, a);
6754 }
6755 void main()
6756 {
6757     a = u_zero + 1;
6758     bool test = u_zero != 0 && doubleA().length() == 2;
6759     if (a == 1)
6760     {
6761         my_FragColor = vec4(0, 1, 0, 1);
6762     }
6763     else
6764     {
6765         my_FragColor = vec4(1, 0, 0, 1);
6766     }
6767 })";
6768 
6769     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6770     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6771     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6772 }
6773 
6774 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)6775 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
6776 {
6777     constexpr char kFS[] = R"(#version 300 es
6778 precision highp float;
6779 uniform int u;
6780 void main()
6781 {
6782     switch (u)
6783     {
6784         case 0:
6785             ivec2 i;
6786             i.yx;
6787     }
6788 })";
6789 
6790     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6791 }
6792 
6793 // Test that switch fall-through works correctly.
6794 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)6795 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
6796 {
6797     constexpr char kFS[] = R"(#version 300 es
6798 precision highp float;
6799 out vec4 my_FragColor;
6800 uniform int u_zero;
6801 
6802 void main()
6803 {
6804     int i = 0;
6805     // switch should fall through both cases.
6806     switch(u_zero)
6807     {
6808         case 0:
6809             i += 1;
6810         case 1:
6811             i += 2;
6812     }
6813     if (i == 3)
6814     {
6815         my_FragColor = vec4(0, 1, 0, 1);
6816     }
6817     else
6818     {
6819         my_FragColor = vec4(1, 0, 0, 1);
6820     }
6821 })";
6822 
6823     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6824     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6825     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6826 }
6827 
6828 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)6829 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
6830 {
6831     constexpr char kFS[] = R"(#version 300 es
6832 
6833 precision mediump float;
6834 uniform int i;
6835 void main()
6836 {
6837     switch (i)
6838     {
6839         case 0:
6840             break;
6841         default:
6842             {}
6843     }
6844 })";
6845     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6846 }
6847 
6848 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)6849 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
6850 {
6851     constexpr char kFS[] = R"(#version 300 es
6852 
6853 precision mediump float;
6854 uniform int i;
6855 void main()
6856 {
6857     switch (i)
6858     {
6859         case 0:
6860             break;
6861         default:
6862             float;
6863     }
6864 })";
6865     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6866 }
6867 
6868 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)6869 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
6870 {
6871     constexpr char kFS[] = R"(#version 300 es
6872 
6873 precision highp float;
6874 
6875 uniform int u_zero;
6876 out vec4 my_FragColor;
6877 
6878 bool test(int n)
6879 {
6880     switch(n) {
6881         case 0:
6882         {
6883             {
6884                 break;
6885             }
6886         }
6887         case 1:
6888         {
6889             return true;
6890         }
6891         case 2:
6892         {
6893             n++;
6894         }
6895     }
6896     return false;
6897 }
6898 
6899 void main()
6900 {
6901     my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
6902 })";
6903 
6904     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6905     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6906     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6907 }
6908 
6909 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
6910 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)6911 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
6912 {
6913     constexpr char kFS[] = R"(#version 300 es
6914 
6915 precision highp float;
6916 out vec4 my_FragColor;
6917 
6918 uniform int u_zero;
6919 
6920 void main()
6921 {
6922     my_FragColor = vec4(1, 0, 0, 1);
6923     switch (u_zero)
6924     {
6925         case 0:
6926             ivec2 i;
6927             i = ivec2(1, 0);
6928         default:
6929             my_FragColor = vec4(0, i[0], 0, 1);
6930     }
6931 })";
6932 
6933     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6934     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6935     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6936 }
6937 
6938 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
6939 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)6940 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
6941 {
6942     constexpr char kFS[] = R"(#version 300 es
6943 
6944 precision highp float;
6945 out vec4 my_FragColor;
6946 
6947 uniform int u_zero;
6948 uniform int u_zero2;
6949 
6950 void main()
6951 {
6952     my_FragColor = vec4(1, 0, 0, 1);
6953     switch (u_zero)
6954     {
6955         case 0:
6956             ivec2 i;
6957             i = ivec2(1, 0);
6958             switch (u_zero2)
6959             {
6960                 case 0:
6961                     int j;
6962                 default:
6963                     j = 1;
6964                     i *= j;
6965             }
6966         default:
6967             my_FragColor = vec4(0, i[0], 0, 1);
6968     }
6969 })";
6970 
6971     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6972     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6973     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6974 }
6975 
6976 // Test that an empty switch/case statement is translated in a way that compiles and executes the
6977 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)6978 TEST_P(GLSLTest_ES3, EmptySwitch)
6979 {
6980     constexpr char kFS[] = R"(#version 300 es
6981 
6982 precision highp float;
6983 
6984 uniform int u_zero;
6985 out vec4 my_FragColor;
6986 
6987 void main()
6988 {
6989     int i = u_zero;
6990     switch(++i) {}
6991     my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
6992 })";
6993 
6994     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6995     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6996     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6997 }
6998 
6999 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)7000 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
7001 {
7002     // Incorrect output color was seen on Android. http://anglebug.com/2226
7003     ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
7004 
7005     constexpr char kFS[] = R"(#version 300 es
7006 
7007 precision highp float;
7008 out vec4 my_FragColor;
7009 
7010 uniform float u_zero;
7011 
7012 struct S
7013 {
7014     float field;
7015 };
7016 
7017 void main()
7018 {
7019     const S constS = S(1.0);
7020     S nonConstS = constS;
7021     nonConstS.field = u_zero;
7022     bool fail = (constS == nonConstS);
7023     my_FragColor = vec4(0, 1, 0, 1);
7024     if (fail)
7025     {
7026         my_FragColor = vec4(1, 0, 0, 1);
7027     }
7028 })";
7029 
7030     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7031     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7032     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7033 }
7034 
7035 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)7036 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
7037 {
7038     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7039     // struct member. Not sure if it's being overly strict.
7040     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7041     constexpr char kVS[] = R"(#version 300 es
7042 in vec4 inputAttribute;
7043 
7044 flat out struct S
7045 {
7046     int field;
7047 } v_s;
7048 
7049 void main()
7050 {
7051     v_s.field = 1;
7052     gl_Position = inputAttribute;
7053 })";
7054 
7055     constexpr char kFS[] = R"(#version 300 es
7056 
7057 precision highp float;
7058 out vec4 my_FragColor;
7059 
7060 flat in struct S
7061 {
7062     int field;
7063 } v_s;
7064 
7065 void main()
7066 {
7067     bool success = (v_s.field == 1);
7068     my_FragColor = vec4(1, 0, 0, 1);
7069     if (success)
7070     {
7071         my_FragColor = vec4(0, 1, 0, 1);
7072     }
7073 })";
7074 
7075     ANGLE_GL_PROGRAM(program, kVS, kFS);
7076     drawQuad(program.get(), "inputAttribute", 0.5f);
7077     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7078 }
7079 
7080 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)7081 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
7082 {
7083     constexpr char kVS[] = R"(#version 300 es
7084 in vec4 position;
7085 uniform highp float inVal;
7086 out highp float myVarying;
7087 
7088 void main()
7089 {
7090     myVarying = inVal;
7091     gl_Position = position;
7092 })";
7093 
7094     constexpr char kFS[] = R"(#version 300 es
7095 precision highp float;
7096 out vec4 my_FragColor;
7097 in mediump float myVarying;
7098 
7099 void main()
7100 {
7101     my_FragColor = vec4(1, 0, 0, 1);
7102     if (myVarying > 1.0)
7103     {
7104         my_FragColor = vec4(0, 1, 0, 1);
7105     }
7106 })";
7107 
7108     ANGLE_GL_PROGRAM(program, kVS, kFS);
7109 
7110     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7111     glClear(GL_COLOR_BUFFER_BIT);
7112     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7113 
7114     glUseProgram(program.get());
7115     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7116     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7117     for (Vector3 &vertex : quadVertices)
7118     {
7119         vertex.z() = 0.5f;
7120     }
7121     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7122     glEnableVertexAttribArray(positionLocation);
7123 
7124     GLint inValLoc = glGetUniformLocation(program, "inVal");
7125     ASSERT_NE(-1, inValLoc);
7126     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7127 
7128     glDrawArrays(GL_TRIANGLES, 0, 6);
7129     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7130 }
7131 
7132 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)7133 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
7134 {
7135     // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
7136     // precision", thus this is the same test as MismatchPrecisionFloat but including it for
7137     // completeness in case something changes.
7138     constexpr char kVS[] = R"(#version 300 es
7139 in vec4 position;
7140 uniform highp float inVal;
7141 out highp float myVarying;
7142 
7143 void main()
7144 {
7145     myVarying = inVal;
7146     gl_Position = position;
7147 })";
7148 
7149     constexpr char kFS[] = R"(#version 300 es
7150 precision highp float;
7151 out vec4 my_FragColor;
7152 in lowp float myVarying;
7153 
7154 void main()
7155 {
7156     my_FragColor = vec4(1, 0, 0, 1);
7157     if (myVarying > 1.0)
7158     {
7159         my_FragColor = vec4(0, 1, 0, 1);
7160     }
7161 })";
7162 
7163     ANGLE_GL_PROGRAM(program, kVS, kFS);
7164 
7165     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7166     glClear(GL_COLOR_BUFFER_BIT);
7167     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7168 
7169     glUseProgram(program.get());
7170     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7171     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7172     for (Vector3 &vertex : quadVertices)
7173     {
7174         vertex.z() = 0.5f;
7175     }
7176     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7177     glEnableVertexAttribArray(positionLocation);
7178 
7179     GLint inValLoc = glGetUniformLocation(program, "inVal");
7180     ASSERT_NE(-1, inValLoc);
7181     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7182 
7183     glDrawArrays(GL_TRIANGLES, 0, 6);
7184     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7185 }
7186 
7187 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)7188 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
7189 {
7190     constexpr char kVS[] = R"(#version 300 es
7191 in vec2 position;
7192 uniform highp float inVal;
7193 out highp float myVarying;
7194 out highp vec2 texCoord;
7195 
7196 void main()
7197 {
7198     myVarying = inVal;
7199     gl_Position = vec4(position, 0, 1);
7200     texCoord = position * 0.5 + vec2(0.5);
7201 })";
7202 
7203     constexpr char kFS[] = R"(#version 300 es
7204 precision highp float;
7205 out vec4 my_FragColor;
7206 in mediump float myVarying;
7207 in mediump vec2 texCoord;
7208 
7209 void main()
7210 {
7211     my_FragColor = vec4(1, 0, 0, 1);
7212     if (myVarying > 1.0)
7213     {
7214         my_FragColor = vec4(0, 1, 0, 1);
7215     }
7216 })";
7217 
7218     ANGLE_GL_PROGRAM(program, kVS, kFS);
7219 
7220     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7221     glClear(GL_COLOR_BUFFER_BIT);
7222     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7223 
7224     glUseProgram(program.get());
7225     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7226     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7227     for (Vector3 &vertex : quadVertices)
7228     {
7229         vertex.z() = 0.5f;
7230     }
7231     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7232     glEnableVertexAttribArray(positionLocation);
7233 
7234     GLint inValLoc = glGetUniformLocation(program, "inVal");
7235     ASSERT_NE(-1, inValLoc);
7236     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7237 
7238     glDrawArrays(GL_TRIANGLES, 0, 6);
7239     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7240 }
7241 
7242 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)7243 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
7244 {
7245     constexpr char kVS[] = R"(#version 300 es
7246 in vec2 position;
7247 uniform highp float inVal;
7248 out mediump float myVarying;
7249 
7250 void main()
7251 {
7252     myVarying = inVal;
7253     gl_Position = vec4(position, 0, 1);
7254 })";
7255 
7256     constexpr char kFS[] = R"(#version 300 es
7257 precision highp float;
7258 out vec4 my_FragColor;
7259 in highp float myVarying;
7260 
7261 void main()
7262 {
7263     my_FragColor = vec4(1, 0, 0, 1);
7264     if (myVarying > 1.0)
7265     {
7266         my_FragColor = vec4(0, 1, 0, 1);
7267     }
7268 })";
7269 
7270     ANGLE_GL_PROGRAM(program, kVS, kFS);
7271 
7272     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7273     glClear(GL_COLOR_BUFFER_BIT);
7274     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7275 
7276     glUseProgram(program.get());
7277     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7278     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7279     for (Vector3 &vertex : quadVertices)
7280     {
7281         vertex.z() = 0.5f;
7282     }
7283     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7284     glEnableVertexAttribArray(positionLocation);
7285 
7286     GLint inValLoc = glGetUniformLocation(program, "inVal");
7287     ASSERT_NE(-1, inValLoc);
7288     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7289 
7290     glDrawArrays(GL_TRIANGLES, 0, 6);
7291     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7292 }
7293 
7294 // Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
7295 // bug that appeared in NVIDIA OpenGL drivers and that is worked around by
7296 // VectorizeVectorScalarArithmetic AST transform.
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)7297 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
7298 {
7299     constexpr char kFS[] = R"(precision mediump float;
7300 
7301 void main() {
7302     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
7303     for (int i = 0; i < 2; i++)
7304     {
7305         gl_FragColor += (2.0 * gl_FragCoord.x);
7306     }
7307     if (gl_FragColor.g == gl_FragColor.r &&
7308         gl_FragColor.b == gl_FragColor.r &&
7309         gl_FragColor.a == gl_FragColor.r)
7310     {
7311         gl_FragColor = vec4(0, 1, 0, 1);
7312     }
7313 })";
7314 
7315     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7316     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
7317     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7318 }
7319 
7320 // Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
7321 // bug that appeared in NVIDIA OpenGL drivers and that is worked around by
7322 // VectorizeVectorScalarArithmetic AST transform.
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)7323 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
7324 {
7325     constexpr char kFS[] = R"(precision mediump float;
7326 
7327 void main() {
7328     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
7329     for (int i = 0; i < 2; i++)
7330     {
7331         float x = gl_FragCoord.x;
7332         gl_FragColor = gl_FragColor + (x /= 2.0);
7333     }
7334     if (gl_FragColor.g == gl_FragColor.r &&
7335         gl_FragColor.b == gl_FragColor.r &&
7336         gl_FragColor.a == gl_FragColor.r)
7337     {
7338         gl_FragColor = vec4(0, 1, 0, 1);
7339     }
7340 })";
7341 
7342     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7343     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
7344     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7345 }
7346 
7347 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
7348 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)7349 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
7350 {
7351     constexpr char kVS[] = R"(#version 300 es
7352 
7353 in vec4 inputAttribute;
7354 
7355 flat out int v;
7356 
7357 void main()
7358 {
7359     v = 1;
7360     gl_Position = inputAttribute;
7361 })";
7362 
7363     constexpr char kFS[] = R"(#version 300 es
7364 
7365 precision highp float;
7366 out vec4 my_FragColor;
7367 
7368 flat in int v;
7369 
7370 void main()
7371 {
7372     my_FragColor = vec4(0, (true ? v : 0), 0, 1);
7373 })";
7374 
7375     ANGLE_GL_PROGRAM(program, kVS, kFS);
7376     drawQuad(program.get(), "inputAttribute", 0.5f);
7377     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7378 }
7379 
7380 // Verify that the link error message from last link failure is cleared when the new link is
7381 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)7382 TEST_P(GLSLTest, ClearLinkErrorLog)
7383 {
7384     constexpr char kVS[] = R"(attribute vec4 vert_in;
7385 varying vec4 vert_out;
7386 void main()
7387 {
7388     gl_Position = vert_in;
7389     vert_out = vert_in;
7390 })";
7391 
7392     constexpr char kFS[] = R"(precision mediump float;
7393 varying vec4 frag_in;
7394 void main()
7395 {
7396     gl_FragColor = frag_in;
7397 })";
7398 
7399     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
7400     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
7401 
7402     GLuint program = glCreateProgram();
7403 
7404     // The first time the program link fails because of lack of fragment shader.
7405     glAttachShader(program, vs);
7406     glLinkProgram(program);
7407     GLint linkStatus = GL_TRUE;
7408     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
7409     ASSERT_FALSE(linkStatus);
7410 
7411     const std::string &lackOfFragmentShader = QueryErrorMessage(program);
7412 
7413     // The second time the program link fails because of the mismatch of the varying types.
7414     glAttachShader(program, fs);
7415     glLinkProgram(program);
7416     linkStatus = GL_TRUE;
7417     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
7418     ASSERT_FALSE(linkStatus);
7419 
7420     const std::string &varyingTypeMismatch = QueryErrorMessage(program);
7421 
7422     EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
7423 
7424     glDetachShader(program, vs);
7425     glDetachShader(program, fs);
7426     glDeleteShader(vs);
7427     glDeleteShader(fs);
7428     glDeleteProgram(program);
7429 
7430     ASSERT_GL_NO_ERROR();
7431 }
7432 
7433 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)7434 TEST_P(GLSLTest, DrawAfterShaderLinkError)
7435 {
7436     constexpr char kVS[]    = R"(attribute vec4 position;
7437         varying vec4 vColor;
7438         void main()
7439         {
7440             vColor = vec4(0.0, 1.0, 0.0, 1.0);
7441             gl_Position = position;
7442         })";
7443     constexpr char kFS[]    = R"(precision mediump float;
7444         varying vec4 vColor;
7445         void main()
7446         {
7447             gl_FragColor = vColor;
7448         })";
7449     constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
7450 
7451     GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
7452 
7453     // Create bad fragment shader
7454     {
7455         const char *sourceArray[1] = {kBadFS};
7456         glShaderSource(fsBad, 1, sourceArray, nullptr);
7457         glCompileShader(fsBad);
7458 
7459         GLint compileResult;
7460         glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
7461         ASSERT_FALSE(compileResult);
7462     }
7463 
7464     ANGLE_GL_PROGRAM(program, kVS, kFS);
7465     GLuint fs = GetProgramShader(program.get(), GL_FRAGMENT_SHADER);
7466 
7467     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7468     glClear(GL_COLOR_BUFFER_BIT);
7469     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7470 
7471     glUseProgram(program.get());
7472     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7473     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7474     for (Vector3 &vertex : quadVertices)
7475     {
7476         vertex.z() = 0.5f;
7477     }
7478     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7479     glEnableVertexAttribArray(positionLocation);
7480     glDrawArrays(GL_TRIANGLES, 0, 6);
7481     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7482 
7483     glDetachShader(program.get(), fs);
7484     glAttachShader(program.get(), fsBad);
7485     glLinkProgram(program.get());
7486     GLint linkStatus = GL_TRUE;
7487     glGetProgramiv(program.get(), GL_LINK_STATUS, &linkStatus);
7488     ASSERT_FALSE(linkStatus);
7489 
7490     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7491     glClear(GL_COLOR_BUFFER_BIT);
7492     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7493 
7494     glDrawArrays(GL_TRIANGLES, 0, 6);
7495     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7496 }
7497 
7498 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)7499 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
7500 {
7501     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
7502 varying vec4 vertex_out;
7503 void main()
7504 {
7505     vertex_out = inputAttribute;
7506     gl_Position = inputAttribute;
7507 })";
7508 
7509     constexpr char kFS[] = R"(precision mediump float;
7510 varying float vertex_out;
7511 void main()
7512 {
7513     gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
7514 })";
7515 
7516     validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
7517 }
7518 
7519 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)7520 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
7521 {
7522     constexpr char kVS[] = R"(#version 300 es
7523 in vec4 inputAttribute;
7524 struct S {
7525     float val1;
7526     vec4 val2;
7527 };
7528 out S vertex_out;
7529 void main()
7530 {
7531     vertex_out.val2 = inputAttribute;
7532     vertex_out.val1 = inputAttribute[0];
7533     gl_Position = inputAttribute;
7534 })";
7535 
7536     constexpr char kFS[] = R"(#version 300 es
7537 precision mediump float;
7538 struct S {
7539     float val1;
7540     vec4 val3;
7541 };
7542 in S vertex_out;
7543 layout (location = 0) out vec4 frag_out;
7544 void main()
7545 {
7546     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
7547 })";
7548 
7549     validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
7550 }
7551 
7552 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)7553 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
7554 {
7555     constexpr char kVS[] = R"(#version 300 es
7556 in vec4 inputAttribute;
7557 struct S {
7558     float val1;
7559     vec4 val2;
7560 };
7561 out S vertex_out;
7562 void main()
7563 {
7564     vertex_out.val2 = inputAttribute;
7565     vertex_out.val1 = inputAttribute[0];
7566     gl_Position = inputAttribute;
7567 })";
7568 
7569     constexpr char kFS[] = R"(#version 300 es
7570 precision mediump float;
7571 struct S {
7572     float val1;
7573     vec2 val2;
7574 };
7575 in S vertex_out;
7576 layout (location = 0) out vec4 frag_out;
7577 void main()
7578 {
7579     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
7580 })";
7581 
7582     validateComponentsInErrorMessage(kVS, kFS, "Types",
7583                                      "varying 'vertex_out' member 'vertex_out.val2'");
7584 }
7585 
7586 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
7587 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)7588 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
7589 {
7590     constexpr char kVS[] = R"(
7591 struct T
7592 {
7593     vec2 t1;
7594     vec3 t2;
7595 };
7596 struct S {
7597     T val1;
7598     vec4 val2;
7599 };
7600 uniform S uni;
7601 
7602 attribute vec4 inputAttribute;
7603 varying vec4 vertex_out;
7604 void main()
7605 {
7606     vertex_out = uni.val2;
7607     gl_Position = inputAttribute;
7608 })";
7609 
7610     constexpr char kFS[] = R"(precision highp float;
7611 struct T
7612 {
7613     vec2 t1;
7614     vec3 t3;
7615 };
7616 struct S {
7617     T val1;
7618     vec4 val2;
7619 };
7620 uniform S uni;
7621 
7622 varying vec4 vertex_out;
7623 void main()
7624 {
7625     gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
7626 })";
7627 
7628     validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
7629 }
7630 
7631 // Validate error messages  when the link mismatch occurs on the type of a non-struct uniform block
7632 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)7633 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
7634 {
7635     constexpr char kVS[] = R"(#version 300 es
7636 uniform S {
7637     vec2 val1;
7638     vec4 val2;
7639 } uni;
7640 
7641 in vec4 inputAttribute;
7642 out vec4 vertex_out;
7643 void main()
7644 {
7645     vertex_out = uni.val2;
7646     gl_Position = inputAttribute;
7647 })";
7648 
7649     constexpr char kFS[] = R"(#version 300 es
7650 precision highp float;
7651 uniform S {
7652     vec2 val1;
7653     vec3 val2;
7654 } uni;
7655 
7656 in vec4 vertex_out;
7657 layout (location = 0) out vec4 frag_out;
7658 void main()
7659 {
7660     frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
7661 })";
7662 
7663     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
7664 }
7665 
7666 // Validate error messages  when the link mismatch occurs on the type of a member of a uniform block
7667 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)7668 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
7669 {
7670     constexpr char kVS[] = R"(#version 300 es
7671 struct T
7672 {
7673     vec2 t1;
7674     vec3 t2;
7675 };
7676 uniform S {
7677     T val1;
7678     vec4 val2;
7679 } uni;
7680 
7681 in vec4 inputAttribute;
7682 out vec4 vertex_out;
7683 void main()
7684 {
7685     vertex_out = uni.val2;
7686     gl_Position = inputAttribute;
7687 })";
7688 
7689     constexpr char kFS[] = R"(#version 300 es
7690 precision highp float;
7691 struct T
7692 {
7693     vec2 t1;
7694     vec4 t2;
7695 };
7696 uniform S {
7697     T val1;
7698     vec4 val2;
7699 } uni;
7700 
7701 in vec4 vertex_out;
7702 layout (location = 0) out vec4 frag_out;
7703 void main()
7704 {
7705     frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
7706 })";
7707 
7708     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
7709 }
7710 
7711 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
7712 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)7713 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
7714 {
7715     constexpr char kVS[] = R"(#version 300 es
7716 precision mediump float;
7717 
7718 void main()
7719 {
7720     gl_Position = vec4(0, 1, 0, 1);
7721 })";
7722 
7723     constexpr char kFS[] = R"(#version 300 es
7724 precision mediump float;
7725 in float foo;
7726 out vec4 my_FragColor;
7727 
7728 void main()
7729 {
7730     if (false)
7731     {
7732         float unreferenced = foo;
7733     }
7734     my_FragColor = vec4(0, 1, 0, 1);
7735 })";
7736 
7737     validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
7738 }
7739 
7740 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)7741 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
7742 {
7743     constexpr char kVS[] = R"(#version 300 es
7744 precision mediump float;
7745 in vec4 iv;
7746 out vec4 v;
7747 void main()
7748 {
7749     gl_Position = iv;
7750     v = iv;
7751 })";
7752 
7753     constexpr char kFS[] = R"(#version 300 es
7754 precision mediump float;
7755 in vec4 v;
7756 out vec4 color;
7757 void main()
7758 {
7759     color = true ? vec4(0.0) : v;
7760 })";
7761 
7762     ANGLE_GL_PROGRAM(program, kVS, kFS);
7763 }
7764 
7765 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)7766 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
7767 {
7768     constexpr char kVS[] = R"(#version 310 es
7769 precision highp float;
7770 in vec4 position;
7771 layout(location = 1) out vec4 shaderOutput;
7772 void main() {
7773     gl_Position = position;
7774     shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
7775 })";
7776 
7777     constexpr char kFS[] = R"(#version 310 es
7778 precision highp float;
7779 layout(location = 1) in vec4 shaderInput;
7780 out vec4 outColor;
7781 void main() {
7782     outColor = shaderInput;
7783 })";
7784 
7785     ANGLE_GL_PROGRAM(program, kVS, kFS);
7786     drawQuad(program, "position", 0.5f);
7787     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7788 }
7789 
7790 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)7791 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
7792 {
7793     // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
7794     // up red. http://crbug.com/838885
7795     ANGLE_SKIP_TEST_IF(IsD3D11());
7796 
7797     constexpr char kFS[] = R"(#version 300 es
7798 precision highp float;
7799 out vec4 my_FragColor;
7800 void main()
7801 {
7802     vec2 coord = gl_FragCoord.xy / 500.0;
7803     my_FragColor = vec4(1, 0, 0, 1);
7804     if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
7805     {
7806         my_FragColor = vec4(0, 1, 0, 1);
7807     }
7808 })";
7809 
7810     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7811     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7812     // Verify that all the corners of the rendered result are green.
7813     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7814     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7815     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
7816     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
7817 }
7818 
7819 // Verify that a link error is generated when the sum of the number of active image uniforms and
7820 // active shader storage blocks in a rendering pipeline exceeds
7821 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)7822 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
7823 {
7824     // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
7825     // D3D11 back-ends.
7826     ANGLE_SKIP_TEST_IF(IsD3D11());
7827 
7828     GLint maxVertexShaderStorageBlocks;
7829     GLint maxVertexImageUniforms;
7830     GLint maxFragmentShaderStorageBlocks;
7831     GLint maxFragmentImageUniforms;
7832     GLint maxCombinedShaderStorageBlocks;
7833     GLint maxCombinedImageUniforms;
7834     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
7835     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
7836     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
7837     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
7838     glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
7839     glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
7840 
7841     ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
7842     ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
7843     ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
7844     ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
7845 
7846     GLint vertexSSBOs   = maxVertexShaderStorageBlocks;
7847     GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
7848     // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
7849     if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
7850     {
7851         fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
7852     }
7853 
7854     GLint vertexImages   = maxVertexImageUniforms;
7855     GLint fragmentImages = maxFragmentImageUniforms;
7856     // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
7857     if (vertexImages + fragmentImages > maxCombinedImageUniforms)
7858     {
7859         vertexImages = maxCombinedImageUniforms - fragmentImages;
7860     }
7861 
7862     GLint maxDrawBuffers;
7863     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
7864 
7865     GLint maxCombinedShaderOutputResources;
7866     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
7867     ASSERT_GL_NO_ERROR();
7868 
7869     ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
7870                            maxDrawBuffers <=
7871                        maxCombinedShaderOutputResources);
7872 
7873     std::ostringstream vertexStream;
7874     vertexStream << "#version 310 es\n";
7875     for (int i = 0; i < vertexSSBOs; ++i)
7876     {
7877         vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
7878                      << "{\n"
7879                         "    float data;\n"
7880                         "} ssbo"
7881                      << i << ";\n";
7882     }
7883     vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
7884                  << "];\n";
7885     vertexStream << "void main()\n"
7886                     "{\n"
7887                     "    float val = 0.1;\n"
7888                     "    vec4 val2 = vec4(0.0);\n";
7889     for (int i = 0; i < vertexSSBOs; ++i)
7890     {
7891         vertexStream << "    val += ssbo" << i << ".data; \n";
7892     }
7893     for (int i = 0; i < vertexImages; ++i)
7894     {
7895         vertexStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
7896     }
7897     vertexStream << "    gl_Position = vec4(val, val2);\n"
7898                     "}\n";
7899 
7900     std::ostringstream fragmentStream;
7901     fragmentStream << "#version 310 es\n"
7902                    << "precision highp float;\n";
7903     for (int i = 0; i < fragmentSSBOs; ++i)
7904     {
7905         fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
7906                        << "{\n"
7907                           "    float data;\n"
7908                           "} ssbo"
7909                        << i << ";\n";
7910     }
7911     fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
7912                    << fragmentImages << "];\n";
7913     fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
7914 
7915     fragmentStream << "void main()\n"
7916                       "{\n"
7917                       "    float val = 0.1;\n"
7918                       "    vec4 val2 = vec4(0.0);\n";
7919     for (int i = 0; i < fragmentSSBOs; ++i)
7920     {
7921         fragmentStream << "    val += ssbo" << i << ".data; \n";
7922     }
7923     for (int i = 0; i < fragmentImages; ++i)
7924     {
7925         fragmentStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
7926     }
7927     for (int i = 0; i < maxDrawBuffers; ++i)
7928     {
7929         fragmentStream << "    foutput[" << i << "] = vec4(val, val2);\n";
7930     }
7931     fragmentStream << "}\n";
7932 
7933     GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
7934     EXPECT_EQ(0u, program);
7935 
7936     ASSERT_GL_NO_ERROR();
7937 }
7938 
7939 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
7940 // function works correctly.
TEST_P(GLSLTest_ES3,AssignAssignmentToSwizzled)7941 TEST_P(GLSLTest_ES3, AssignAssignmentToSwizzled)
7942 {
7943     constexpr char kFS[] = R"(#version 300 es
7944 precision highp float;
7945 out vec4 my_FragColor;
7946 
7947 uniform float uzero;
7948 
7949 vec3 fun(float s, float v)
7950 {
7951     vec3 r = vec3(0);
7952     if (s < 1.0) {
7953         r.x = r.y = r.z = v;
7954         return r;
7955     }
7956     return r;
7957 }
7958 
7959 void main()
7960 {
7961     my_FragColor.a = 1.0;
7962     my_FragColor.rgb = fun(uzero, 1.0);
7963 })";
7964 
7965     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7966     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7967     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
7968 }
7969 
7970 // Test a fragment shader that returns inside if (that being the only branch that actually gets
7971 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)7972 TEST_P(GLSLTest, IfElseIfAndReturn)
7973 {
7974     constexpr char kVS[] = R"(attribute vec4 a_position;
7975 varying vec2 vPos;
7976 void main()
7977 {
7978     gl_Position = a_position;
7979     vPos = a_position.xy;
7980 })";
7981 
7982     constexpr char kFS[] = R"(precision mediump float;
7983 varying vec2 vPos;
7984 void main()
7985 {
7986     if (vPos.x < 1.0) // This colors the whole canvas green
7987     {
7988         gl_FragColor = vec4(0, 1, 0, 1);
7989         return;
7990     }
7991     else if (vPos.x < 1.1) // This should have no effect
7992     {
7993         gl_FragColor = vec4(1, 0, 0, 1);
7994     }
7995 })";
7996 
7997     ANGLE_GL_PROGRAM(program, kVS, kFS);
7998     drawQuad(program.get(), "a_position", 0.5f);
7999     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8000 }
8001 
8002 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)8003 TEST_P(GLSLTest, PointCoordConsistency)
8004 {
8005     // AMD's OpenGL drivers may have the same issue. http://anglebug.com/1643
8006     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
8007     // http://anglebug.com/4092
8008     ANGLE_SKIP_TEST_IF(isSwiftshader());
8009 
8010     constexpr char kPointCoordVS[] = R"(attribute vec2 position;
8011 uniform vec2 viewportSize;
8012 void main()
8013 {
8014    gl_Position = vec4(position, 0, 1);
8015    gl_PointSize = viewportSize.x;
8016 })";
8017 
8018     constexpr char kPointCoordFS[] = R"(void main()
8019 {
8020     gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
8021 })";
8022 
8023     ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
8024     glUseProgram(program);
8025 
8026     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8027     ASSERT_NE(-1, uniLoc);
8028     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8029                 static_cast<GLfloat>(getWindowHeight()));
8030 
8031     // Draw to backbuffer.
8032     glClear(GL_COLOR_BUFFER_BIT);
8033     glDrawArrays(GL_POINTS, 0, 1);
8034     ASSERT_GL_NO_ERROR();
8035 
8036     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8037     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8038                  backbufferData.data());
8039 
8040     GLTexture tex;
8041     glBindTexture(GL_TEXTURE_2D, tex);
8042     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8043                  GL_UNSIGNED_BYTE, nullptr);
8044 
8045     GLFramebuffer fbo;
8046     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8047     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8048     ASSERT_GL_NO_ERROR();
8049     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8050 
8051     // Draw to user FBO.
8052     glClear(GL_COLOR_BUFFER_BIT);
8053     glDrawArrays(GL_POINTS, 0, 1);
8054     ASSERT_GL_NO_ERROR();
8055 
8056     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8057     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8058                  userFBOData.data());
8059 
8060     ASSERT_GL_NO_ERROR();
8061     ASSERT_EQ(userFBOData.size(), backbufferData.size());
8062     EXPECT_EQ(userFBOData, backbufferData);
8063 }
8064 
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)8065 bool SubrectEquals(const std::vector<GLColor> &bigArray,
8066                    const std::vector<GLColor> &smallArray,
8067                    int bigSize,
8068                    int offset,
8069                    int smallSize)
8070 {
8071     int badPixels = 0;
8072     for (int y = 0; y < smallSize; y++)
8073     {
8074         for (int x = 0; x < smallSize; x++)
8075         {
8076             int bigOffset   = (y + offset) * bigSize + x + offset;
8077             int smallOffset = y * smallSize + x;
8078             if (bigArray[bigOffset] != smallArray[smallOffset])
8079                 badPixels++;
8080         }
8081     }
8082     return badPixels == 0;
8083 }
8084 
8085 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)8086 TEST_P(GLSLTest, FragCoordConsistency)
8087 {
8088     constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
8089 void main()
8090 {
8091     gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
8092 })";
8093 
8094     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
8095     glUseProgram(program);
8096 
8097     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8098     ASSERT_NE(-1, uniLoc);
8099     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8100                 static_cast<GLfloat>(getWindowHeight()));
8101 
8102     // Draw to backbuffer.
8103     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8104     ASSERT_GL_NO_ERROR();
8105 
8106     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8107     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8108                  backbufferData.data());
8109 
8110     GLTexture tex;
8111     glBindTexture(GL_TEXTURE_2D, tex);
8112     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8113                  GL_UNSIGNED_BYTE, nullptr);
8114 
8115     GLFramebuffer fbo;
8116     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8117     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8118     ASSERT_GL_NO_ERROR();
8119     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8120 
8121     // Draw to user FBO.
8122     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8123     ASSERT_GL_NO_ERROR();
8124 
8125     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8126     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8127                  userFBOData.data());
8128 
8129     ASSERT_GL_NO_ERROR();
8130     ASSERT_EQ(userFBOData.size(), backbufferData.size());
8131     EXPECT_EQ(userFBOData, backbufferData)
8132         << "FragCoord should be the same to default and user FBO";
8133 
8134     // Repeat the same test but with a smaller viewport.
8135     ASSERT_EQ(getWindowHeight(), getWindowWidth());
8136     const int kQuarterSize = getWindowWidth() >> 2;
8137     glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
8138 
8139     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8140     glClear(GL_COLOR_BUFFER_BIT);
8141     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8142 
8143     std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
8144     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8145                  GL_UNSIGNED_BYTE, userFBOViewportData.data());
8146 
8147     glBindFramebuffer(GL_FRAMEBUFFER, 0);
8148     glClear(GL_COLOR_BUFFER_BIT);
8149     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8150 
8151     std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
8152     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8153                  GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
8154     ASSERT_GL_NO_ERROR();
8155     EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
8156         << "FragCoord should be the same to default and user FBO even with a custom viewport";
8157 
8158     // Check that the subrectangles are the same between the viewport and non-viewport modes.
8159     EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
8160                               kQuarterSize * 2));
8161     EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
8162                               kQuarterSize, kQuarterSize * 2));
8163 }
8164 
8165 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)8166 TEST_P(GLSLTest, DefinedInMacroSucceeds)
8167 {
8168     constexpr char kVS[] = R"(precision mediump float;
8169 attribute highp vec4 position;
8170 varying vec2 out0;
8171 
8172 void main()
8173 {
8174 #define AAA defined(BBB)
8175 
8176 #if !AAA
8177     out0 = vec2(0.0, 1.0);
8178 #else
8179     out0 = vec2(1.0, 0.0);
8180 #endif
8181     gl_Position = position;
8182 })";
8183 
8184     constexpr char kFS[] = R"(precision mediump float;
8185 varying vec2 out0;
8186 void main()
8187 {
8188     gl_FragColor = vec4(out0, 0, 1);
8189 })";
8190 
8191     ANGLE_GL_PROGRAM(program, kVS, kFS);
8192     drawQuad(program, "position", 0.5f);
8193     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8194 }
8195 
8196 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)8197 TEST_P(GLSLTest, DefinedInMacroWithUndef)
8198 {
8199     constexpr char kVS[] = R"(precision mediump float;
8200 attribute highp vec4 position;
8201 varying vec2 out0;
8202 
8203 void main()
8204 {
8205 #define BBB 1
8206 #define AAA defined(BBB)
8207 #undef BBB
8208 
8209 #if AAA
8210     out0 = vec2(1.0, 0.0);
8211 #else
8212     out0 = vec2(0.0, 1.0);
8213 #endif
8214     gl_Position = position;
8215 })";
8216 
8217     constexpr char kFS[] = R"(precision mediump float;
8218 varying vec2 out0;
8219 void main()
8220 {
8221     gl_FragColor = vec4(out0, 0, 1);
8222 })";
8223 
8224     ANGLE_GL_PROGRAM(program, kVS, kFS);
8225     drawQuad(program, "position", 0.5f);
8226     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8227 }
8228 
8229 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)8230 TEST_P(GLSLTest, DefinedAfterMacroUsage)
8231 {
8232     constexpr char kVS[] = R"(precision mediump float;
8233 attribute highp vec4 position;
8234 varying vec2 out0;
8235 
8236 void main()
8237 {
8238 #define AAA defined(BBB)
8239 #define BBB 1
8240 
8241 #if AAA
8242     out0 = vec2(0.0, 1.0);
8243 #else
8244     out0 = vec2(1.0, 0.0);
8245 #endif
8246     gl_Position = position;
8247 })";
8248 
8249     constexpr char kFS[] = R"(precision mediump float;
8250 varying vec2 out0;
8251 void main()
8252 {
8253     gl_FragColor = vec4(out0, 0, 1);
8254 })";
8255 
8256     ANGLE_GL_PROGRAM(program, kVS, kFS);
8257     drawQuad(program, "position", 0.5f);
8258     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8259 }
8260 
8261 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)8262 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
8263 {
8264     constexpr char kVS[] = R"(precision mediump float;
8265 attribute highp vec4 position;
8266 varying vec2 out0;
8267 
8268 void main()
8269 {
8270 #define BBB 1
8271 #define AAA(defi, ned) defi ## ned(BBB)
8272 
8273 #if AAA(defi, ned)
8274     out0 = vec2(0.0, 1.0);
8275 #else
8276     out0 = vec2(1.0, 0.0);
8277 #endif
8278     gl_Position = position;
8279 })";
8280 
8281     constexpr char kFS[] = R"(precision mediump float;
8282 varying vec2 out0;
8283 void main()
8284 {
8285     gl_FragColor = vec4(out0, 0, 1);
8286 })";
8287 
8288     GLuint program = CompileProgram(kVS, kFS);
8289     EXPECT_EQ(0u, program);
8290     glDeleteProgram(program);
8291 }
8292 
8293 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)8294 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
8295 {
8296     constexpr char kVS[] = R"(precision mediump float;
8297 attribute highp vec4 position;
8298 varying vec2 out0;
8299 
8300 void main()
8301 {
8302 #define BBB 1
8303 #define AAA(defined) defined(BBB)
8304 
8305 #if AAA(defined)
8306     out0 = vec2(0.0, 1.0);
8307 #else
8308     out0 = vec2(1.0, 0.0);
8309 #endif
8310     gl_Position = position;
8311 })";
8312 
8313     constexpr char kFS[] = R"(precision mediump float;
8314 varying vec2 out0;
8315 void main()
8316 {
8317     gl_FragColor = vec4(out0, 0, 1);
8318 })";
8319 
8320     GLuint program = CompileProgram(kVS, kFS);
8321     EXPECT_EQ(0u, program);
8322     glDeleteProgram(program);
8323 }
8324 
8325 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)8326 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
8327 {
8328     constexpr char kVS[] = R"(precision mediump float;
8329 attribute highp vec4 position;
8330 varying float out0;
8331 
8332 void main()
8333 {
8334 #define AAA defined(BBB)
8335 
8336 #if !AAA
8337     out0 = 1.0;
8338 #else
8339     out0 = 0.0;
8340 #endif
8341     gl_Position = dEQP_Position;
8342 })";
8343 
8344     constexpr char kFS[] = R"(precision mediump float;
8345 varying float out0;
8346 void main()
8347 {
8348     gl_FragColor = vec4(out0, 0, 0, 1);
8349 })";
8350 
8351     GLuint program = CompileProgram(kVS, kFS);
8352     EXPECT_EQ(0u, program);
8353     glDeleteProgram(program);
8354 }
8355 
8356 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)8357 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
8358 {
8359     constexpr char kVS[] = R"(void main()
8360 {
8361     gl_Position = vec4(1, 0, 0, 1);
8362 })";
8363 
8364     constexpr char kFS[] = R"(#if defined(GL_ES)
8365 precision mediump float;
8366 void main()
8367 {
8368     gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
8369 }
8370 #else
8371 foo
8372 #endif
8373 )";
8374 
8375     ANGLE_GL_PROGRAM(program, kVS, kFS);
8376 }
8377 
8378 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)8379 TEST_P(GLSLTest, ValidIndexClampES100)
8380 {
8381     // http://anglebug.com/6027
8382     ANGLE_SKIP_TEST_IF(IsD3D9());
8383 
8384     constexpr char kFS[] = R"(
8385 precision mediump float;
8386 uniform int u;
8387 uniform mat4 m[2];
8388 void main()
8389 {
8390     gl_FragColor = vec4(m[u][1].xyz, 1);
8391 }
8392 )";
8393 
8394     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8395     glUseProgram(program);
8396 
8397     GLint uniformLocation = glGetUniformLocation(program, "u");
8398     ASSERT_NE(-1, uniformLocation);
8399 
8400     GLint matrixLocation = glGetUniformLocation(program, "m");
8401     ASSERT_NE(matrixLocation, -1);
8402     const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
8403                                              0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
8404                                              1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
8405                                              0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
8406     glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
8407 
8408     glUniform1i(uniformLocation, 1);
8409     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8410     EXPECT_GL_NO_ERROR();
8411 
8412     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8413 }
8414 
8415 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)8416 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
8417 {
8418     constexpr char kFS[] = R"(#version 300 es
8419 precision mediump float;
8420 out vec4 color;
8421 uniform int u;
8422 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
8423 void main()
8424 {
8425     color = vec4(m[u][2].xyz, 1);
8426 }
8427 )";
8428 
8429     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8430     glUseProgram(program);
8431 
8432     GLint uniformLocation = glGetUniformLocation(program, "u");
8433     ASSERT_NE(-1, uniformLocation);
8434 
8435     glUniform1i(uniformLocation, 2);
8436     EXPECT_GL_NO_ERROR();
8437     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8438     EXPECT_GL_NO_ERROR();
8439 
8440     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
8441 }
8442 
8443 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)8444 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
8445 {
8446     constexpr char kFS[] = R"(#version 300 es
8447 precision mediump float;
8448 
8449 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
8450 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);
8451 
8452 out vec4 color;
8453 
8454 void main()
8455 {
8456     mat4x2 result = matrixCompMult(matA, matB);
8457     vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
8458     if (vresult == vec2(4.0, 4.0))
8459     {
8460         color = vec4(0.0, 1.0, 0.0, 1.0);
8461     }
8462     else
8463     {
8464         color = vec4(1.0, 0.0, 0.0, 1.0);
8465     }
8466 })";
8467 
8468     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8469     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8470     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8471 }
8472 
8473 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)8474 TEST_P(GLSLTest_ES3, InitSameNameArray)
8475 {
8476     constexpr char kFS[] = R"(#version 300 es
8477       precision highp float;
8478       out vec4 my_FragColor;
8479 
8480       void main()
8481       {
8482           float arr[2] = float[2](1.0, 1.0);
8483           {
8484               float arr[2] = arr;
8485               my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
8486           }
8487       })";
8488 
8489     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8490     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8491     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8492 }
8493 
8494 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)8495 TEST_P(GLSLTest, FragData)
8496 {
8497     // Ensures that we don't regress and emit Vulkan layer warnings.
8498     // TODO(jonahr): http://anglebug.com/3900 - Remove check once warnings are cleaned up
8499     if (IsVulkan())
8500     {
8501         treatPlatformWarningsAsErrors();
8502     }
8503 
8504     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
8505     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8506     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8507     EXPECT_GL_NO_ERROR();
8508     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8509 }
8510 
8511 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)8512 TEST_P(GLSLTest, MemoryExhaustedTest)
8513 {
8514     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
8515     GLuint program =
8516         CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
8517     EXPECT_NE(0u, program);
8518 }
8519 
8520 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)8521 TEST_P(GLSLTest, InactiveSamplersInStruct)
8522 {
8523     constexpr char kVS[] = R"(attribute vec4 a_position;
8524 void main() {
8525   gl_Position = a_position;
8526 })";
8527 
8528     constexpr char kFS[] = R"(precision highp float;
8529 struct S
8530 {
8531     vec4 v;
8532     sampler2D t[10];
8533 };
8534 uniform S s;
8535 void main() {
8536   gl_FragColor = s.v;
8537 })";
8538 
8539     ANGLE_GL_PROGRAM(program, kVS, kFS);
8540 
8541     drawQuad(program, "a_position", 0.5f);
8542 }
8543 
8544 // Helper functions for MixedRowAndColumnMajorMatrices* tests
8545 
8546 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)8547 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
8548 {
8549     return (value + alignment - 1) & ~(alignment - 1);
8550 }
8551 
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)8552 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
8553 {
8554     unsigned int outputInitData = 0;
8555     glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
8556     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
8557     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
8558     EXPECT_GL_NO_ERROR();
8559 }
8560 
8561 // Fill provided buffer with matrices based on the given dimensions.  The buffer should be large
8562 // 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)8563 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
8564                     const bool matrixIsColMajor[],
8565                     size_t matrixCount,
8566                     float data[],
8567                     bool isStd430,
8568                     bool isTransposed)
8569 {
8570     size_t offset = 0;
8571     for (size_t m = 0; m < matrixCount; ++m)
8572     {
8573         uint32_t cols   = matrixDims[m].first;
8574         uint32_t rows   = matrixDims[m].second;
8575         bool isColMajor = matrixIsColMajor[m] != isTransposed;
8576 
8577         uint32_t arraySize              = isColMajor ? cols : rows;
8578         uint32_t arrayElementComponents = isColMajor ? rows : cols;
8579         // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
8580         // MixedRowAndColumnMajorMatrices* tests don't use).  With std430, small matrices can have
8581         // a stride of 2 between rows/columns.
8582         uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
8583 
8584         offset = RoundUpPow2(offset, stride);
8585 
8586         for (uint32_t i = 0; i < arraySize; ++i)
8587         {
8588             for (uint32_t c = 0; c < arrayElementComponents; ++c)
8589             {
8590                 uint32_t row = isColMajor ? c : i;
8591                 uint32_t col = isColMajor ? i : c;
8592 
8593                 data[offset + i * stride + c] = col * 4 + row;
8594             }
8595         }
8596 
8597         offset += arraySize * stride;
8598     }
8599     return offset;
8600 }
8601 
8602 // Initialize and bind the buffer.
8603 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)8604 void InitBuffer(GLuint program,
8605                 const char *name,
8606                 GLuint buffer,
8607                 uint32_t bindingIndex,
8608                 const T data[],
8609                 uint32_t dataSize,
8610                 bool isUniform)
8611 {
8612     GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
8613 
8614     glBindBufferBase(bindPoint, bindingIndex, buffer);
8615     glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
8616 
8617     if (isUniform)
8618     {
8619         GLint blockIndex = glGetUniformBlockIndex(program, name);
8620         glUniformBlockBinding(program, blockIndex, bindingIndex);
8621     }
8622 }
8623 
8624 // Verify that buffer data is written by the shader as expected.
8625 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)8626 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
8627 {
8628     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
8629 
8630     const T *ptr = reinterpret_cast<const T *>(
8631         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize, GL_MAP_READ_BIT));
8632 
8633     bool isCorrect = memcmp(ptr, data, dataSize * sizeof(*data)) == 0;
8634     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8635 
8636     return isCorrect;
8637 }
8638 
8639 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)8640 bool VerifySuccess(GLuint buffer)
8641 {
8642     uint32_t success = 1;
8643     return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
8644 }
8645 
8646 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
8647 // both std140 and std430 layouts.  Tests many combinations of std140 vs std430, struct being used
8648 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
8649 // nested structs, matrix arrays, inout parameters etc.
8650 //
8651 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)8652 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
8653 {
8654     GLint maxComputeShaderStorageBlocks;
8655     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
8656 
8657     // The test uses 9 SSBOs.  Skip if not that many are supported.
8658     ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
8659 
8660     // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
8661     // UBO also see it as row-major despite explicit column-major qualifier.
8662     // http://anglebug.com/3830
8663     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
8664 
8665     // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
8666     // read column-major despite explicit row-major qualifier.  http://anglebug.com/3837
8667     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
8668 
8669     // Fails on windows AMD on GL: http://anglebug.com/3838
8670     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
8671 
8672     // Fails to compile the shader on Android.  http://anglebug.com/3839
8673     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
8674 
8675     // Fails on assertion in translation to D3D.  http://anglebug.com/3841
8676     ANGLE_SKIP_TEST_IF(IsD3D11());
8677 
8678     // Fails on SSBO validation on Android/Vulkan.  http://anglebug.com/3840
8679     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
8680 
8681     // Fails input verification as well as std140 SSBO validation.  http://anglebug.com/3844
8682     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
8683 
8684     // Fails on ARM on Vulkan.  http://anglebug.com/4492
8685     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
8686 
8687     constexpr char kCS[] = R"(#version 310 es
8688 precision highp float;
8689 layout(local_size_x=1) in;
8690 
8691 struct Inner
8692 {
8693     mat3x4 m3c4r;
8694     mat4x3 m4c3r;
8695 };
8696 
8697 struct Matrices
8698 {
8699     mat2 m2c2r;
8700     mat2x3 m2c3r[2];
8701     mat3x2 m3c2r;
8702     Inner inner;
8703 };
8704 
8705 // For simplicity, the layouts are either of:
8706 // - col-major mat4, row-major rest
8707 // - row-major mat4, col-major rest
8708 //
8709 // The former is tagged with c, the latter with r.
8710 layout(std140, column_major) uniform Ubo140c
8711 {
8712     mat4 m4c4r;
8713     layout(row_major) Matrices m;
8714 } ubo140cIn;
8715 
8716 layout(std140, row_major) uniform Ubo140r
8717 {
8718     mat4 m4c4r;
8719     layout(column_major) Matrices m;
8720 } ubo140rIn;
8721 
8722 layout(std140, row_major, binding = 0) buffer Ssbo140c
8723 {
8724     layout(column_major) mat4 m4c4r;
8725     Matrices m;
8726 } ssbo140cIn;
8727 
8728 layout(std140, column_major, binding = 1) buffer Ssbo140r
8729 {
8730     layout(row_major) mat4 m4c4r;
8731     Matrices m;
8732 } ssbo140rIn;
8733 
8734 layout(std430, column_major, binding = 2) buffer Ssbo430c
8735 {
8736     mat4 m4c4r;
8737     layout(row_major) Matrices m;
8738 } ssbo430cIn;
8739 
8740 layout(std430, row_major, binding = 3) buffer Ssbo430r
8741 {
8742     mat4 m4c4r;
8743     layout(column_major) Matrices m;
8744 } ssbo430rIn;
8745 
8746 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
8747 {
8748     layout(column_major) mat4 m4c4r;
8749     Matrices m;
8750 } ssbo140cOut;
8751 
8752 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
8753 {
8754     layout(row_major) mat4 m4c4r;
8755     Matrices m;
8756 } ssbo140rOut;
8757 
8758 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
8759 {
8760     mat4 m4c4r;
8761     layout(row_major) Matrices m;
8762 } ssbo430cOut;
8763 
8764 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
8765 {
8766     mat4 m4c4r;
8767     layout(column_major) Matrices m;
8768 } ssbo430rOut;
8769 
8770 layout(std140, binding = 8) buffer Result
8771 {
8772     uint success;
8773 } resultOut;
8774 
8775 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
8776 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
8777 
8778 #define VERIFY_IN(result, mat, cols, rows)                  \
8779     EXPECT(result, mat[0].x, 0.0);                          \
8780     EXPECT(result, mat[0][1], 1.0);                         \
8781     EXPECTV(result, mat[0].xy, vec2(0, 1));                 \
8782     EXPECTV(result, mat[1].xy, vec2(4, 5));                 \
8783     for (int c = 0; c < cols; ++c)                          \
8784     {                                                       \
8785         for (int r = 0; r < rows; ++r)                      \
8786         {                                                   \
8787             EXPECT(result, mat[c][r], float(c * 4 + r));    \
8788         }                                                   \
8789     }
8790 
8791 #define COPY(matIn, matOut, cols, rows)     \
8792     matOut = matOut + matIn;                \
8793     /* random operations for testing */     \
8794     matOut[0].x += matIn[0].x + matIn[1].x; \
8795     matOut[0].x -= matIn[1].x;              \
8796     matOut[0][1] += matIn[0][1];            \
8797     matOut[1] += matIn[1];                  \
8798     matOut[1].xy -= matIn[1].xy;            \
8799     /* undo the above to get back matIn */  \
8800     matOut[0].x -= matIn[0].x;              \
8801     matOut[0][1] -= matIn[0][1];            \
8802     matOut[1] -= matIn[1];                  \
8803     matOut[1].xy += matIn[1].xy;
8804 
8805 bool verifyMatrices(in Matrices m)
8806 {
8807     bool result = true;
8808     VERIFY_IN(result, m.m2c2r, 2, 2);
8809     VERIFY_IN(result, m.m2c3r[0], 2, 3);
8810     VERIFY_IN(result, m.m2c3r[1], 2, 3);
8811     VERIFY_IN(result, m.m3c2r, 3, 2);
8812     VERIFY_IN(result, m.inner.m3c4r, 3, 4);
8813     VERIFY_IN(result, m.inner.m4c3r, 4, 3);
8814     return result;
8815 }
8816 
8817 mat4 copyMat4(in mat4 m)
8818 {
8819     return m;
8820 }
8821 
8822 void copyMatrices(in Matrices mIn, inout Matrices mOut)
8823 {
8824     COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
8825     COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
8826     COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
8827     COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
8828     COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
8829     COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
8830 }
8831 
8832 void main()
8833 {
8834     bool result = true;
8835 
8836     VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
8837     VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
8838     EXPECT(result, verifyMatrices(ubo140cIn.m), true);
8839 
8840     VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
8841     VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
8842     EXPECT(result, verifyMatrices(ubo140rIn.m), true);
8843 
8844     VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
8845     VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
8846     EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
8847 
8848     VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
8849     VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
8850     EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
8851 
8852     VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
8853     VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
8854     EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
8855 
8856     VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
8857     VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
8858     EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
8859 
8860     // Only assign to SSBO from a single invocation.
8861     if (gl_GlobalInvocationID.x == 0u)
8862     {
8863         ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
8864         copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
8865         ssbo140cOut.m.m2c3r[1] = mat2x3(0);
8866         COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
8867 
8868         ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
8869         copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
8870         ssbo140rOut.m.inner.m3c4r = mat3x4(0);
8871         COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
8872 
8873         ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
8874         copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
8875         ssbo430cOut.m.m3c2r = mat3x2(0);
8876         COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
8877 
8878         ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
8879         copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
8880         ssbo430rOut.m.inner.m4c3r = mat4x3(0);
8881         COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
8882 
8883         resultOut.success = uint(result);
8884     }
8885 })";
8886 
8887     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
8888     EXPECT_GL_NO_ERROR();
8889 
8890     constexpr size_t kMatrixCount                                     = 7;
8891     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
8892         {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
8893     };
8894     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
8895         true, false, false, false, false, false, false,
8896     };
8897 
8898     float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
8899     float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
8900     float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
8901     float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
8902     float dataZeros[kMatrixCount * 4 * 4]          = {};
8903 
8904     const uint32_t sizeStd140ColMajor =
8905         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
8906     const uint32_t sizeStd140RowMajor =
8907         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
8908     const uint32_t sizeStd430ColMajor =
8909         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
8910     const uint32_t sizeStd430RowMajor =
8911         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
8912 
8913     GLBuffer uboStd140ColMajor, uboStd140RowMajor;
8914     GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
8915     GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
8916     GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
8917     GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
8918 
8919     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
8920                true);
8921     InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
8922                true);
8923     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
8924                false);
8925     InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
8926                false);
8927     InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
8928                false);
8929     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
8930                false);
8931     InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
8932                false);
8933     InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
8934                false);
8935     InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
8936                false);
8937     InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
8938                false);
8939     EXPECT_GL_NO_ERROR();
8940 
8941     GLBuffer outputBuffer;
8942     CreateOutputBuffer(&outputBuffer, 8);
8943 
8944     glUseProgram(program);
8945     glDispatchCompute(1, 1, 1);
8946     EXPECT_GL_NO_ERROR();
8947     EXPECT_TRUE(VerifySuccess(outputBuffer));
8948 
8949     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
8950     EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
8951     EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
8952     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
8953 }
8954 
8955 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)8956 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
8957 {
8958     // Fails to compile the shader on Android: http://anglebug.com/3839
8959     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
8960 
8961     // http://anglebug.com/3837
8962     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
8963 
8964     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
8965     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
8966 
8967     // Fails on windows AMD on GL: http://anglebug.com/3838
8968     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
8969 
8970     // Fails on D3D due to mistranslation: http://anglebug.com/3841
8971     ANGLE_SKIP_TEST_IF(IsD3D11());
8972 
8973     constexpr char kFS[] = R"(#version 300 es
8974 precision highp float;
8975 out vec4 outColor;
8976 
8977 layout(std140, column_major) uniform Ubo
8978 {
8979     mat4 m1;
8980     layout(row_major) mat4 m2;
8981 } ubo[3];
8982 
8983 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
8984 
8985 #define VERIFY_IN(result, mat, cols, rows)                  \
8986     for (int c = 0; c < cols; ++c)                          \
8987     {                                                       \
8988         for (int r = 0; r < rows; ++r)                      \
8989         {                                                   \
8990             EXPECT(result, mat[c][r], float(c * 4 + r));    \
8991         }                                                   \
8992     }
8993 
8994 void main()
8995 {
8996     bool result = true;
8997 
8998     VERIFY_IN(result, ubo[0].m1, 4, 4);
8999     VERIFY_IN(result, ubo[0].m2, 4, 4);
9000 
9001     VERIFY_IN(result, ubo[1].m1, 4, 4);
9002     VERIFY_IN(result, ubo[1].m2, 4, 4);
9003 
9004     VERIFY_IN(result, ubo[2].m1, 4, 4);
9005     VERIFY_IN(result, ubo[2].m2, 4, 4);
9006 
9007     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9008 })";
9009 
9010     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9011     EXPECT_GL_NO_ERROR();
9012 
9013     constexpr size_t kMatrixCount                                     = 2;
9014     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9015         {4, 4},
9016         {4, 4},
9017     };
9018     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9019         true,
9020         false,
9021     };
9022 
9023     float data[kMatrixCount * 4 * 4] = {};
9024 
9025     const uint32_t size =
9026         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9027 
9028     GLBuffer ubos[3];
9029 
9030     InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
9031     InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
9032     InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
9033 
9034     EXPECT_GL_NO_ERROR();
9035 
9036     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9037     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9038 }
9039 
9040 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)9041 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
9042 {
9043     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
9044     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
9045 
9046     // Fails on D3D due to mistranslation: http://anglebug.com/3841
9047     ANGLE_SKIP_TEST_IF(IsD3D11());
9048 
9049     constexpr char kFS[] = R"(#version 300 es
9050 precision highp float;
9051 out vec4 outColor;
9052 
9053 struct S
9054 {
9055     mat2x3 m2[3];
9056 };
9057 
9058 layout(std140, column_major) uniform Ubo
9059 {
9060     mat4 m1;
9061     layout(row_major) S s[2];
9062 } ubo;
9063 
9064 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
9065 
9066 #define VERIFY_IN(result, mat, cols, rows)                  \
9067     for (int c = 0; c < cols; ++c)                          \
9068     {                                                       \
9069         for (int r = 0; r < rows; ++r)                      \
9070         {                                                   \
9071             EXPECT(result, mat[c][r], float(c * 4 + r));    \
9072         }                                                   \
9073     }
9074 
9075 bool verify2x3(mat2x3 mat)
9076 {
9077     bool result = true;
9078 
9079     for (int c = 0; c < 2; ++c)
9080     {
9081         for (int r = 0; r < 3; ++r)
9082         {
9083             EXPECT(result, mat[c][r], float(c * 4 + r));
9084         }
9085     }
9086 
9087     return result;
9088 }
9089 
9090 void main()
9091 {
9092     bool result = true;
9093 
9094     int sideEffect = 0;
9095     VERIFY_IN(result, ubo.m1, 4, 4);
9096     EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
9097     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
9098     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
9099 
9100     EXPECT(result, sideEffect, 2);
9101 
9102     EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
9103     EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
9104     EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
9105 
9106     EXPECT(result, sideEffect, 4);
9107 
9108     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9109 })";
9110 
9111     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9112     EXPECT_GL_NO_ERROR();
9113 
9114     constexpr size_t kMatrixCount                                     = 7;
9115     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9116         {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
9117     };
9118     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9119         true, false, false, false, false, false, false,
9120     };
9121 
9122     float data[kMatrixCount * 4 * 4] = {};
9123 
9124     const uint32_t size =
9125         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9126 
9127     GLBuffer ubo;
9128     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
9129 
9130     EXPECT_GL_NO_ERROR();
9131 
9132     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9133     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9134 }
9135 
9136 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)9137 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
9138 {
9139     // http://anglebug.com/3837
9140     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
9141 
9142     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
9143     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
9144     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
9145 
9146     constexpr char kFS[] = R"(#version 300 es
9147 precision highp float;
9148 out vec4 outColor;
9149 
9150 layout(std140, column_major) uniform Ubo
9151 {
9152     mat4 m1;
9153     layout(row_major) mat4 m2[2];
9154 } ubo;
9155 
9156 void main()
9157 {
9158     bool result = true;
9159 
9160     int x = 0;
9161     if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
9162     {
9163         result = true;
9164     }
9165     else
9166     {
9167         result = false;
9168     }
9169 
9170     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9171 })";
9172 
9173     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9174     EXPECT_GL_NO_ERROR();
9175 
9176     constexpr size_t kMatrixCount                                     = 3;
9177     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9178         {4, 4},
9179         {4, 4},
9180         {4, 4},
9181     };
9182     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
9183 
9184     float data[kMatrixCount * 4 * 4] = {};
9185 
9186     const uint32_t size =
9187         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9188 
9189     GLBuffer ubo;
9190     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
9191 
9192     EXPECT_GL_NO_ERROR();
9193 
9194     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9195     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9196 }
9197 
9198 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)9199 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
9200 {
9201     // Fails on Android: http://anglebug.com/3839
9202     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
9203 
9204     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
9205     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
9206     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
9207 
9208     constexpr char kFS[] = R"(#version 300 es
9209 precision highp float;
9210 out vec4 outColor;
9211 
9212 layout(std140, column_major) uniform Ubo
9213 {
9214     mat4 m1;
9215     layout(row_major) mat4 m2[2];
9216 } ubo;
9217 
9218 void main()
9219 {
9220     bool result = true;
9221 
9222     int x = 0;
9223     if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
9224     {
9225         // First x == 1 should prevent the side effect of the second expression (x = 1) from
9226         // being executed.  If x = 1 is run before the if, the condition of the if would be true,
9227         // which is a failure.
9228         result = false;
9229     }
9230     if (x == 1)
9231     {
9232         result = false;
9233     }
9234 
9235     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9236 })";
9237 
9238     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9239     EXPECT_GL_NO_ERROR();
9240 
9241     constexpr size_t kMatrixCount                                     = 3;
9242     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9243         {4, 4},
9244         {4, 4},
9245         {4, 4},
9246     };
9247     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
9248 
9249     float data[kMatrixCount * 4 * 4] = {};
9250 
9251     const uint32_t size =
9252         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9253 
9254     GLBuffer ubo;
9255     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
9256 
9257     EXPECT_GL_NO_ERROR();
9258 
9259     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9260     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9261 }
9262 
9263 // Test that dynamic indexing of swizzled l-values should work.
9264 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)9265 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
9266 {
9267     // The shader first assigns v.x to v.z (1.0)
9268     // Then v.y to v.y (2.0)
9269     // Then v.z to v.x (1.0)
9270     constexpr char kFS[] = R"(#version 300 es
9271 precision highp float;
9272 out vec4 my_FragColor;
9273 void main() {
9274     vec3 v = vec3(1.0, 2.0, 3.0);
9275     for (int i = 0; i < 3; i++) {
9276         v.zyx[i] = v[i];
9277     }
9278     my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9279 })";
9280 
9281     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9282     EXPECT_GL_NO_ERROR();
9283     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9284     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9285 }
9286 
9287 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)9288 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
9289 {
9290     constexpr char kFS[] = R"(#version 300 es
9291 precision mediump float;
9292 out vec4 color;
9293 
9294 vec4 f(vec4 c)
9295 {
9296     return c;
9297     // dead code
9298     c = vec4(0, 0, 1, 1);
9299     return c;
9300 }
9301 
9302 void main()
9303 {
9304     vec4 result = vec4(0, 0.5, 0, 1);
9305     int var = int(result.y * 2.2);
9306 
9307     {
9308         if (result.x > 1.0)
9309         {
9310             discard;
9311             // dead code
9312             result = vec4(1, 0, 0, 1);
9313         }
9314         for (int i = 0; i < 3; ++i)
9315         {
9316             if (i < 2)
9317             {
9318                 result = f(result);
9319                 continue;
9320                 // dead code
9321                 result = vec4(1, 0, 1, 1);
9322             }
9323             result = f(result);
9324             break;
9325             // dead code
9326             result = vec4(1, 0, 1, 0);
9327         }
9328         while (true)
9329         {
9330             if (result.x > -1.0)
9331             {
9332                 {
9333                     result = f(result);
9334                     {
9335                         break;
9336                         // dead code
9337                         result = vec4(1, 0, 0, 0);
9338                     }
9339                     // dead code
9340                     for (int j = 0; j < 3; ++j)
9341                     {
9342                         if (j > 1) continue;
9343                         result = vec4(0, 0, 1, 0);
9344                         color = vec4(0.5, 0, 0.5, 0.5);
9345                         return;
9346                     }
9347                 }
9348                 // dead code
9349                 result = vec4(0.5, 0, 0, 0);
9350             }
9351         }
9352         switch (var)
9353         {
9354         case 2:
9355             return;
9356             // dead code
9357             color = vec4(0.25, 0, 0.25, 0.25);
9358         case 1:
9359             {
9360                 // Make sure this path is not pruned due to the return in the previous case.
9361                 result.y += 0.5;
9362                 break;
9363                 // dead code
9364                 color = vec4(0.25, 0, 0, 0);
9365             }
9366             // dead code
9367             color = vec4(0, 0, 0.25, 0);
9368             break;
9369         default:
9370             break;
9371         }
9372 
9373         color = result;
9374         return;
9375         // dead code
9376         color = vec4(0, 0, 0.5, 0);
9377     }
9378     // dead code
9379     color = vec4(0, 0, 0, 0.5);
9380 })";
9381 
9382     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9383 
9384     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9385     EXPECT_GL_NO_ERROR();
9386 
9387     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9388 }
9389 
9390 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
9391 // make sure they are all linked ok.  The front-end sorts these resources and traverses the list of
9392 // "uniforms" to find the range for each resource.  A bug there was causing some resource ranges to
9393 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)9394 TEST_P(GLSLTest_ES31, MixOfAllResources)
9395 {
9396     // http://anglebug.com/5072
9397     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
9398 
9399     constexpr char kComputeShader[] = R"(#version 310 es
9400 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9401 layout(binding = 1, std430) buffer Output {
9402   uint ubo_value;
9403   uint default_value;
9404   uint sampler_value;
9405   uint ac_value;
9406   uint image_value;
9407 } outbuf;
9408 uniform Input {
9409   uint input_value;
9410 } inbuf;
9411 uniform uint default_uniform;
9412 uniform sampler2D smplr;
9413 layout(binding=0) uniform atomic_uint ac;
9414 layout(r32ui) uniform highp readonly uimage2D image;
9415 
9416 void main(void)
9417 {
9418   outbuf.ubo_value = inbuf.input_value;
9419   outbuf.default_value = default_uniform;
9420   outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
9421   outbuf.ac_value = atomicCounterIncrement(ac);
9422   outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
9423 }
9424 )";
9425     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9426     EXPECT_GL_NO_ERROR();
9427 
9428     glUseProgram(program);
9429 
9430     unsigned int inputData = 89u;
9431     GLBuffer inputBuffer;
9432     glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
9433     glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
9434     GLuint inputBufferIndex = glGetUniformBlockIndex(program.get(), "Input");
9435     ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
9436     glUniformBlockBinding(program.get(), inputBufferIndex, 0);
9437     glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
9438 
9439     unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
9440                                       0x13579BDFu};
9441     GLBuffer outputBuffer;
9442     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9443     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
9444     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9445     EXPECT_GL_NO_ERROR();
9446 
9447     unsigned int uniformData = 456u;
9448     GLint uniformLocation    = glGetUniformLocation(program, "default_uniform");
9449     ASSERT_NE(uniformLocation, -1);
9450     glUniform1ui(uniformLocation, uniformData);
9451 
9452     unsigned int acData = 2u;
9453     GLBuffer atomicCounterBuffer;
9454     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9455     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9456     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9457     EXPECT_GL_NO_ERROR();
9458 
9459     unsigned int imageData = 33u;
9460     GLTexture image;
9461     glBindTexture(GL_TEXTURE_2D, image);
9462     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
9463     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
9464     glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
9465     EXPECT_GL_NO_ERROR();
9466 
9467     GLColor textureData(127, 18, 189, 211);
9468     GLTexture texture;
9469     glBindTexture(GL_TEXTURE_2D, texture);
9470     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
9471     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9472     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9473     ASSERT_GL_NO_ERROR();
9474 
9475     glDispatchCompute(1, 1, 1);
9476     EXPECT_GL_NO_ERROR();
9477 
9478     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9479 
9480     // read back
9481     const GLuint *ptr = reinterpret_cast<const GLuint *>(
9482         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9483     EXPECT_EQ(ptr[0], inputData);
9484     EXPECT_EQ(ptr[1], uniformData);
9485     EXPECT_NEAR(ptr[2], textureData.R, 1.0);
9486     EXPECT_EQ(ptr[3], acData);
9487     EXPECT_EQ(ptr[4], imageData);
9488 
9489     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9490 }
9491 
9492 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)9493 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
9494 {
9495     // http://anglebug.com/5546
9496     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9497 
9498     // anglebug.com/3832 - no sampler array params on Android
9499     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9500 
9501     constexpr char kComputeShader[] = R"(#version 310 es
9502 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9503 
9504 layout(binding = 1, std430) buffer Output {
9505   uint success;
9506 } outbuf;
9507 
9508 uniform uint initialAcValue;
9509 uniform sampler2D smplr[2][3];
9510 layout(binding=0) uniform atomic_uint ac;
9511 
9512 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
9513 {
9514     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
9515                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
9516                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
9517     uint aResult = atomicCounterIncrement(a);
9518 
9519     return sExpect == sResult && aExpect == aResult;
9520 }
9521 
9522 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
9523 {
9524     bool success = true;
9525     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
9526     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
9527     return success;
9528 }
9529 
9530 void main(void)
9531 {
9532     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
9533 }
9534 )";
9535     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9536     EXPECT_GL_NO_ERROR();
9537 
9538     glUseProgram(program);
9539 
9540     unsigned int outputInitData = 0x12345678u;
9541     GLBuffer outputBuffer;
9542     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9543     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9544     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9545     EXPECT_GL_NO_ERROR();
9546 
9547     unsigned int acData   = 2u;
9548     GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
9549     ASSERT_NE(uniformLocation, -1);
9550     glUniform1ui(uniformLocation, acData);
9551 
9552     GLBuffer atomicCounterBuffer;
9553     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9554     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9555     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9556     EXPECT_GL_NO_ERROR();
9557 
9558     const std::array<GLColor, 6> kTextureData = {
9559         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
9560         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
9561     };
9562     GLTexture textures[2][3];
9563 
9564     for (int dim1 = 0; dim1 < 2; ++dim1)
9565     {
9566         for (int dim2 = 0; dim2 < 3; ++dim2)
9567         {
9568             int textureUnit = dim1 * 3 + dim2;
9569             glActiveTexture(GL_TEXTURE0 + textureUnit);
9570             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
9571             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9572                          &kTextureData[textureUnit]);
9573             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9574             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9575 
9576             std::stringstream uniformName;
9577             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
9578             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
9579             EXPECT_NE(samplerLocation, -1);
9580             glUniform1i(samplerLocation, textureUnit);
9581         }
9582     }
9583     ASSERT_GL_NO_ERROR();
9584 
9585     glDispatchCompute(1, 1, 1);
9586     EXPECT_GL_NO_ERROR();
9587 
9588     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9589 
9590     // read back
9591     const GLuint *ptr = reinterpret_cast<const GLuint *>(
9592         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9593     EXPECT_EQ(ptr[0], 1u);
9594 
9595     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9596 }
9597 
9598 // Test that array of array of samplers used as function parameter with an index that has a
9599 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)9600 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
9601 {
9602     // http://anglebug.com/5546
9603     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9604 
9605     // anglebug.com/3832 - no sampler array params on Android
9606     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9607 
9608     // Skip if EXT_gpu_shader5 is not enabled.
9609     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
9610 
9611     constexpr char kComputeShader[] = R"(#version 310 es
9612 #extension GL_EXT_gpu_shader5 : require
9613 
9614 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9615 
9616 layout(binding = 1, std430) buffer Output {
9617   uint success;
9618 } outbuf;
9619 
9620 uniform sampler2D smplr[2][3];
9621 layout(binding=0) uniform atomic_uint ac;
9622 
9623 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
9624 {
9625     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
9626                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
9627                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
9628     uint aResult = atomicCounter(a);
9629 
9630     return sExpect == sResult && aExpect == aResult;
9631 }
9632 
9633 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
9634 {
9635     bool success = true;
9636     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
9637                     s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
9638     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
9639                     s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
9640     return success;
9641 }
9642 
9643 void main(void)
9644 {
9645     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
9646 }
9647 )";
9648     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9649     EXPECT_GL_NO_ERROR();
9650 
9651     glUseProgram(program);
9652 
9653     unsigned int outputInitData = 0x12345678u;
9654     GLBuffer outputBuffer;
9655     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9656     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9657     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9658     EXPECT_GL_NO_ERROR();
9659 
9660     unsigned int acData = 0u;
9661     GLBuffer atomicCounterBuffer;
9662     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9663     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9664     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9665     EXPECT_GL_NO_ERROR();
9666 
9667     const std::array<GLColor, 6> kTextureData = {
9668         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
9669         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
9670     };
9671     GLTexture textures[2][3];
9672 
9673     for (int dim1 = 0; dim1 < 2; ++dim1)
9674     {
9675         for (int dim2 = 0; dim2 < 3; ++dim2)
9676         {
9677             int textureUnit = dim1 * 3 + dim2;
9678             glActiveTexture(GL_TEXTURE0 + textureUnit);
9679             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
9680             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9681                          &kTextureData[textureUnit]);
9682             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9683             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9684 
9685             std::stringstream uniformName;
9686             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
9687             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
9688             EXPECT_NE(samplerLocation, -1);
9689             glUniform1i(samplerLocation, textureUnit);
9690         }
9691     }
9692     ASSERT_GL_NO_ERROR();
9693 
9694     glDispatchCompute(1, 1, 1);
9695     EXPECT_GL_NO_ERROR();
9696 
9697     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9698 
9699     // read back
9700     const GLuint *ptr = reinterpret_cast<const GLuint *>(
9701         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9702     EXPECT_EQ(ptr[0], 1u);
9703 
9704     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9705 }
9706 
9707 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndex)9708 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndex)
9709 {
9710     // Skip if EXT_gpu_shader5 is not enabled.
9711     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
9712 
9713     int maxTextureImageUnits = 0;
9714     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
9715     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
9716 
9717     // anglebug.com/3832 - no sampler array params on Android
9718     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9719 
9720     // http://anglebug.com/5546
9721     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9722 
9723     constexpr char kComputeShader[] = R"(#version 310 es
9724 #extension GL_EXT_gpu_shader5 : require
9725 
9726 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9727 
9728 layout(binding = 1, std430) buffer Output {
9729   uint success;
9730 } outbuf;
9731 
9732 uniform sampler2D smplr[2][3][4];
9733 layout(binding=0) uniform atomic_uint ac;
9734 
9735 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
9736 {
9737     uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
9738                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
9739                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
9740                           uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
9741     uint aResult = atomicCounter(a);
9742 
9743     return sExpect == sResult && aExpect == aResult;
9744 }
9745 
9746 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
9747 {
9748     bool success = true;
9749     // [0][0]
9750     success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
9751                     s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
9752     // [1][0]
9753     success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
9754                     s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
9755     // [0][1]
9756     success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
9757                     s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
9758     // [0][2]
9759     success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
9760                     s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
9761     // [1][1]
9762     success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
9763                     s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
9764     // [1][2]
9765     uint acValue = atomicCounterIncrement(ac);  // Returns 5
9766     success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
9767                     s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
9768 
9769     return success;
9770 }
9771 
9772 void main(void)
9773 {
9774     outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
9775 }
9776 )";
9777     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9778     EXPECT_GL_NO_ERROR();
9779 
9780     glUseProgram(program);
9781 
9782     unsigned int outputInitData = 0x12345678u;
9783     GLBuffer outputBuffer;
9784     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9785     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9786     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9787     EXPECT_GL_NO_ERROR();
9788 
9789     unsigned int acData = 0u;
9790     GLBuffer atomicCounterBuffer;
9791     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9792     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9793     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9794     EXPECT_GL_NO_ERROR();
9795 
9796     const std::array<GLColor, 24> kTextureData = {
9797         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
9798         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
9799         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
9800         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
9801         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
9802         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
9803     };
9804     GLTexture textures[2][3][4];
9805 
9806     for (int dim1 = 0; dim1 < 2; ++dim1)
9807     {
9808         for (int dim2 = 0; dim2 < 3; ++dim2)
9809         {
9810             for (int dim3 = 0; dim3 < 4; ++dim3)
9811             {
9812                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
9813                 glActiveTexture(GL_TEXTURE0 + textureUnit);
9814                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
9815                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9816                              &kTextureData[textureUnit]);
9817                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9818                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9819 
9820                 std::stringstream uniformName;
9821                 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
9822                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
9823                 EXPECT_NE(samplerLocation, -1);
9824                 glUniform1i(samplerLocation, textureUnit);
9825             }
9826         }
9827     }
9828     ASSERT_GL_NO_ERROR();
9829 
9830     glDispatchCompute(1, 1, 1);
9831     EXPECT_GL_NO_ERROR();
9832 
9833     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9834 
9835     // read back
9836     const GLuint *ptr = reinterpret_cast<const GLuint *>(
9837         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9838     EXPECT_EQ(ptr[0], 1u);
9839 
9840     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9841 }
9842 
9843 // Test that array of array of samplers can be indexed correctly with dynamic indices.  Uses
9844 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)9845 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
9846 {
9847     // Skip if EXT_gpu_shader5 is not enabled.
9848     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
9849 
9850     int maxTextureImageUnits = 0;
9851     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
9852     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
9853 
9854     // http://anglebug.com/5072
9855     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
9856 
9857     // anglebug.com/3832 - no sampler array params on Android
9858     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9859 
9860     // http://anglebug.com/5546
9861     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9862 
9863     constexpr char kComputeShader[] = R"(#version 310 es
9864 #extension GL_EXT_gpu_shader5 : require
9865 
9866 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9867 
9868 layout(binding = 1, std430) buffer Output {
9869   uint success;
9870 } outbuf;
9871 
9872 struct I
9873 {
9874     uint index;
9875 };
9876 
9877 struct S
9878 {
9879     sampler2D smplr[4];
9880     I nested;
9881 };
9882 
9883 struct T
9884 {
9885     S nested[3];
9886     uint tIndex;
9887 };
9888 
9889 uniform T u[2];
9890 
9891 uint getValue(in sampler2D s)
9892 {
9893     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
9894 }
9895 
9896 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
9897 {
9898     uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
9899                           getValue(s[2]), getValue(s[3]));
9900 
9901     return sExpect == sResult;
9902 }
9903 
9904 bool samplerTest(T t, uint N)
9905 {
9906     // u[N].tIndex == 0 + N*4
9907     // u[N].nested[0].nested.index == 1 + N*4
9908     // u[N].nested[1].nested.index == 2 + N*4
9909     // u[N].nested[2].nested.index == 3 + N*4
9910 
9911     uvec4 colorOffset = N * 3u * 4u * uvec4(8);
9912 
9913     bool success = true;
9914     // [N][0]
9915     success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
9916                     t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
9917     // [N][1]
9918     success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
9919                     t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
9920     // [N][2]
9921     success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
9922                     t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
9923 
9924     return success;
9925 }
9926 
9927 bool uniformTest(T t, uint N)
9928 {
9929     // Also verify that expressions that involve structs-with-samplers are correct when not
9930     // referecing the sampler.
9931 
9932     bool success = true;
9933     success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
9934     success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
9935     success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
9936 
9937     success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
9938                 && success;
9939     success = (t.nested[t.nested[0].nested.index - t.tIndex     ].nested.index - t.tIndex == 2u)
9940                 && success;
9941     success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
9942                 && success;
9943 
9944     success = (t.nested[
9945                           t.nested[
9946                                      t.nested[2].nested.index - t.tIndex - 1u  // 2
9947                                   ].nested.index - t.tIndex - 2u               // 1
9948                        ].nested.index - t.tIndex                               // 2
9949                 == 2u) && success;
9950 
9951     return success;
9952 }
9953 
9954 void main(void)
9955 {
9956     bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
9957                     && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
9958     outbuf.success = uint(success);
9959 }
9960 )";
9961     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9962     EXPECT_GL_NO_ERROR();
9963 
9964     glUseProgram(program);
9965 
9966     unsigned int outputInitData = 0x12345678u;
9967     GLBuffer outputBuffer;
9968     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9969     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9970     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9971     EXPECT_GL_NO_ERROR();
9972 
9973     const std::array<GLColor, 24> kTextureData = {
9974         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
9975         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
9976         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
9977         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
9978         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
9979         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
9980     };
9981     GLTexture textures[2][3][4];
9982 
9983     for (int dim1 = 0; dim1 < 2; ++dim1)
9984     {
9985         for (int dim2 = 0; dim2 < 3; ++dim2)
9986         {
9987             for (int dim3 = 0; dim3 < 4; ++dim3)
9988             {
9989                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
9990                 glActiveTexture(GL_TEXTURE0 + textureUnit);
9991                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
9992                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9993                              &kTextureData[textureUnit]);
9994                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9995                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9996 
9997                 std::stringstream uniformName;
9998                 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
9999                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10000                 EXPECT_NE(samplerLocation, -1);
10001                 glUniform1i(samplerLocation, textureUnit);
10002             }
10003 
10004             std::stringstream uniformName;
10005             uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
10006             GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
10007             EXPECT_NE(nestedIndexLocation, -1);
10008             glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
10009         }
10010 
10011         std::stringstream uniformName;
10012         uniformName << "u[" << dim1 << "].tIndex";
10013         GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
10014         EXPECT_NE(indexLocation, -1);
10015         glUniform1ui(indexLocation, dim1 * 4);
10016     }
10017     ASSERT_GL_NO_ERROR();
10018 
10019     glDispatchCompute(1, 1, 1);
10020     EXPECT_GL_NO_ERROR();
10021 
10022     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10023 
10024     // read back
10025     const GLuint *ptr = reinterpret_cast<const GLuint *>(
10026         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10027     EXPECT_EQ(ptr[0], 1u);
10028 
10029     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10030 }
10031 
10032 // Test that array of array of samplers work when indexed with an expression that's derived from an
10033 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)10034 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
10035 {
10036     // Skip if EXT_gpu_shader5 is not enabled.
10037     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10038 
10039     // anglebug.com/3832 - no sampler array params on Android
10040     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10041 
10042     constexpr char kComputeShader[] = R"(#version 310 es
10043 #extension GL_EXT_gpu_shader5 : require
10044 
10045 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10046 
10047 layout(binding = 1, std430) buffer Output {
10048   uint success;
10049 } outbuf;
10050 
10051 uniform sampler2D smplr[2][3];
10052 
10053 uint getValue(in sampler2D s)
10054 {
10055     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
10056 }
10057 
10058 bool runTest(in sampler2D s[2][3])
10059 {
10060     // s[0][0] should contain 2
10061     // s[0][1] should contain 0
10062     // s[0][2] should contain 1
10063     // s[1][0] should contain 1
10064     // s[1][1] should contain 2
10065     // s[1][2] should contain 0
10066 
10067     uint result = getValue(
10068                        s[
10069                            getValue(
10070                                 s[
10071                                     getValue(s[0][1])   // 0
10072                                 ][
10073                                     getValue(s[0][0])   // 2
10074                                 ]
10075                            )                      // s[0][2] -> 1
10076                        ][
10077                            getValue(
10078                                 s[
10079                                     getValue(s[1][0])   // 1
10080                                 ][
10081                                     getValue(s[1][1])   // 2
10082                                 ]
10083                            )                      // s[1][2] -> 0
10084                        ]
10085                   );                      // s[1][0] -> 1
10086 
10087     return result == 1u;
10088 }
10089 
10090 void main(void)
10091 {
10092     outbuf.success = uint(runTest(smplr));
10093 }
10094 )";
10095     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10096     EXPECT_GL_NO_ERROR();
10097 
10098     glUseProgram(program);
10099 
10100     unsigned int outputInitData = 0x12345678u;
10101     GLBuffer outputBuffer;
10102     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10103     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10104     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10105     EXPECT_GL_NO_ERROR();
10106 
10107     const std::array<GLColor, 6> kTextureData = {
10108         GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
10109         GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
10110     };
10111     GLTexture textures[2][3];
10112 
10113     for (int dim1 = 0; dim1 < 2; ++dim1)
10114     {
10115         for (int dim2 = 0; dim2 < 3; ++dim2)
10116         {
10117             int textureUnit = dim1 * 3 + dim2;
10118             glActiveTexture(GL_TEXTURE0 + textureUnit);
10119             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
10120             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10121                          &kTextureData[textureUnit]);
10122             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10123             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10124 
10125             std::stringstream uniformName;
10126             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
10127             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10128             EXPECT_NE(samplerLocation, -1);
10129             glUniform1i(samplerLocation, textureUnit);
10130         }
10131     }
10132     ASSERT_GL_NO_ERROR();
10133 
10134     glDispatchCompute(1, 1, 1);
10135     EXPECT_GL_NO_ERROR();
10136 
10137     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10138 
10139     // read back
10140     const GLuint *ptr = reinterpret_cast<const GLuint *>(
10141         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10142     EXPECT_EQ(ptr[0], 1u);
10143 
10144     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10145 }
10146 
10147 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)10148 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
10149 {
10150     // http://anglebug.com/3831
10151     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
10152 
10153     // Fails on windows AMD on GL: http://anglebug.com/3838
10154     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
10155     // http://anglebug.com/5384
10156     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
10157 
10158     // Fails on D3D due to mistranslation: http://anglebug.com/3841
10159     ANGLE_SKIP_TEST_IF(IsD3D11());
10160 
10161     constexpr char kCS[] = R"(#version 310 es
10162 precision highp float;
10163 layout(local_size_x=1) in;
10164 
10165 layout(std140, column_major) uniform Ubo
10166 {
10167     mat4 m1;
10168     layout(row_major) mat4 m2;
10169 } ubo;
10170 
10171 layout(std140, row_major, binding = 0) buffer Ssbo
10172 {
10173     layout(column_major) mat4 m1;
10174     mat4 m2;
10175 } ssbo;
10176 
10177 layout(std140, binding = 1) buffer Result
10178 {
10179     uint success;
10180 } resultOut;
10181 
10182 void main()
10183 {
10184     bool result = true;
10185 
10186     // Only assign to SSBO from a single invocation.
10187     if (gl_GlobalInvocationID.x == 0u)
10188     {
10189         if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
10190         {
10191             result = false;
10192         }
10193 
10194         resultOut.success = uint(result);
10195     }
10196 })";
10197 
10198     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10199     EXPECT_GL_NO_ERROR();
10200 
10201     constexpr size_t kMatrixCount                                     = 2;
10202     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10203         {4, 4},
10204         {4, 4},
10205     };
10206     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10207         true,
10208         false,
10209     };
10210 
10211     float data[kMatrixCount * 4 * 4]  = {};
10212     float zeros[kMatrixCount * 4 * 4] = {};
10213 
10214     const uint32_t size =
10215         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10216 
10217     GLBuffer ubo, ssbo;
10218 
10219     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10220     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
10221     EXPECT_GL_NO_ERROR();
10222 
10223     GLBuffer outputBuffer;
10224     CreateOutputBuffer(&outputBuffer, 1);
10225 
10226     glUseProgram(program);
10227     glDispatchCompute(1, 1, 1);
10228     EXPECT_GL_NO_ERROR();
10229     EXPECT_TRUE(VerifySuccess(outputBuffer));
10230 
10231     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
10232 }
10233 
10234 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)10235 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
10236 {
10237     // Fails on windows AMD on GL: http://anglebug.com/3838
10238     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
10239     // http://anglebug.com/5384
10240     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
10241 
10242     // Fails on D3D due to mistranslation: http://anglebug.com/3841
10243     ANGLE_SKIP_TEST_IF(IsD3D11());
10244 
10245     // Fails compiling shader on Android/Vulkan.  http://anglebug.com/4290
10246     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
10247 
10248     // Fails on ARM on Vulkan.  http://anglebug.com/4492
10249     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
10250 
10251     constexpr char kCS[] = R"(#version 310 es
10252 precision highp float;
10253 layout(local_size_x=1) in;
10254 
10255 layout(std140, column_major) uniform Ubo
10256 {
10257     mat4 m1;
10258     layout(row_major) mat4 m2[2][3];
10259 } ubo;
10260 
10261 layout(std140, row_major, binding = 0) buffer Ssbo
10262 {
10263     layout(column_major) mat4 m1;
10264     mat4 m2[2][3];
10265 } ssbo;
10266 
10267 layout(std140, binding = 1) buffer Result
10268 {
10269     uint success;
10270 } resultOut;
10271 
10272 void main()
10273 {
10274     bool result = true;
10275 
10276     // Only assign to SSBO from a single invocation.
10277     if (gl_GlobalInvocationID.x == 0u)
10278     {
10279         ssbo.m1 = ubo.m1;
10280         ssbo.m2 = ubo.m2;
10281 
10282         resultOut.success = uint(result);
10283     }
10284 })";
10285 
10286     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10287     EXPECT_GL_NO_ERROR();
10288 
10289     constexpr size_t kMatrixCount                                     = 7;
10290     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10291         {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
10292     };
10293     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10294         true, false, false, false, false, false, false,
10295     };
10296 
10297     float data[kMatrixCount * 4 * 4]  = {};
10298     float zeros[kMatrixCount * 4 * 4] = {};
10299 
10300     const uint32_t size =
10301         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10302 
10303     GLBuffer ubo, ssbo;
10304 
10305     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10306     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
10307     EXPECT_GL_NO_ERROR();
10308 
10309     GLBuffer outputBuffer;
10310     CreateOutputBuffer(&outputBuffer, 1);
10311 
10312     glUseProgram(program);
10313     glDispatchCompute(1, 1, 1);
10314     EXPECT_GL_NO_ERROR();
10315     EXPECT_TRUE(VerifySuccess(outputBuffer));
10316 
10317     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
10318 }
10319 
10320 // Verify that types used differently (in different block storages, differently qualified etc) work
10321 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)10322 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
10323 {
10324     constexpr char kCS[] = R"(#version 310 es
10325 precision highp float;
10326 layout(local_size_x=1) in;
10327 
10328 struct Inner
10329 {
10330     mat3x2 m;
10331     float f[3];
10332     uvec2 u[2][4];
10333     ivec3 i;
10334     mat2x3 m2[3][2];
10335 };
10336 
10337 struct Outer
10338 {
10339     Inner i[2];
10340 };
10341 
10342 layout(std140, column_major) uniform Ubo140c
10343 {
10344     mat2 m;
10345     layout(row_major) Outer o;
10346 } ubo140cIn;
10347 
10348 layout(std430, row_major, binding = 0) buffer Ubo430r
10349 {
10350     mat2 m;
10351     layout(column_major) Outer o;
10352 } ubo430rIn;
10353 
10354 layout(std140, column_major, binding = 1) buffer Ssbo140c
10355 {
10356     layout(row_major) mat2 m[2];
10357     Outer o;
10358     layout(row_major) Inner i;
10359 } ssbo140cOut;
10360 
10361 layout(std430, row_major, binding = 2) buffer Ssbo430r
10362 {
10363     layout(column_major) mat2 m[2];
10364     Outer o;
10365     layout(column_major) Inner i;
10366 } ssbo430rOut;
10367 
10368 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
10369 {
10370     ssbo140cOut.o.i[innerIndex].u = u;
10371 }
10372 
10373 void writeBlockArgToStd140(Inner i, int innerIndex)
10374 {
10375     ssbo140cOut.o.i[innerIndex] = i;
10376 }
10377 
10378 mat2x3[3][2] readFromStd140(int innerIndex)
10379 {
10380     return ubo140cIn.o.i[0].m2;
10381 }
10382 
10383 Inner readBlockFromStd430(int innerIndex)
10384 {
10385     return ubo430rIn.o.i[innerIndex];
10386 }
10387 
10388 void copyFromStd140(out Inner i)
10389 {
10390     i = ubo140cIn.o.i[1];
10391 }
10392 
10393 void main(){
10394     // Directly copy from one layout to another.
10395     ssbo140cOut.m[0] = ubo140cIn.m;
10396     ssbo140cOut.m[1] = ubo430rIn.m;
10397     ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
10398     ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
10399     ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
10400 
10401     // Read from block and pass to function.
10402     writeArgToStd140(ubo140cIn.o.i[0].u, 0);
10403     writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
10404 
10405     // Have function return value read from block.
10406     ssbo140cOut.o.i[0].m2 = readFromStd140(0);
10407 
10408     // Have function fill in value as out parameter.
10409     copyFromStd140(ssbo140cOut.i);
10410 
10411     // Initialize local variable.
10412     mat2 mStd140 = ubo140cIn.m;
10413 
10414     // Copy to variable, through multiple assignments.
10415     mat2 mStd430, temp;
10416     mStd430 = temp = ubo430rIn.m;
10417 
10418     // Copy from local variable
10419     ssbo430rOut.m[0] = mStd140;
10420     ssbo430rOut.m[1] = mStd430;
10421 
10422     // Construct from struct.
10423     Inner iStd140 = ubo140cIn.o.i[1];
10424     Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
10425 
10426     // Copy struct from local variable.
10427     ssbo430rOut.o = oStd140;
10428 
10429     // Construct from arrays
10430     Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
10431                           ubo430rIn.o.i[1].f,
10432                           ubo430rIn.o.i[1].u,
10433                           ubo430rIn.o.i[1].i,
10434                           ubo430rIn.o.i[1].m2);
10435     ssbo430rOut.i = iStd430;
10436 })";
10437 
10438     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10439     EXPECT_GL_NO_ERROR();
10440 
10441     // Test data, laid out with padding (0) based on std140/std430 rules.
10442     // clang-format off
10443     const std::vector<float> ubo140cData = {
10444         // m (mat2, column-major)
10445         1, 2, 0, 0,     3, 4, 0, 0,
10446 
10447         // o.i[0].m (mat3x2, row-major)
10448         5, 7, 9, 0,     6, 8, 10, 0,
10449         // o.i[0].f (float[3])
10450         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
10451         // o.i[0].u (uvec2[2][4])
10452         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
10453         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
10454         // o.i[0].i (ivec3)
10455         31, 32, 33, 0,
10456         // o.i[0].m2 (mat2x3[3][2], row-major)
10457         34, 37, 0, 0,   35, 38, 0, 0,   36, 39, 0, 0,
10458         40, 43, 0, 0,   41, 44, 0, 0,   42, 45, 0, 0,
10459         46, 49, 0, 0,   47, 50, 0, 0,   48, 51, 0, 0,
10460         52, 55, 0, 0,   53, 56, 0, 0,   54, 57, 0, 0,
10461         58, 61, 0, 0,   59, 62, 0, 0,   60, 63, 0, 0,
10462         64, 67, 0, 0,   65, 68, 0, 0,   66, 69, 0, 0,
10463 
10464         // o.i[1].m (mat3x2, row-major)
10465         70, 72, 74, 0,     71, 73, 75, 0,
10466         // o.i[1].f (float[3])
10467         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
10468         // o.i[1].u (uvec2[2][4])
10469         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
10470         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
10471         // o.i[1].i (ivec3)
10472         96, 97, 98, 0,
10473         // o.i[1].m2 (mat2x3[3][2], row-major)
10474          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
10475         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
10476         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
10477         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
10478         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
10479         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
10480     };
10481     const std::vector<float> ubo430rData = {
10482         // m (mat2, row-major)
10483         135, 137,         136, 138,
10484 
10485         // o.i[0].m (mat3x2, column-major)
10486         139, 140,         141, 142,         143, 144,
10487         // o.i[0].f (float[3])
10488         146, 147, 148, 0,
10489         // o.i[0].u (uvec2[2][4])
10490         149, 150,         151, 152,         153, 154,         155, 156,
10491         157, 158,         159, 160,         161, 162,         163, 164, 0, 0,
10492         // o.i[0].i (ivec3)
10493         165, 166, 167, 0,
10494         // o.i[0].m2 (mat2x3[3][2], column-major)
10495         168, 169, 170, 0,   171, 172, 173, 0,
10496         174, 175, 176, 0,   177, 178, 179, 0,
10497         180, 181, 182, 0,   183, 184, 185, 0,
10498         186, 187, 188, 0,   189, 190, 191, 0,
10499         192, 193, 194, 0,   195, 196, 197, 0,
10500         198, 199, 200, 0,   201, 202, 203, 0,
10501 
10502         // o.i[1].m (mat3x2, column-major)
10503         204, 205,         206, 207,         208, 209,
10504         // o.i[1].f (float[3])
10505         211, 212, 213, 0,
10506         // o.i[1].u (uvec2[2][4])
10507         214, 215,         216, 217,         218, 219,         220, 221,
10508         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
10509         // o.i[1].i (ivec3)
10510         230, 231, 232, 0,
10511         // o.i[1].m2 (mat2x3[3][2], column-major)
10512         233, 234, 235, 0,   236, 237, 238, 0,
10513         239, 240, 241, 0,   242, 243, 244, 0,
10514         245, 246, 247, 0,   248, 249, 250, 0,
10515         251, 252, 253, 0,   254, 255, 256, 0,
10516         257, 258, 259, 0,   260, 261, 262, 0,
10517         263, 264, 265, 0,   266, 267, 268, 0,
10518     };
10519     const std::vector<float> ssbo140cExpect = {
10520         // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
10521         1, 3, 0, 0,     2, 4, 0, 0,
10522         135, 137, 0, 0, 136, 138, 0, 0,
10523 
10524         // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
10525         5, 6, 0, 0,     7, 8, 0, 0,     9, 10, 0, 0,
10526         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
10527         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
10528         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
10529         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
10530         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
10531         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
10532         31, 32, 33, 0,
10533         // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
10534         34, 35, 36, 0,  37, 38, 39, 0,
10535         40, 41, 42, 0,  43, 44, 45, 0,
10536         46, 47, 48, 0,  49, 50, 51, 0,
10537         52, 53, 54, 0,  55, 56, 57, 0,
10538         58, 59, 60, 0,  61, 62, 63, 0,
10539         64, 65, 66, 0,  67, 68, 69, 0,
10540 
10541         // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
10542         139, 140, 0, 0,   141, 142, 0, 0,   143, 144, 0, 0,
10543         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
10544         146, 0, 0, 0,     147, 0, 0, 0,     148, 0, 0, 0,
10545         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
10546         149, 150, 0, 0,   151, 152, 0, 0,   153, 154, 0, 0,   155, 156, 0, 0,
10547         157, 158, 0, 0,   159, 160, 0, 0,   161, 162, 0, 0,   163, 164, 0, 0,
10548         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
10549         165, 166, 167, 0,
10550         // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
10551         168, 169, 170, 0,   171, 172, 173, 0,
10552         174, 175, 176, 0,   177, 178, 179, 0,
10553         180, 181, 182, 0,   183, 184, 185, 0,
10554         186, 187, 188, 0,   189, 190, 191, 0,
10555         192, 193, 194, 0,   195, 196, 197, 0,
10556         198, 199, 200, 0,   201, 202, 203, 0,
10557 
10558         // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
10559         70, 72, 74, 0,     71, 73, 75, 0,
10560         // i.f (float[3]), copied from ubo140cIn.o.i[1].f
10561         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
10562         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
10563         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
10564         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
10565         // i.i (ivec3), copied from ubo140cIn.o.i[1].i
10566         96, 97, 98, 0,
10567         // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
10568          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
10569         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
10570         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
10571         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
10572         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
10573         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
10574     };
10575     const std::vector<float> ssbo430rExpect = {
10576         // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
10577         1, 2,           3, 4,
10578         135, 136,       137, 138,
10579 
10580         // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
10581         70, 72, 74, 0,  71, 73, 75, 0,
10582         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
10583         77, 78, 79, 0,
10584         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
10585         80, 81,         82, 83,         84, 85,         86, 87,
10586         88, 89,         90, 91,         92, 93,         94, 95,
10587         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
10588         96, 97, 98, 0,
10589         // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
10590          99, 102,        100, 103,         101, 104,
10591         105, 108,        106, 109,         107, 110,
10592         111, 114,        112, 115,         113, 116,
10593         117, 120,        118, 121,         119, 122,
10594         123, 126,        124, 127,         125, 128,
10595         129, 132,        130, 133,         131, 134,
10596 
10597         // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
10598         204, 206, 208, 0,  205, 207, 209, 0,
10599         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
10600         211, 212, 213, 0,
10601         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
10602         214, 215,         216, 217,         218, 219,         220, 221,
10603         222, 223,         224, 225,         226, 227,         228, 229,
10604         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
10605         230, 231, 232, 0,
10606         // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
10607         233, 236,         234, 237,         235, 238,
10608         239, 242,         240, 243,         241, 244,
10609         245, 248,         246, 249,         247, 250,
10610         251, 254,         252, 255,         253, 256,
10611         257, 260,         258, 261,         259, 262,
10612         263, 266,         264, 267,         265, 268,
10613 
10614         // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
10615         204, 205,          206, 207,         208, 209,
10616         // i.f (float[3]), copied from ubo430rIn.o.i[1].f
10617         211, 212, 213, 0,
10618         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
10619         214, 215,         216, 217,         218, 219,         220, 221,
10620         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
10621         // i.i (ivec3), copied from ubo430rIn.o.i[1].i
10622         230, 231, 232, 0,
10623         // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
10624         233, 234, 235, 0,   236, 237, 238, 0,
10625         239, 240, 241, 0,   242, 243, 244, 0,
10626         245, 246, 247, 0,   248, 249, 250, 0,
10627         251, 252, 253, 0,   254, 255, 256, 0,
10628         257, 258, 259, 0,   260, 261, 262, 0,
10629         263, 264, 265, 0,   266, 267, 268, 0,
10630     };
10631     const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
10632     // clang-format on
10633 
10634     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
10635     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
10636 
10637     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
10638                static_cast<uint32_t>(ubo140cData.size()), true);
10639     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
10640                static_cast<uint32_t>(ubo430rData.size()), false);
10641     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
10642                static_cast<uint32_t>(ssbo140cExpect.size()), false);
10643     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
10644                static_cast<uint32_t>(ssbo430rExpect.size()), false);
10645     EXPECT_GL_NO_ERROR();
10646 
10647     glUseProgram(program);
10648     glDispatchCompute(1, 1, 1);
10649     EXPECT_GL_NO_ERROR();
10650 
10651     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
10652                              static_cast<uint32_t>(ssbo140cExpect.size())));
10653     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
10654                              static_cast<uint32_t>(ssbo430rExpect.size())));
10655 }
10656 
10657 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)10658 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
10659 {
10660     constexpr char kCS[] = R"(#version 310 es
10661 precision highp float;
10662 layout(local_size_x=1) in;
10663 
10664 struct Inner
10665 {
10666     bool b;
10667     bvec2 b2;
10668     bvec3 b3;
10669     bvec4 b4;
10670     bool ba[5];
10671     bvec2 b2a[2][3];
10672 };
10673 
10674 struct Outer
10675 {
10676     Inner i[2];
10677 };
10678 
10679 layout(std140) uniform Ubo140
10680 {
10681     Outer o;
10682 };
10683 
10684 layout(std430, binding = 0) buffer Ubo430
10685 {
10686     Outer o;
10687 } ubo430In;
10688 
10689 layout(std140, binding = 1) buffer Ssbo140
10690 {
10691     bool valid;
10692     Inner i;
10693 } ssbo140Out;
10694 
10695 layout(std430, binding = 2) buffer Ssbo430
10696 {
10697     bool valid;
10698     Inner i;
10699 };
10700 
10701 void writeArgToStd430(bool ba[5])
10702 {
10703     i.ba = ba;
10704 }
10705 
10706 bool[5] readFromStd430(uint innerIndex)
10707 {
10708     return ubo430In.o.i[innerIndex].ba;
10709 }
10710 
10711 void copyFromStd430(out bvec2 b2a[2][3])
10712 {
10713     b2a = ubo430In.o.i[0].b2a;
10714 }
10715 
10716 bool destroyContent(inout Inner iOut)
10717 {
10718     iOut.b = true;
10719     iOut.b2 = bvec2(true);
10720     iOut.b3 = bvec3(true);
10721     iOut.b4 = bvec4(true);
10722     iOut.ba = bool[5](true, true, true, true, true);
10723     bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
10724     iOut.b2a = bvec2[2][3](true3, true3);
10725     return true;
10726 }
10727 
10728 void main(){
10729     // Directly copy from one layout to another.
10730     i.b = o.i[0].b;
10731     i.b2 = o.i[0].b2;
10732     i.b2a = o.i[0].b2a;
10733 
10734     // Copy to temp with swizzle.
10735     bvec4 t1 = o.i[0].b3.yxzy;
10736     bvec4 t2 = o.i[0].b4.xxyy;
10737     bvec4 t3 = o.i[0].b4.zzww;
10738 
10739     // Copy from temp with swizzle.
10740     i.b3 = t1.ywz;
10741     i.b4.yz = bvec2(t2.z, t3.y);
10742     i.b4.wx = bvec2(t3.w, t2.x);
10743 
10744     // Copy by passing argument to function.
10745     writeArgToStd430(o.i[0].ba);
10746 
10747     // Copy by return value.
10748     ssbo140Out.i.ba = readFromStd430(0u);
10749 
10750     // Copy by out parameter.
10751     copyFromStd430(ssbo140Out.i.b2a);
10752 
10753     // Logical operations
10754     uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
10755     ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
10756     ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
10757     ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
10758     ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
10759 
10760     ssbo140Out.valid = true;
10761     ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
10762     ssbo140Out.valid = ssbo140Out.valid &&
10763             all(notEqual(o.i[1].b4, bvec4(o.i[1].ba[0], o.i[1].ba[1], o.i[1].ba[2], o.i[1].ba[3])));
10764     ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
10765     for (int x = 0; x < o.i[1].b2a.length(); ++x)
10766     {
10767         for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
10768         {
10769             ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
10770         }
10771     }
10772 
10773     valid = o.i[1] == ubo430In.o.i[1];
10774 
10775     // Make sure short-circuiting behavior is correct.
10776     bool falseVar = !valid && destroyContent(i);
10777     if (falseVar && destroyContent(ssbo140Out.i))
10778     {
10779         valid = false;
10780     }
10781 
10782     if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
10783     {
10784     }
10785     else
10786     {
10787         ssbo140Out.valid = false;
10788     }
10789 })";
10790 
10791     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10792     EXPECT_GL_NO_ERROR();
10793 
10794     // Test data, laid out with padding (0) based on std140/std430 rules.
10795     // clang-format off
10796     const std::vector<uint32_t> ubo140Data = {
10797         // o.i[0].b (bool)
10798         true, 0,
10799         // o.i[0].b2 (bvec2)
10800         true, false,
10801         // o.i[0].b3 (bvec3)
10802         true, true, false, 0,
10803         // o.i[0].b4 (bvec4)
10804         false, true, false, true,
10805         // o.i[0].ba (bool[5])
10806         true, 0, 0, 0,
10807         false, 0, 0, 0,
10808         false, 0, 0, 0,
10809         true, 0, 0, 0,
10810         true, 0, 0, 0,
10811         // o.i[0].b2a (bool[2][3])
10812         false, true, 0, 0,  true, true, 0, 0,    true, false, 0, 0,
10813         true, false, 0, 0,  false, false, 0, 0,  true, true, 0, 0,
10814 
10815         // o.i[1].b (bool)
10816         false, 0,
10817         // o.i[1].b2 (bvec2)
10818         true, true,
10819         // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
10820         false, true, true, 0,
10821         // o.i[1].b4 (bvec4)
10822         true, false, true, true,
10823         // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
10824         false, 0, 0, 0,
10825         true, 0, 0, 0,
10826         false, 0, 0, 0,
10827         false, 0, 0, 0,
10828         true, 0, 0, 0,
10829         // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
10830         false, false, 0, 0,  false, true, 0, 0,  false, false, 0, 0,
10831         true, false, 0, 0,   true, true, 0, 0,   true, false, 0, 0,
10832     };
10833     const std::vector<uint32_t> ubo430Data = {
10834         // o.i[0].b (bool)
10835         false, 0,
10836         // o.i[0].b2 (bvec2)
10837         true, true,
10838         // o.i[0].b3 (bvec3)
10839         false, false, true, 0,
10840         // o.i[0].b4 (bvec4)
10841         true, false, true, true,
10842         // o.i[0].ba (bool[5])
10843         false, false, false, true, false, 0,
10844         // o.i[0].b2a (bool[2][3])
10845         true, false,  true, false,  true, true,
10846         false, true,  true, true,   false, false, 0, 0,
10847 
10848         // o.i[1] expected to be equal to ubo140In.o.i[1]
10849         // o.i[1].b (bool)
10850         false, 0,
10851         // o.i[1].b2 (bvec2)
10852         true, true,
10853         // o.i[1].b3 (bvec3)
10854         false, true, true, 0,
10855         // o.i[1].b4 (bvec4)
10856         true, false, true, true,
10857         // o.i[1].ba (bool[5])
10858         false, true, false, false, true, 0,
10859         // o.i[1].b2a (bvec2[2][3])
10860         false, false,  false, true,  false, false,
10861         true, false,   true, true,   true, false,
10862     };
10863     const std::vector<uint32_t> ssbo140Expect = {
10864         // valid, expected to be true
10865         true, 0, 0, 0,
10866 
10867         // i.b (bool), ubo430In.o.i[0].b ? false : true
10868         true, 0,
10869         // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
10870         false, false,
10871         // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
10872         false, true, false, 0,
10873         // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
10874         true, true, true, false,
10875         // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
10876         false, 0, 0, 0,
10877         false, 0, 0, 0,
10878         false, 0, 0, 0,
10879         true, 0, 0, 0,
10880         false, 0, 0, 0,
10881         // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
10882         true, false, 0, 0,  true, false, 0, 0,   true, true, 0, 0,
10883         false, true, 0, 0,  true, true, 0, 0,    false, false, 0, 0,
10884     };
10885     const std::vector<uint32_t> ssbo430Expect = {
10886         // valid, expected to be true
10887         true, 0, 0, 0,
10888 
10889         // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
10890         true, 0,
10891         // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
10892         true, false,
10893         // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
10894         true, true, false, 0,
10895         // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
10896         false, true, false, true,
10897         // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
10898         true, false, false, true, true, 0,
10899         // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
10900         false, true,  true, true,    true, false,
10901         true, false,  false, false,  true, true, 0, 0,
10902     };
10903     const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
10904     // clang-format on
10905 
10906     GLBuffer uboStd140, uboStd430;
10907     GLBuffer ssboStd140, ssboStd430;
10908 
10909     InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
10910                static_cast<uint32_t>(ubo140Data.size()), true);
10911     InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
10912                static_cast<uint32_t>(ubo430Data.size()), false);
10913     InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
10914                static_cast<uint32_t>(ssbo140Expect.size()), false);
10915     InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
10916                static_cast<uint32_t>(ssbo430Expect.size()), false);
10917     EXPECT_GL_NO_ERROR();
10918 
10919     glUseProgram(program);
10920     glDispatchCompute(1, 1, 1);
10921     EXPECT_GL_NO_ERROR();
10922 
10923     EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
10924                              static_cast<uint32_t>(ssbo140Expect.size())));
10925     EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
10926                              static_cast<uint32_t>(ssbo430Expect.size())));
10927 }
10928 
10929 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)10930 TEST_P(GLSLTest_ES3, PreciseNotReserved)
10931 {
10932     // Skip in ES3.1+ as the precise keyword is reserved/core.
10933     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
10934                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
10935 
10936     constexpr char kFS[] = R"(#version 300 es
10937 precision mediump float;
10938 in float precise;
10939 out vec4 my_FragColor;
10940 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
10941 
10942     constexpr char kVS[] = R"(#version 300 es
10943 in vec4 a_position;
10944 out float precise;
10945 void main() { precise = a_position.x; gl_Position = a_position; })";
10946 
10947     GLuint program = CompileProgram(kVS, kFS);
10948     EXPECT_NE(0u, program);
10949 }
10950 
10951 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)10952 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
10953 {
10954     // Skip if EXT_gpu_shader5 is enabled.
10955     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10956     // Skip in ES3.2+ as the precise keyword is core.
10957     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
10958                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
10959 
10960     constexpr char kFS[] = R"(#version 310 es
10961 precision mediump float;
10962 in float v_varying;
10963 out vec4 my_FragColor;
10964 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
10965 
10966     constexpr char kVS[] = R"(#version 310 es
10967 in vec4 a_position;
10968 precise out float v_varying;
10969 void main() { v_varying = a_position.x; gl_Position = a_position; })";
10970 
10971     // Should fail, as precise is a reserved keyword when the extension is not enabled.
10972     GLuint program = CompileProgram(kVS, kFS);
10973     EXPECT_EQ(0u, program);
10974 }
10975 
10976 // Test that reusing the same variable name for different uses across stages links fine.  Glslang
10977 // wrapper's SPIR-V transformation should ignore all names for non-shader-interface variables and
10978 // not get confused by them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)10979 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
10980 {
10981     // Fails to compile the fragment shader with error "undeclared identifier '_g'"
10982     // http://anglebug.com/4404
10983     ANGLE_SKIP_TEST_IF(IsD3D11());
10984 
10985     constexpr char kVS[] = R"(#version 310 es
10986 precision mediump float;
10987 uniform highp vec4 a;
10988 in highp vec4 b;
10989 in highp vec4 c;
10990 in highp vec4 d;
10991 out highp vec4 e;
10992 
10993 vec4 f(vec4 a)
10994 {
10995     return a;
10996 }
10997 
10998 vec4 g(vec4 f)
10999 {
11000     return f + f;
11001 }
11002 
11003 void main() {
11004     e = f(b) + a;
11005     gl_Position = g(c) + f(d);
11006 }
11007 )";
11008 
11009     constexpr char kFS[] = R"(#version 310 es
11010 precision mediump float;
11011 in highp vec4 e;
11012 uniform sampler2D f;
11013 layout(rgba8) uniform highp readonly image2D g;
11014 uniform A
11015 {
11016     vec4 x;
11017 } c;
11018 layout(std140, binding=0) buffer B
11019 {
11020     vec4 x;
11021 } d[2];
11022 out vec4 col;
11023 
11024 vec4 h(vec4 c)
11025 {
11026     return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
11027 }
11028 
11029 vec4 i(vec4 x, vec4 y)
11030 {
11031     return vec4(x.xy, y.zw);
11032 }
11033 
11034 void main() {
11035     col = h(e) + i(c.x, d[0].x) + d[1].x;
11036 }
11037 )";
11038 
11039     GLuint program = CompileProgram(kVS, kFS);
11040     EXPECT_NE(0u, program);
11041 }
11042 
11043 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)11044 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
11045 {
11046     constexpr char kVS[] = R"(#version 310 es
11047 precision mediump float;
11048 in highp vec4 variableWithSameName;
11049 
11050 void main() {
11051     gl_Position = variableWithSameName;
11052 }
11053 )";
11054 
11055     constexpr char kFS[] = R"(#version 310 es
11056 precision mediump float;
11057 uniform vec4 variableWithSameName;
11058 out vec4 col;
11059 
11060 void main() {
11061     col = vec4(variableWithSameName);
11062 }
11063 )";
11064 
11065     GLuint program = CompileProgram(kVS, kFS);
11066     EXPECT_NE(0u, program);
11067 }
11068 
11069 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)11070 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
11071 {
11072     // Nvidia driver bug: http://anglebug.com/5240
11073     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
11074 
11075     constexpr char kVSUnused[] = R"(#version 300 es
11076 precision highp float;
11077 uniform highp vec4 positionIn;
11078 
11079 void main()
11080 {
11081     gl_Position = vec4(1, 0, 0, 1);
11082 })";
11083 
11084     constexpr char kVSStaticUse[] = R"(#version 300 es
11085 precision highp float;
11086 uniform highp vec4 positionIn;
11087 
11088 void main()
11089 {
11090     gl_Position = positionIn;
11091 })";
11092 
11093     constexpr char kFSUnused[] = R"(#version 300 es
11094 precision highp float;
11095 uniform highp vec4 positionIn;
11096 out vec4 my_FragColor;
11097 
11098 void main()
11099 {
11100     my_FragColor = vec4(1, 0, 0, 1);
11101 })";
11102 
11103     constexpr char kFSStaticUse[] = R"(#version 300 es
11104 precision highp float;
11105 uniform mediump vec4 positionIn;
11106 out vec4 my_FragColor;
11107 
11108 void main()
11109 {
11110     my_FragColor = vec4(1, 0, 0, positionIn.z);
11111 })";
11112 
11113     GLuint program = 0;
11114 
11115     program = CompileProgram(kVSUnused, kFSUnused);
11116     EXPECT_NE(0u, program);
11117 
11118     program = CompileProgram(kVSUnused, kFSStaticUse);
11119     EXPECT_NE(0u, program);
11120 
11121     program = CompileProgram(kVSStaticUse, kFSUnused);
11122     EXPECT_NE(0u, program);
11123 
11124     program = CompileProgram(kVSStaticUse, kFSStaticUse);
11125     EXPECT_EQ(0u, program);
11126 }
11127 
11128 // Validate that link fails when two instanceless interface blocks with different block names but
11129 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)11130 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
11131 {
11132     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11133 
11134     constexpr char kVS[] = R"(#version 310 es
11135 in highp vec4 position;
11136 layout(binding = 0) buffer BlockA { mediump float a; };
11137 void main()
11138 {
11139     a = 0.0;
11140     gl_Position = position;
11141 })";
11142 
11143     constexpr char kFS[] = R"(#version 310 es
11144 precision mediump float;
11145 layout(location = 0) out mediump vec4 color;
11146 uniform BlockB { float a; };
11147 void main()
11148 {
11149     color = vec4(a, a, a, 1.0);
11150 })";
11151 
11152     GLuint program = CompileProgram(kVS, kFS);
11153     EXPECT_EQ(0u, program);
11154 }
11155 
11156 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)11157 TEST_P(GLSLTest_ES31, IOBlockLocations)
11158 {
11159     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11160     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
11161 
11162     constexpr char kVS[] = R"(#version 310 es
11163 #extension GL_EXT_shader_io_blocks : require
11164 
11165 in highp vec4 position;
11166 
11167 layout(location = 0) out vec4 aOut;
11168 
11169 layout(location = 6) out VSBlock
11170 {
11171     vec4 b;     // location 6
11172     vec4 c;     // location 7
11173     layout(location = 1) vec4 d;
11174     vec4 e;     // location 2
11175     vec4 f[2];  // locations 3 and 4
11176 } blockOut;
11177 
11178 layout(location = 5) out vec4 gOut;
11179 
11180 void main()
11181 {
11182     aOut = vec4(0.03, 0.06, 0.09, 0.12);
11183     blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
11184     blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
11185     blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
11186     blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
11187     blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
11188     blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
11189     gOut = vec4(0.84, 0.87, 0.9, 0.93);
11190     gl_Position = position;
11191 })";
11192 
11193     constexpr char kGS[] = R"(#version 310 es
11194 #extension GL_EXT_geometry_shader : require
11195 layout (triangles) in;
11196 layout (triangle_strip, max_vertices = 3) out;
11197 
11198 // Input varyings
11199 layout(location = 0) in vec4 aIn[];
11200 
11201 layout(location = 6) in VSBlock
11202 {
11203     vec4 b;
11204     vec4 c;
11205     layout(location = 1) vec4 d;
11206     vec4 e;
11207     vec4 f[2];
11208 } blockIn[];
11209 
11210 layout(location = 5) in vec4 gIn[];
11211 
11212 // Output varyings
11213 layout(location = 1) out vec4 aOut;
11214 
11215 layout(location = 0) out GSBlock
11216 {
11217     vec4 b;     // location 0
11218     layout(location = 3) vec4 c;
11219     layout(location = 7) vec4 d;
11220     layout(location = 5) vec4 e[2];
11221     layout(location = 4) vec4 f;
11222 } blockOut;
11223 
11224 layout(location = 2) out vec4 gOut;
11225 
11226 void main()
11227 {
11228     int n;
11229     for (n = 0; n < gl_in.length(); n++)
11230     {
11231         gl_Position = gl_in[n].gl_Position;
11232 
11233         aOut = aIn[n];
11234         blockOut.b = blockIn[n].b;
11235         blockOut.c = blockIn[n].c;
11236         blockOut.d = blockIn[n].d;
11237         blockOut.e[0] = blockIn[n].e;
11238         blockOut.e[1] = blockIn[n].f[0];
11239         blockOut.f = blockIn[n].f[1];
11240         gOut = gIn[n];
11241 
11242         EmitVertex();
11243     }
11244     EndPrimitive();
11245 })";
11246 
11247     constexpr char kFS[] = R"(#version 310 es
11248 #extension GL_EXT_shader_io_blocks : require
11249 precision mediump float;
11250 
11251 layout(location = 0) out mediump vec4 color;
11252 
11253 layout(location = 1) in vec4 aIn;
11254 
11255 layout(location = 0) in GSBlock
11256 {
11257     vec4 b;
11258     layout(location = 3) vec4 c;
11259     layout(location = 7) vec4 d;
11260     layout(location = 5) vec4 e[2];
11261     layout(location = 4) vec4 f;
11262 } blockIn;
11263 
11264 layout(location = 2) in vec4 gIn;
11265 
11266 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
11267 
11268 void main()
11269 {
11270     bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
11271     bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
11272                  isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
11273                  isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
11274                  isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
11275                  isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
11276                  isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
11277     bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
11278 
11279     color = vec4(passR, passG, passB, 1.0);
11280 })";
11281 
11282     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
11283     EXPECT_GL_NO_ERROR();
11284 
11285     GLTexture color;
11286     glBindTexture(GL_TEXTURE_2D, color);
11287     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
11288 
11289     GLFramebuffer fbo;
11290     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
11291     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
11292 
11293     drawQuad(program, "position", 0);
11294 
11295     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
11296 }
11297 
11298 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)11299 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
11300 {
11301     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11302 
11303     constexpr char kVS[] = R"(#version 310 es
11304 #extension GL_EXT_shader_io_blocks : require
11305 
11306 in highp vec4 position;
11307 
11308 out VSBlock1
11309 {
11310     vec4 a;
11311     vec4 b[2];
11312 } blockOut1;
11313 
11314 out VSBlock2
11315 {
11316     vec4 c[2];
11317     vec4 d;
11318 } blockOut2;
11319 
11320 void main()
11321 {
11322     blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
11323     blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
11324     blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
11325     blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
11326     blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
11327     blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
11328     gl_Position = position;
11329 })";
11330 
11331     constexpr char kFS[] = R"(#version 310 es
11332 #extension GL_EXT_shader_io_blocks : require
11333 precision mediump float;
11334 
11335 layout(location = 0) out mediump vec4 color;
11336 
11337 in VSBlock1
11338 {
11339     vec4 a;
11340     vec4 b[2];
11341 } blockIn1;
11342 
11343 in VSBlock2
11344 {
11345     vec4 c[2];
11346     vec4 d;
11347 } blockIn2;
11348 
11349 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
11350 
11351 void main()
11352 {
11353     bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
11354     bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
11355                  isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
11356     bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
11357                  isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
11358     bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
11359 
11360     color = vec4(passR, passG, passB, passA);
11361 })";
11362 
11363     ANGLE_GL_PROGRAM(program, kVS, kFS);
11364     EXPECT_GL_NO_ERROR();
11365 
11366     GLTexture color;
11367     glBindTexture(GL_TEXTURE_2D, color);
11368     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
11369 
11370     GLFramebuffer fbo;
11371     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
11372     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
11373 
11374     drawQuad(program, "position", 0);
11375 
11376     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
11377 }
11378 
11379 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)11380 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
11381 {
11382     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11383 
11384     constexpr char kVS[] = R"(#version 310 es
11385 #extension GL_EXT_shader_io_blocks : require
11386 in highp vec4 position;
11387 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11388 void main()
11389 {
11390     blockOut1.a = vec4(0);
11391     blockOut1.b[0] = vec4(0);
11392     blockOut1.b[1] = vec4(0);
11393     gl_Position = position;
11394 })";
11395 
11396     constexpr char kFS[] = R"(#version 310 es
11397 #extension GL_EXT_shader_io_blocks : require
11398 precision mediump float;
11399 layout(location = 0) out mediump vec4 color;
11400 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
11401 void main()
11402 {
11403     color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11404 })";
11405 
11406     GLuint program = CompileProgram(kVS, kFS);
11407     EXPECT_EQ(0u, program);
11408 }
11409 
11410 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)11411 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
11412 {
11413     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11414 
11415     constexpr char kVS[] = R"(#version 310 es
11416 #extension GL_EXT_shader_io_blocks : require
11417 in highp vec4 position;
11418 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11419 void main()
11420 {
11421     blockOut1.a = vec4(0);
11422     blockOut1.b[0] = vec4(0);
11423     blockOut1.b[1] = vec4(0);
11424     gl_Position = position;
11425 })";
11426 
11427     constexpr char kFS[] = R"(#version 310 es
11428 #extension GL_EXT_shader_io_blocks : require
11429 precision mediump float;
11430 layout(location = 0) out mediump vec4 color;
11431 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
11432 void main()
11433 {
11434     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11435 })";
11436 
11437     GLuint program = CompileProgram(kVS, kFS);
11438     EXPECT_EQ(0u, program);
11439 }
11440 
11441 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)11442 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
11443 {
11444     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11445 
11446     constexpr char kVS[] = R"(#version 310 es
11447 #extension GL_EXT_shader_io_blocks : require
11448 in highp vec4 position;
11449 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11450 void main()
11451 {
11452     blockOut1.a = vec4(0);
11453     blockOut1.b[0] = vec4(0);
11454     blockOut1.b[1] = vec4(0);
11455     gl_Position = position;
11456 })";
11457 
11458     constexpr char kFS[] = R"(#version 310 es
11459 #extension GL_EXT_shader_io_blocks : require
11460 precision mediump float;
11461 layout(location = 0) out mediump vec4 color;
11462 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
11463 void main()
11464 {
11465     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11466 })";
11467 
11468     GLuint program = CompileProgram(kVS, kFS);
11469     EXPECT_EQ(0u, program);
11470 }
11471 
11472 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)11473 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
11474 {
11475     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11476 
11477     constexpr char kVS[] = R"(#version 310 es
11478 #extension GL_EXT_shader_io_blocks : require
11479 in highp vec4 position;
11480 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11481 void main()
11482 {
11483     blockOut1.a = vec4(0);
11484     blockOut1.b[0] = vec4(0);
11485     blockOut1.b[1] = vec4(0);
11486     gl_Position = position;
11487 })";
11488 
11489     constexpr char kFS[] = R"(#version 310 es
11490 #extension GL_EXT_shader_io_blocks : require
11491 precision mediump float;
11492 layout(location = 0) out mediump vec4 color;
11493 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
11494 void main()
11495 {
11496     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11497 })";
11498 
11499     GLuint program = CompileProgram(kVS, kFS);
11500     EXPECT_EQ(0u, program);
11501 }
11502 
11503 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)11504 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
11505 {
11506     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11507 
11508     constexpr char kVS[] = R"(#version 310 es
11509 #extension GL_EXT_shader_io_blocks : require
11510 in highp vec4 position;
11511 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
11512 void main()
11513 {
11514     blockOut1.a = vec4(0);
11515     blockOut1.b[0] = vec4(0);
11516     blockOut1.b[1] = vec4(0);
11517     gl_Position = position;
11518 })";
11519 
11520     constexpr char kFS[] = R"(#version 310 es
11521 #extension GL_EXT_shader_io_blocks : require
11522 precision mediump float;
11523 layout(location = 0) out mediump vec4 color;
11524 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
11525 void main()
11526 {
11527     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11528 })";
11529 
11530     GLuint program = CompileProgram(kVS, kFS);
11531     EXPECT_EQ(0u, program);
11532 }
11533 
11534 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)11535 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
11536 {
11537     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11538 
11539     constexpr char kVS[] = R"(#version 310 es
11540 #extension GL_EXT_shader_io_blocks : require
11541 in highp vec4 position;
11542 struct S1 { vec4 a; vec4 b[2]; };
11543 out VSBlock { S1 s; } blockOut1;
11544 void main()
11545 {
11546     blockOut1.s.a = vec4(0);
11547     blockOut1.s.b[0] = vec4(0);
11548     blockOut1.s.b[1] = vec4(0);
11549     gl_Position = position;
11550 })";
11551 
11552     constexpr char kFS[] = R"(#version 310 es
11553 #extension GL_EXT_shader_io_blocks : require
11554 precision mediump float;
11555 layout(location = 0) out mediump vec4 color;
11556 struct S2 { vec4 a; vec4 b[2]; };
11557 in VSBlock { S2 s; } blockIn1;
11558 void main()
11559 {
11560     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11561 })";
11562 
11563     GLuint program = CompileProgram(kVS, kFS);
11564     EXPECT_EQ(0u, program);
11565 }
11566 
11567 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)11568 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
11569 {
11570     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11571 
11572     constexpr char kVS[] = R"(#version 310 es
11573 #extension GL_EXT_shader_io_blocks : require
11574 in highp vec4 position;
11575 struct S { vec4 c; vec4 b[2]; };
11576 out VSBlock { S s; } blockOut1;
11577 void main()
11578 {
11579     blockOut1.s.c = vec4(0);
11580     blockOut1.s.b[0] = vec4(0);
11581     blockOut1.s.b[1] = vec4(0);
11582     gl_Position = position;
11583 })";
11584 
11585     constexpr char kFS[] = R"(#version 310 es
11586 #extension GL_EXT_shader_io_blocks : require
11587 precision mediump float;
11588 layout(location = 0) out mediump vec4 color;
11589 struct S { vec4 a; vec4 b[2]; };
11590 in VSBlock { S s; } blockIn1;
11591 void main()
11592 {
11593     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11594 })";
11595 
11596     GLuint program = CompileProgram(kVS, kFS);
11597     EXPECT_EQ(0u, program);
11598 }
11599 
11600 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)11601 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
11602 {
11603     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11604 
11605     constexpr char kVS[] = R"(#version 310 es
11606 #extension GL_EXT_shader_io_blocks : require
11607 in highp vec4 position;
11608 struct S { vec4 a; vec4 b[2]; };
11609 out VSBlock { S s; } blockOut1;
11610 void main()
11611 {
11612     blockOut1.s.a = vec4(0);
11613     blockOut1.s.b[0] = vec4(0);
11614     blockOut1.s.b[1] = vec4(0);
11615     gl_Position = position;
11616 })";
11617 
11618     constexpr char kFS[] = R"(#version 310 es
11619 #extension GL_EXT_shader_io_blocks : require
11620 precision mediump float;
11621 layout(location = 0) out mediump vec4 color;
11622 struct S { vec3 a; vec4 b[2]; };
11623 in VSBlock { S s; } blockIn1;
11624 void main()
11625 {
11626     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11627 })";
11628 
11629     GLuint program = CompileProgram(kVS, kFS);
11630     EXPECT_EQ(0u, program);
11631 }
11632 
11633 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)11634 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
11635 {
11636     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11637 
11638     constexpr char kVS[] = R"(#version 310 es
11639 #extension GL_EXT_shader_io_blocks : require
11640 in highp vec4 position;
11641 struct S { vec4 a; vec4 b[3]; };
11642 out VSBlock { S s; } blockOut1;
11643 void main()
11644 {
11645     blockOut1.s.a = vec4(0);
11646     blockOut1.s.b[0] = vec4(0);
11647     blockOut1.s.b[1] = vec4(0);
11648     gl_Position = position;
11649 })";
11650 
11651     constexpr char kFS[] = R"(#version 310 es
11652 #extension GL_EXT_shader_io_blocks : require
11653 precision mediump float;
11654 layout(location = 0) out mediump vec4 color;
11655 struct S { vec4 a; vec4 b[2]; };
11656 in VSBlock { S s; } blockIn1;
11657 void main()
11658 {
11659     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11660 })";
11661 
11662     GLuint program = CompileProgram(kVS, kFS);
11663     EXPECT_EQ(0u, program);
11664 }
11665 
11666 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)11667 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
11668 {
11669     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11670 
11671     constexpr char kVS[] = R"(#version 310 es
11672 #extension GL_EXT_shader_io_blocks : require
11673 in highp vec4 position;
11674 struct S { vec4 a; vec4 b[2]; vec4 c; };
11675 out VSBlock { S s; } blockOut1;
11676 void main()
11677 {
11678     blockOut1.s.c = vec4(0);
11679     blockOut1.s.b[0] = vec4(0);
11680     blockOut1.s.b[1] = vec4(0);
11681     gl_Position = position;
11682 })";
11683 
11684     constexpr char kFS[] = R"(#version 310 es
11685 #extension GL_EXT_shader_io_blocks : require
11686 precision mediump float;
11687 layout(location = 0) out mediump vec4 color;
11688 struct S { vec4 a; vec4 b[2]; };
11689 in VSBlock { S s; } blockIn1;
11690 void main()
11691 {
11692     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11693 })";
11694 
11695     GLuint program = CompileProgram(kVS, kFS);
11696     EXPECT_EQ(0u, program);
11697 }
11698 
11699 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)11700 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
11701 {
11702     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11703 
11704     constexpr char kVS[] = R"(#version 310 es
11705 #extension GL_EXT_shader_io_blocks : require
11706 in highp vec4 position;
11707 struct S1 { vec4 c; vec4 b[2]; };
11708 struct S2 { S1 s; };
11709 struct S3 { S2 s; };
11710 out VSBlock { S3 s; } blockOut1;
11711 void main()
11712 {
11713     blockOut1.s.s.s.c = vec4(0);
11714     blockOut1.s.s.s.b[0] = vec4(0);
11715     blockOut1.s.s.s.b[1] = vec4(0);
11716     gl_Position = position;
11717 })";
11718 
11719     constexpr char kFS[] = R"(#version 310 es
11720 #extension GL_EXT_shader_io_blocks : require
11721 precision mediump float;
11722 layout(location = 0) out mediump vec4 color;
11723 struct S1 { vec4 a; vec4 b[2]; };
11724 struct S2 { S1 s; };
11725 struct S3 { S2 s; };
11726 in VSBlock { S3 s; } blockIn1;
11727 void main()
11728 {
11729     color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
11730 })";
11731 
11732     GLuint program = CompileProgram(kVS, kFS);
11733     EXPECT_EQ(0u, program);
11734 }
11735 
11736 // Regression test for transformation bug which separates struct declarations from uniform
11737 // declarations.  The bug was that the uniform variable usage in the initializer of a new
11738 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)11739 TEST_P(GLSLTest, UniformStructBug)
11740 {
11741     constexpr char kVS[] = R"(precision highp float;
11742 
11743 uniform struct Global
11744 {
11745     float x;
11746 } u_global;
11747 
11748 void main() {
11749   float y = u_global.x;
11750 
11751   gl_Position = vec4(y);
11752 })";
11753 
11754     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
11755 
11756     const char *sourceArray[1] = {kVS};
11757     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
11758     glShaderSource(shader, 1, sourceArray, lengths);
11759     glCompileShader(shader);
11760 
11761     GLint compileResult;
11762     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
11763     EXPECT_NE(compileResult, 0);
11764 }
11765 
11766 // Regression test for transformation bug which separates struct declarations from uniform
11767 // declarations.  The bug was that the arrayness of the declaration was not being applied to the
11768 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)11769 TEST_P(GLSLTest_ES31, UniformStructBug2)
11770 {
11771     constexpr char kVS[] = R"(#version 310 es
11772 precision highp float;
11773 
11774 uniform struct Global
11775 {
11776     float x;
11777 } u_global[2][3];
11778 
11779 void main() {
11780   float y = u_global[0][0].x;
11781 
11782   gl_Position = vec4(y);
11783 })";
11784 
11785     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
11786 
11787     const char *sourceArray[1] = {kVS};
11788     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
11789     glShaderSource(shader, 1, sourceArray, lengths);
11790     glCompileShader(shader);
11791 
11792     GLint compileResult;
11793     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
11794     EXPECT_NE(compileResult, 0);
11795 }
11796 
11797 // Test that providing more components to a matrix constructor than necessary works.  Based on a
11798 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)11799 TEST_P(GLSLTest, MatrixConstructor)
11800 {
11801     constexpr char kVS[] = R"(attribute vec4 aPosition;
11802 varying vec4 vColor;
11803 void main()
11804 {
11805     gl_Position = aPosition;
11806     vec4 color = vec4(aPosition.xy, 0, 1);
11807     mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
11808     vColor = m4[0];
11809 })";
11810 
11811     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
11812     EXPECT_NE(0u, shader);
11813     glDeleteShader(shader);
11814 }
11815 
11816 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)11817 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
11818 {
11819     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
11820 
11821     constexpr char kVS[] = R"(#version 300 es
11822 #extension GL_EXT_shader_non_constant_global_initializers : require
11823 uniform vec4 u;
11824 out vec4 color;
11825 
11826 vec4 global1 = u;
11827 vec4 global2 = u + vec4(1);
11828 vec4 global3 = global1 * global2;
11829 void main()
11830 {
11831     color = global3;
11832 })";
11833 
11834     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
11835     EXPECT_NE(0u, shader);
11836     glDeleteShader(shader);
11837 }
11838 
11839 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)11840 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
11841 {
11842     constexpr char kFS[] = R"(#version 300 es
11843 precision highp float;
11844 out vec4 color;
11845 
11846 struct T
11847 {
11848     float f;
11849 };
11850 
11851 struct S
11852 {
11853     vec4 v;
11854     mat3x4 m[2];
11855     T t;
11856 };
11857 
11858 S s = S(
11859         vec4(0, 1, 2, 3),
11860         mat3x4[2](
11861                   mat3x4(
11862                          vec4(4, 5, 6, 7),
11863                          vec4(8, 9, 10, 11),
11864                          vec4(12, 13, 14, 15)
11865                   ),
11866                   mat3x4(
11867                          vec4(16, 17, 18, 19),
11868                          vec4(20, 21, 22, 23),
11869                          vec4(24, 25, 26, 27)
11870                   )
11871         ),
11872         T(28.0)
11873        );
11874 
11875 void main()
11876 {
11877     vec4 result = vec4(0, 1, 0, 1);
11878 
11879     if (s.v != vec4(0, 1, 2, 3))
11880         result = vec4(1, 0, 0, 0);
11881 
11882     for (int index = 0; index < 2; ++index)
11883     {
11884         for (int column = 0; column < 3; ++column)
11885         {
11886             int expect = index * 12 + column * 4 + 4;
11887             if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
11888                 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
11889         }
11890     }
11891 
11892     if (s.t.f != 28.0)
11893         result = vec4(0, 0, 1, 0);
11894 
11895     color = result;
11896 })";
11897 
11898     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11899 
11900     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11901     EXPECT_GL_NO_ERROR();
11902 
11903     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11904 }
11905 
11906 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)11907 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
11908 {
11909     constexpr char kFS[] = R"(#version 310 es
11910 precision highp float;
11911 precision highp int;
11912 
11913 out vec4 color;
11914 
11915 uniform float f;    // = 3.41
11916 uniform uvec4 u1;   // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
11917 uniform uvec4 u2;   // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
11918 
11919 struct S
11920 {
11921     float fvalue;
11922     int ivalues[2];
11923     uvec4 uvalues[3];
11924 };
11925 
11926 struct T
11927 {
11928     S s[2];
11929 };
11930 
11931 void main()
11932 {
11933     float integer;
11934     float fraction = modf(f, integer);
11935 
11936     T t;
11937 
11938     t.s[0].fvalue     = frexp(f, t.s[0].ivalues[0]);
11939     float significand = t.s[0].fvalue;
11940     int exponent      = t.s[0].ivalues[0];
11941 
11942     t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
11943     uvec4 addResult   = t.s[0].uvalues[0];
11944     uvec4 addCarry    = t.s[0].uvalues[1].yxwz;
11945 
11946     t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
11947     uvec2 subResult      = t.s[0].uvalues[2].wx;
11948     uvec2 subBorrow      = t.s[1].uvalues[0].wx;
11949 
11950     umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
11951     uvec4 mulMsb = t.s[1].uvalues[1];
11952     uvec4 mulLsb = t.s[1].uvalues[2];
11953 
11954     ivec2 imulMsb, imulLsb;
11955     imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
11956 
11957     bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
11958     bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
11959     bool addPassed =
11960         addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
11961         addCarry == uvec4(1, 0, 1, 0);
11962     bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
11963     bool mulPassed =
11964         mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
11965         mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
11966     bool imulPassed =
11967         imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
11968         imulLsb == ivec2(0x35068740, 0x822E97E0);
11969 
11970     color = vec4(modfPassed ? 1 : 0,
11971                  frexpPassed ? 1 : 0,
11972                  (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
11973                  (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
11974 })";
11975 
11976     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
11977     glUseProgram(program);
11978 
11979     GLint floc  = glGetUniformLocation(program, "f");
11980     GLint u1loc = glGetUniformLocation(program, "u1");
11981     GLint u2loc = glGetUniformLocation(program, "u2");
11982     ASSERT_NE(floc, -1);
11983     ASSERT_NE(u1loc, -1);
11984     ASSERT_NE(u2loc, -1);
11985     glUniform1f(floc, 3.41);
11986     glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
11987     glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
11988 
11989     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
11990     EXPECT_GL_NO_ERROR();
11991 
11992     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
11993 }
11994 
11995 // Test that interpolateAt* work with swizzle.  This test is disabled as swizzled interpolants are
11996 // only allowed in desktop GLSL.
TEST_P(GLSLTest_ES31,InterpolateAtWithSwizzle)11997 TEST_P(GLSLTest_ES31, InterpolateAtWithSwizzle)
11998 {
11999     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
12000 
12001     constexpr char kVS[] = R"(#version 310 es
12002 
12003 out vec4 interpolant;
12004 
12005 void main()
12006 {
12007     // The following triangle is being drawn over the framebuffer.
12008     //
12009     //   (-1,3) |\
12010     //          |   \
12011     //          |      \
12012     //          |         \
12013     //          |            \
12014     //          +--------------+
12015     //          |              | \
12016     //          |              |    \
12017     //          | Framebuffer  |       \
12018     //          |              |          \
12019     //          |              |             \
12020     //  (-1,-1) +--------------+--------------- (3,-1)
12021     //
12022     // Interpolant is set such that interpolateAtCentroid would produce the desired value for
12023     // position == (0, 0), and interpolateAtOffset(0.5, -0.5) for position == (1,-1)
12024     if (gl_VertexID == 0)
12025     {
12026         gl_Position = vec4(-1, -1, 0, 1);
12027         interpolant = vec4(1.5, 0.5, 0, 0);
12028     }
12029     else if (gl_VertexID == 1)
12030     {
12031         gl_Position = vec4(3, -1, 0, 1);
12032         interpolant = vec4(0, 0, 1, 2);
12033     }
12034     else
12035     {
12036         gl_Position = vec4(-1, 3, 0, 1);
12037         interpolant = vec4(0, 1, -1, 2);
12038     }
12039 })";
12040 
12041     constexpr char kFS[] = R"(#version 310 es
12042 #extension GL_OES_shader_multisample_interpolation : require
12043 precision highp float;
12044 
12045 in vec4 interpolant;
12046 out vec4 color;
12047 
12048 void main()
12049 {
12050     // Should result in (0.75, 1.0)
12051     vec2 atCentroid = interpolateAtCentroid(interpolant.xw);
12052     // Selecting the bottom-right corner, this should result in (0.5, 0.25), but interpolateAtOffset
12053     // doesn't make guarantees regarding the range and granularity of the offset.  The interpolant
12054     // is given values such that the bottom-left/top-right diagonal is interpolated to a constant
12055     // value of (0, 0.5).  The top-left corner has the value (-0.5, 0.75).  We therefore make a
12056     // coarse test to make sure that atOffset.x > 0 and atOffset.y < 0.5, thus ensuring at least
12057     // that the offset is in the correct half of the pixel.
12058     vec2 atOffset = interpolateAtOffset(interpolant.zy, vec2(0.5, -0.5));
12059 
12060     color = vec4(atCentroid, atOffset.x > 0.0 ? 1 : 0, atOffset.y < 0.5 ? 1 : 0);
12061 })";
12062 
12063     GLRenderbuffer rbo;
12064     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
12065     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
12066 
12067     GLFramebuffer fbo;
12068     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12069     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
12070     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12071 
12072     ANGLE_GL_PROGRAM(program, kVS, kFS);
12073     glUseProgram(program);
12074 
12075     glViewport(0, 0, 1, 1);
12076     glDrawArrays(GL_TRIANGLES, 0, 3);
12077     EXPECT_GL_NO_ERROR();
12078 
12079     EXPECT_PIXEL_NEAR(0, 0, 191, 255, 255, 255, 1);
12080 }
12081 
12082 class GLSLTestLoops : public GLSLTest
12083 {
12084   protected:
runTest(const char * fs)12085     void runTest(const char *fs)
12086     {
12087         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
12088 
12089         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12090         EXPECT_GL_NO_ERROR();
12091 
12092         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12093     }
12094 };
12095 
12096 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)12097 TEST_P(GLSLTestLoops, BasicFor)
12098 {
12099     constexpr char kFS[] = R"(#version 300 es
12100 precision mediump float;
12101 out vec4 color;
12102 
12103 void main()
12104 {
12105     int result = 0;
12106     for (int i = 0; i < 10; ++i)
12107         for (int j = 0; j < 8; ++j)
12108         {
12109             for (int k = 0; k < 2; ++k, ++j) ++result;
12110             for (int k = 0; k < 3; ++k)      ++result;
12111             for (int k = 0; k < 0; ++k)      ++result;
12112         }
12113 
12114     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12115 })";
12116 
12117     runTest(kFS);
12118 }
12119 
12120 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)12121 TEST_P(GLSLTestLoops, ForNoCondition)
12122 {
12123     constexpr char kFS[] = R"(#version 300 es
12124 precision mediump float;
12125 out vec4 color;
12126 
12127 void main()
12128 {
12129     int result = 0;
12130     for (int i = 0; i < 10; ++i)
12131         for (int j = 0; ; ++j)
12132         {
12133             for (int k = 0; k < 2; ++k, ++j) ++result;
12134             for (int k = 0; k < 3; ++k)      ++result;
12135             for (int k = 0; k < 0; ++k)      ++result;
12136 
12137             if (j >= 8)
12138                 break;
12139         }
12140 
12141     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12142 })";
12143 
12144     runTest(kFS);
12145 }
12146 
12147 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)12148 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
12149 {
12150     constexpr char kFS[] = R"(#version 300 es
12151 precision mediump float;
12152 out vec4 color;
12153 
12154 void main()
12155 {
12156     int result = 0;
12157     for (int i = 0; i < 10; ++i)
12158     {
12159         int j = 0;
12160         for (;;)
12161         {
12162             for (int k = 0; k < 2; ++k, ++j) ++result;
12163             for (int k = 0; k < 3; ++k)      ++result;
12164             for (int k = 0; k < 0; ++k)      ++result;
12165 
12166             if (j >= 8)
12167                 break;
12168             ++j;
12169         }
12170     }
12171 
12172     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12173 })";
12174 
12175     runTest(kFS);
12176 }
12177 
12178 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)12179 TEST_P(GLSLTestLoops, ForContinue)
12180 {
12181     constexpr char kFS[] = R"(#version 300 es
12182 precision mediump float;
12183 out vec4 color;
12184 
12185 void main()
12186 {
12187     int result = 0;
12188     for (int i = 0; i < 10; ++i)
12189         for (int j = 0; j < 8; ++j)
12190         {
12191             for (int k = 0; k < 2; ++k, ++j) ++result;
12192             for (int k = 0; k < 3; ++k)      ++result;
12193             if (i > 3)
12194                 continue;
12195             for (int k = 0; k < 0; ++k)      ++result;
12196         }
12197 
12198     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12199 })";
12200 
12201     runTest(kFS);
12202 }
12203 
12204 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)12205 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
12206 {
12207     constexpr char kFS[] = R"(#version 300 es
12208 precision mediump float;
12209 out vec4 color;
12210 
12211 void main()
12212 {
12213     int result = 0;
12214     for (int i = 0; i < 10; ++i)
12215         for (int j = 0; j < 8; ++j)
12216         {
12217             for (int k = 0; k < 2; ++k, ++j) ++result;
12218             for (int k = 0; k < 3; ++k)      ++result;
12219             for (int k = 0; k < 0; ++k)      ++result;
12220             continue;
12221         }
12222 
12223     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12224 })";
12225 
12226     runTest(kFS);
12227 }
12228 
12229 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)12230 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
12231 {
12232     constexpr char kFS[] = R"(#version 300 es
12233 precision mediump float;
12234 out vec4 color;
12235 
12236 void main()
12237 {
12238     int result = 0;
12239     for (int i = 0; i < 10; ++i)
12240         for (int j = 0; j < 8; ++j)
12241         {
12242             for (int k = 0; k < 2; ++k, ++j) ++result;
12243             for (int k = 0; k < 3; ++k)      ++result;
12244             for (int k = 0; k < 0; ++k)      ++result;
12245             break;
12246         }
12247 
12248     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12249 })";
12250 
12251     runTest(kFS);
12252 }
12253 
12254 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)12255 TEST_P(GLSLTestLoops, ForBreakContinue)
12256 {
12257     constexpr char kFS[] = R"(#version 300 es
12258 precision mediump float;
12259 out vec4 color;
12260 
12261 void main()
12262 {
12263     int result = 0;
12264     for (int i = 0; i < 10; ++i)
12265         for (int j = 0; j < 8; ++j)
12266         {
12267             if (j < 2) continue;
12268             if (j > 6) break;
12269             if (i < 3) continue;
12270             if (i > 8) break;
12271             ++result;
12272         }
12273 
12274     color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12275 })";
12276 
12277     runTest(kFS);
12278 }
12279 
12280 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)12281 TEST_P(GLSLTestLoops, BasicWhile)
12282 {
12283     constexpr char kFS[] = R"(#version 300 es
12284 precision mediump float;
12285 out vec4 color;
12286 
12287 void main()
12288 {
12289     int result = 0;
12290     int i = 0;
12291     while (i < 10)
12292     {
12293         int j = 0;
12294         while (j < 8)
12295         {
12296             int k = 0;
12297             while (k < 2) { ++result; ++k; ++j; }
12298             while (k < 5) { ++result; ++k; }
12299             while (k < 4) { ++result; }
12300             ++j;
12301         }
12302         ++i;
12303     }
12304 
12305     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12306 })";
12307 
12308     runTest(kFS);
12309 }
12310 
12311 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)12312 TEST_P(GLSLTestLoops, WhileContinue)
12313 {
12314     constexpr char kFS[] = R"(#version 300 es
12315 precision mediump float;
12316 out vec4 color;
12317 
12318 void main()
12319 {
12320     int result = 0;
12321     int i = 0;
12322     while (i < 10)
12323     {
12324         int j = 0;
12325         while (j < 8)
12326         {
12327             int k = 0;
12328             while (k < 2) { ++result; ++k; ++j; }
12329             while (k < 5) { ++result; ++k; }
12330             if (i > 3)
12331             {
12332                 ++j;
12333                 continue;
12334             }
12335             while (k < 4) { ++result; }
12336             ++j;
12337         }
12338         ++i;
12339     }
12340 
12341     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12342 })";
12343 
12344     runTest(kFS);
12345 }
12346 
12347 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)12348 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
12349 {
12350     constexpr char kFS[] = R"(#version 300 es
12351 precision mediump float;
12352 out vec4 color;
12353 
12354 void main()
12355 {
12356     int result = 0;
12357     int i = 0;
12358     while (i < 10)
12359     {
12360         int j = 0;
12361         while (j < 8)
12362         {
12363             int k = 0;
12364             while (k < 2) { ++result; ++k; ++j; }
12365             while (k < 5) { ++result; ++k; }
12366             while (k < 4) { ++result; }
12367             ++j;
12368             continue;
12369         }
12370         ++i;
12371     }
12372 
12373     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12374 })";
12375 
12376     runTest(kFS);
12377 }
12378 
12379 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)12380 TEST_P(GLSLTestLoops, WhileBreak)
12381 {
12382     constexpr char kFS[] = R"(#version 300 es
12383 precision mediump float;
12384 out vec4 color;
12385 
12386 void main()
12387 {
12388     int result = 0;
12389     int i = 0;
12390     while (i < 10)
12391     {
12392         int j = 0;
12393         while (true)
12394         {
12395             int k = 0;
12396             while (k < 2) { ++result; ++k; ++j; }
12397             while (k < 5) { ++result; ++k; }
12398             while (k < 4) { ++result; }
12399             ++j;
12400             if (j >= 8)
12401                 break;
12402         }
12403         ++i;
12404     }
12405 
12406     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12407 })";
12408 
12409     runTest(kFS);
12410 }
12411 
12412 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)12413 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
12414 {
12415     constexpr char kFS[] = R"(#version 300 es
12416 precision mediump float;
12417 out vec4 color;
12418 
12419 void main()
12420 {
12421     int result = 0;
12422     int i = 0;
12423     while (i < 10)
12424     {
12425         int j = 0;
12426         while (j < 8)
12427         {
12428             int k = 0;
12429             while (k < 2) { ++result; ++k; ++j; }
12430             while (k < 5) { ++result; ++k; }
12431             while (k < 4) { ++result; }
12432             ++j;
12433             break;
12434         }
12435         ++i;
12436     }
12437 
12438     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12439 })";
12440 
12441     runTest(kFS);
12442 }
12443 
12444 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)12445 TEST_P(GLSLTestLoops, BasicDoWhile)
12446 {
12447     constexpr char kFS[] = R"(#version 300 es
12448 precision mediump float;
12449 out vec4 color;
12450 
12451 void main()
12452 {
12453     int result = 0;
12454     int i = 0;
12455     do
12456     {
12457         int j = 0;
12458         do
12459         {
12460             int k = 0;
12461             do { ++result; ++k; ++j; } while (k < 2);
12462             do { ++result; ++k;      } while (k < 5);
12463             do { ++result;           } while (k < 3);
12464             ++j;
12465         } while (j < 8);
12466         ++i;
12467     } while (i < 10);
12468 
12469     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12470 })";
12471 
12472     runTest(kFS);
12473 }
12474 
12475 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)12476 TEST_P(GLSLTestLoops, DoWhileContinue)
12477 {
12478     constexpr char kFS[] = R"(#version 300 es
12479 precision mediump float;
12480 out vec4 color;
12481 
12482 void main()
12483 {
12484     int result = 0;
12485     int i = 0;
12486     do
12487     {
12488         int j = 0;
12489         do
12490         {
12491             int k = 0;
12492             do { ++result; ++k; ++j; } while (k < 2);
12493             if (i > 3)
12494             {
12495                 ++j;
12496                 continue;
12497             }
12498             do { ++result; ++k;      } while (k < 5);
12499             do { ++result;           } while (k < 3);
12500             ++j;
12501         } while (j < 8);
12502         ++i;
12503     } while (i < 10);
12504 
12505     color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12506 })";
12507 
12508     runTest(kFS);
12509 }
12510 
12511 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)12512 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
12513 {
12514     constexpr char kFS[] = R"(#version 300 es
12515 precision mediump float;
12516 out vec4 color;
12517 
12518 void main()
12519 {
12520     int result = 0;
12521     int i = 0;
12522     do
12523     {
12524         int j = 0;
12525         do
12526         {
12527             int k = 0;
12528             do { ++result; ++k; ++j; continue; } while (k < 2);
12529             do { ++result; ++k;      continue; } while (k < 5);
12530             do { ++result;           continue; } while (k < 3);
12531             ++j;
12532         } while (j < 8);
12533         ++i;
12534     } while (i < 10);
12535 
12536     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12537 })";
12538 
12539     runTest(kFS);
12540 }
12541 
12542 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)12543 TEST_P(GLSLTestLoops, DoWhileBreak)
12544 {
12545     constexpr char kFS[] = R"(#version 300 es
12546 precision mediump float;
12547 out vec4 color;
12548 
12549 void main()
12550 {
12551     int result = 0;
12552     int i = 0;
12553     do
12554     {
12555         int j = 0;
12556         do
12557         {
12558             int k = 0;
12559             do { ++result; ++k; ++j; } while (k < 2);
12560             do { ++result; ++k;      } while (k < 5);
12561             do { ++result;           } while (k < 3);
12562             ++j;
12563             if (j >= 8)
12564                 break;
12565         } while (true);
12566         ++i;
12567     } while (i < 10);
12568 
12569     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12570 })";
12571 
12572     runTest(kFS);
12573 }
12574 
12575 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)12576 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
12577 {
12578     constexpr char kFS[] = R"(#version 300 es
12579 precision mediump float;
12580 out vec4 color;
12581 
12582 void main()
12583 {
12584     int result = 0;
12585     int i = 0;
12586     do
12587     {
12588         int j = 0;
12589         do
12590         {
12591             int k = 0;
12592             do { ++result; ++k; ++j; break; } while (k < 2);
12593             do { ++result; ++k;      break; } while (k < 5);
12594             do { ++result;           break; } while (k < 3);
12595             ++j;
12596         } while (j < 8);
12597         ++i;
12598     } while (i < 10);
12599 
12600     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12601 })";
12602 
12603     runTest(kFS);
12604 }
12605 
12606 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)12607 TEST_P(GLSLTestLoops, ForContinueInSwitch)
12608 {
12609     constexpr char kFS[] = R"(#version 300 es
12610 precision mediump float;
12611 out vec4 color;
12612 
12613 void main()
12614 {
12615     int result = 0;
12616     for (int i = 0; i < 10; ++i)
12617         for (int j = 0; j < 8; ++j)
12618         {
12619             switch (j)
12620             {
12621                 case 2:
12622                 case 3:
12623                 case 4:
12624                     ++result;
12625                     // fallthrough
12626                 case 5:
12627                 case 6:
12628                     ++result;
12629                     break;
12630                 default:
12631                     continue;
12632             }
12633         }
12634 
12635     color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12636 })";
12637 
12638     runTest(kFS);
12639 }
12640 
12641 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)12642 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
12643 {
12644     constexpr char kFS[] = R"(#version 300 es
12645 precision mediump float;
12646 out vec4 color;
12647 
12648 void main()
12649 {
12650     int result = 0;
12651     int i = 0;
12652     while (i < 10)
12653     {
12654         int j = 0;
12655         while (j < 8)
12656         {
12657             switch (j)
12658             {
12659                 case 2:
12660                 default:
12661                 case 3:
12662                 case 4:
12663                     ++j;
12664                     ++result;
12665                     continue;
12666                 case 0:
12667                 case 1:
12668                 case 7:
12669                     break;
12670             }
12671             ++j;
12672         }
12673         ++i;
12674     }
12675 
12676     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12677 })";
12678 
12679     runTest(kFS);
12680 }
12681 
12682 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)12683 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
12684 {
12685     constexpr char kFS[] = R"(#version 300 es
12686 precision mediump float;
12687 out vec4 color;
12688 
12689 void main()
12690 {
12691     int result = 0;
12692     int i = 0;
12693     do
12694     {
12695         int j = 0;
12696         do
12697         {
12698             switch (j)
12699             {
12700                 case 0:
12701                     ++j;
12702                     continue;
12703                 default:
12704                 case 2:
12705                 case 3:
12706                 case 4:
12707                     ++j;
12708                     ++result;
12709                     if (j >= 2 && j <= 6)
12710                         break;
12711                     else
12712                         continue;
12713             }
12714             ++result;
12715         } while (j < 8);
12716         ++i;
12717     } while (i < 10);
12718 
12719     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12720 })";
12721 
12722     runTest(kFS);
12723 }
12724 
12725 }  // anonymous namespace
12726 
12727 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(GLSLTest, WithDirectSPIRVGeneration(ES2_VULKAN()));
12728 
12729 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
12730 
12731 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
12732 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTest_ES3, WithDirectSPIRVGeneration(ES3_VULKAN()));
12733 
12734 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
12735 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTestLoops, WithDirectSPIRVGeneration(ES3_VULKAN()));
12736 
12737 ANGLE_INSTANTIATE_TEST_ES2_AND(WebGLGLSLTest, WithDirectSPIRVGeneration(ES2_VULKAN()));
12738 
12739 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
12740 ANGLE_INSTANTIATE_TEST_ES3_AND(WebGL2GLSLTest, WithDirectSPIRVGeneration(ES3_VULKAN()));
12741 
12742 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
12743 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31, WithDirectSPIRVGeneration(ES31_VULKAN()));
12744