1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "test_utils/ANGLETest.h"
8
9 #include "test_utils/gl_raii.h"
10 #include "util/shader_utils.h"
11
12 using namespace angle;
13
14 namespace
15 {
16 class GLSLTest : public ANGLETest<>
17 {
18 protected:
GLSLTest()19 GLSLTest()
20 {
21 setWindowWidth(128);
22 setWindowHeight(128);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 }
28
GenerateVaryingType(GLint vectorSize)29 std::string GenerateVaryingType(GLint vectorSize)
30 {
31 char varyingType[10];
32
33 if (vectorSize == 1)
34 {
35 snprintf(varyingType, sizeof(varyingType), "float");
36 }
37 else
38 {
39 snprintf(varyingType, sizeof(varyingType), "vec%d", vectorSize);
40 }
41
42 return std::string(varyingType);
43 }
44
GenerateVectorVaryingDeclaration(GLint vectorSize,GLint arraySize,GLint id)45 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
46 {
47 char buff[100];
48
49 if (arraySize == 1)
50 {
51 snprintf(buff, sizeof(buff), "varying %s v%d;\n",
52 GenerateVaryingType(vectorSize).c_str(), id);
53 }
54 else
55 {
56 snprintf(buff, sizeof(buff), "varying %s v%d[%d];\n",
57 GenerateVaryingType(vectorSize).c_str(), id, arraySize);
58 }
59
60 return std::string(buff);
61 }
62
GenerateVectorVaryingSettingCode(GLint vectorSize,GLint arraySize,GLint id)63 std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
64 {
65 std::string returnString;
66 char buff[100];
67
68 if (arraySize == 1)
69 {
70 snprintf(buff, sizeof(buff), "\t v%d = %s(1.0);\n", id,
71 GenerateVaryingType(vectorSize).c_str());
72 returnString += buff;
73 }
74 else
75 {
76 for (int i = 0; i < arraySize; i++)
77 {
78 snprintf(buff, sizeof(buff), "\t v%d[%d] = %s(1.0);\n", id, i,
79 GenerateVaryingType(vectorSize).c_str());
80 returnString += buff;
81 }
82 }
83
84 return returnString;
85 }
86
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)87 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
88 {
89 if (arraySize == 1)
90 {
91 char buff[100];
92 snprintf(buff, sizeof(buff), "v%d + ", id);
93 return std::string(buff);
94 }
95 else
96 {
97 std::string returnString;
98 for (int i = 0; i < arraySize; i++)
99 {
100 char buff[100];
101 snprintf(buff, sizeof(buff), "v%d[%d] + ", id, i);
102 returnString += buff;
103 }
104 return returnString;
105 }
106 }
107
GenerateGLSLWithVaryings(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,std::string * fragmentShader,std::string * vertexShader)108 void GenerateGLSLWithVaryings(GLint floatCount,
109 GLint floatArrayCount,
110 GLint vec2Count,
111 GLint vec2ArrayCount,
112 GLint vec3Count,
113 GLint vec3ArrayCount,
114 GLint vec4Count,
115 GLint vec4ArrayCount,
116 bool useFragCoord,
117 bool usePointCoord,
118 bool usePointSize,
119 std::string *fragmentShader,
120 std::string *vertexShader)
121 {
122 // Generate a string declaring the varyings, to share between the fragment shader and the
123 // vertex shader.
124 std::string varyingDeclaration;
125
126 unsigned int varyingCount = 0;
127
128 for (GLint i = 0; i < floatCount; i++)
129 {
130 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
131 varyingCount += 1;
132 }
133
134 for (GLint i = 0; i < floatArrayCount; i++)
135 {
136 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
137 varyingCount += 1;
138 }
139
140 for (GLint i = 0; i < vec2Count; i++)
141 {
142 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
143 varyingCount += 1;
144 }
145
146 for (GLint i = 0; i < vec2ArrayCount; i++)
147 {
148 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
149 varyingCount += 1;
150 }
151
152 for (GLint i = 0; i < vec3Count; i++)
153 {
154 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
155 varyingCount += 1;
156 }
157
158 for (GLint i = 0; i < vec3ArrayCount; i++)
159 {
160 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
161 varyingCount += 1;
162 }
163
164 for (GLint i = 0; i < vec4Count; i++)
165 {
166 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
167 varyingCount += 1;
168 }
169
170 for (GLint i = 0; i < vec4ArrayCount; i++)
171 {
172 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
173 varyingCount += 1;
174 }
175
176 // Generate the vertex shader
177 vertexShader->clear();
178 vertexShader->append(varyingDeclaration);
179 vertexShader->append("\nvoid main()\n{\n");
180
181 unsigned int currentVSVarying = 0;
182
183 for (GLint i = 0; i < floatCount; i++)
184 {
185 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
186 currentVSVarying += 1;
187 }
188
189 for (GLint i = 0; i < floatArrayCount; i++)
190 {
191 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
192 currentVSVarying += 1;
193 }
194
195 for (GLint i = 0; i < vec2Count; i++)
196 {
197 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
198 currentVSVarying += 1;
199 }
200
201 for (GLint i = 0; i < vec2ArrayCount; i++)
202 {
203 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
204 currentVSVarying += 1;
205 }
206
207 for (GLint i = 0; i < vec3Count; i++)
208 {
209 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
210 currentVSVarying += 1;
211 }
212
213 for (GLint i = 0; i < vec3ArrayCount; i++)
214 {
215 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
216 currentVSVarying += 1;
217 }
218
219 for (GLint i = 0; i < vec4Count; i++)
220 {
221 vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
222 currentVSVarying += 1;
223 }
224
225 for (GLint i = 0; i < vec4ArrayCount; i++)
226 {
227 vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
228 currentVSVarying += 1;
229 }
230
231 if (usePointSize)
232 {
233 vertexShader->append("gl_PointSize = 1.0;\n");
234 }
235
236 vertexShader->append("}\n");
237
238 // Generate the fragment shader
239 fragmentShader->clear();
240 fragmentShader->append("precision highp float;\n");
241 fragmentShader->append(varyingDeclaration);
242 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
243
244 unsigned int currentFSVarying = 0;
245
246 // Make use of the float varyings
247 fragmentShader->append("\tretColor += vec4(");
248
249 for (GLint i = 0; i < floatCount; i++)
250 {
251 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
252 currentFSVarying += 1;
253 }
254
255 for (GLint i = 0; i < floatArrayCount; i++)
256 {
257 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
258 currentFSVarying += 1;
259 }
260
261 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
262
263 // Make use of the vec2 varyings
264 fragmentShader->append("\tretColor += vec4(");
265
266 for (GLint i = 0; i < vec2Count; i++)
267 {
268 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
269 currentFSVarying += 1;
270 }
271
272 for (GLint i = 0; i < vec2ArrayCount; i++)
273 {
274 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
275 currentFSVarying += 1;
276 }
277
278 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
279
280 // Make use of the vec3 varyings
281 fragmentShader->append("\tretColor += vec4(");
282
283 for (GLint i = 0; i < vec3Count; i++)
284 {
285 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
286 currentFSVarying += 1;
287 }
288
289 for (GLint i = 0; i < vec3ArrayCount; i++)
290 {
291 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
292 currentFSVarying += 1;
293 }
294
295 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
296
297 // Make use of the vec4 varyings
298 fragmentShader->append("\tretColor += ");
299
300 for (GLint i = 0; i < vec4Count; i++)
301 {
302 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
303 currentFSVarying += 1;
304 }
305
306 for (GLint i = 0; i < vec4ArrayCount; i++)
307 {
308 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
309 currentFSVarying += 1;
310 }
311
312 fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
313
314 // Set gl_FragColor, and use special variables if requested
315 fragmentShader->append("\tgl_FragColor = retColor");
316
317 if (useFragCoord)
318 {
319 fragmentShader->append(" + gl_FragCoord");
320 }
321
322 if (usePointCoord)
323 {
324 fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
325 }
326
327 fragmentShader->append(";\n}");
328 }
329
VaryingTestBase(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,bool expectSuccess)330 void VaryingTestBase(GLint floatCount,
331 GLint floatArrayCount,
332 GLint vec2Count,
333 GLint vec2ArrayCount,
334 GLint vec3Count,
335 GLint vec3ArrayCount,
336 GLint vec4Count,
337 GLint vec4ArrayCount,
338 bool useFragCoord,
339 bool usePointCoord,
340 bool usePointSize,
341 bool expectSuccess)
342 {
343 std::string fragmentShaderSource;
344 std::string vertexShaderSource;
345
346 GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
347 vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
348 usePointCoord, usePointSize, &fragmentShaderSource,
349 &vertexShaderSource);
350
351 GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
352
353 if (expectSuccess)
354 {
355 EXPECT_NE(0u, program);
356 }
357 else
358 {
359 EXPECT_EQ(0u, program);
360 }
361 }
362
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)363 void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
364 GLint fragmentUniformCount,
365 GLint vertexSamplersCount,
366 GLint fragmentSamplersCount,
367 bool expectSuccess)
368 {
369 std::stringstream vertexShader;
370 std::stringstream fragmentShader;
371
372 // Generate the vertex shader
373 vertexShader << "precision mediump float;\n";
374
375 for (int i = 0; i < vertexUniformCount; i++)
376 {
377 vertexShader << "uniform vec4 v" << i << ";\n";
378 }
379
380 for (int i = 0; i < vertexSamplersCount; i++)
381 {
382 vertexShader << "uniform sampler2D s" << i << ";\n";
383 }
384
385 vertexShader << "void main()\n{\n";
386
387 for (int i = 0; i < vertexUniformCount; i++)
388 {
389 vertexShader << " gl_Position += v" << i << ";\n";
390 }
391
392 for (int i = 0; i < vertexSamplersCount; i++)
393 {
394 vertexShader << " gl_Position += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
395 }
396
397 if (vertexUniformCount == 0 && vertexSamplersCount == 0)
398 {
399 vertexShader << " gl_Position = vec4(0.0);\n";
400 }
401
402 vertexShader << "}\n";
403
404 // Generate the fragment shader
405 fragmentShader << "precision mediump float;\n";
406
407 for (int i = 0; i < fragmentUniformCount; i++)
408 {
409 fragmentShader << "uniform vec4 v" << i << ";\n";
410 }
411
412 for (int i = 0; i < fragmentSamplersCount; i++)
413 {
414 fragmentShader << "uniform sampler2D s" << i << ";\n";
415 }
416
417 fragmentShader << "void main()\n{\n";
418
419 for (int i = 0; i < fragmentUniformCount; i++)
420 {
421 fragmentShader << " gl_FragColor += v" << i << ";\n";
422 }
423
424 for (int i = 0; i < fragmentSamplersCount; i++)
425 {
426 fragmentShader << " gl_FragColor += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
427 }
428
429 if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
430 {
431 fragmentShader << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
432 }
433
434 fragmentShader << "}\n";
435
436 GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
437
438 if (expectSuccess)
439 {
440 EXPECT_NE(0u, program);
441 }
442 else
443 {
444 EXPECT_EQ(0u, program);
445 }
446 }
447
QueryErrorMessage(GLuint program)448 std::string QueryErrorMessage(GLuint program)
449 {
450 GLint infoLogLength;
451 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
452 EXPECT_GL_NO_ERROR();
453
454 if (infoLogLength >= 1)
455 {
456 std::vector<GLchar> infoLog(infoLogLength);
457 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
458 infoLog.data());
459 EXPECT_GL_NO_ERROR();
460 return infoLog.data();
461 }
462
463 return "";
464 }
465
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)466 void validateComponentsInErrorMessage(const char *vertexShader,
467 const char *fragmentShader,
468 const char *expectedErrorType,
469 const char *expectedVariableFullName)
470 {
471 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
472 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
473
474 GLuint program = glCreateProgram();
475 glAttachShader(program, vs);
476 glAttachShader(program, fs);
477 glLinkProgram(program);
478
479 glDetachShader(program, vs);
480 glDetachShader(program, fs);
481 glDeleteShader(vs);
482 glDeleteShader(fs);
483
484 const std::string errorMessage = QueryErrorMessage(program);
485 printf("%s\n", errorMessage.c_str());
486
487 EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
488 EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
489
490 glDeleteProgram(program);
491 ASSERT_GL_NO_ERROR();
492 }
493
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)494 void verifyAttachment2DColor(unsigned int index,
495 GLuint textureName,
496 GLenum target,
497 GLint level,
498 GLColor color)
499 {
500 glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
501 ASSERT_GL_NO_ERROR();
502
503 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
504 << "index " << index;
505 }
506
ExpectedExtensionMacros(std::vector<std::string> expected)507 std::string ExpectedExtensionMacros(std::vector<std::string> expected)
508 {
509 std::string shader;
510 for (const auto &ext : expected)
511 {
512 if (IsGLExtensionEnabled(ext))
513 {
514 shader += "\n#ifndef " + ext + "\n#error !defined(" + ext + ")\n#endif\n";
515 }
516 }
517 return shader;
518 }
519
UnexpectedExtensionMacros(std::vector<std::string> unexpected)520 std::string UnexpectedExtensionMacros(std::vector<std::string> unexpected)
521 {
522 std::string shader;
523 for (const auto &ext : unexpected)
524 {
525 shader += "\n#ifdef " + ext + "\n#error defined(" + ext + ")\n#endif\n";
526 }
527 return shader;
528 }
529 };
530
531 class GLSLTestNoValidation : public GLSLTest
532 {
533 public:
GLSLTestNoValidation()534 GLSLTestNoValidation() { setNoErrorEnabled(true); }
535 };
536
537 class GLSLTest_ES3 : public GLSLTest
538 {};
539
540 class GLSLTest_ES31 : public GLSLTest
541 {
542 protected:
543 void testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension);
544 void testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension);
545 };
546
547 // Tests the "init output variables" ANGLE shader translator option.
548 class GLSLTest_ES3_InitShaderVariables : public GLSLTest
549 {};
550 class GLSLTest_ES31_InitShaderVariables : public GLSLTest
551 {};
552
BuildBigInitialStackShader(int length)553 std::string BuildBigInitialStackShader(int length)
554 {
555 std::string result;
556 result += "void main() { \n";
557 for (int i = 0; i < length; i++)
558 {
559 result += " if (true) { \n";
560 }
561 result += " int temp; \n";
562 for (int i = 0; i <= length; i++)
563 {
564 result += "} \n";
565 }
566 return result;
567 }
568
569 // Tests a shader from conformance.olges/GL/build/build_017_to_024
570 // This shader uses chained assign-equals ops with swizzle, often reusing the same variable
571 // as part of a swizzle.
TEST_P(GLSLTest,SwizzledChainedAssignIncrement)572 TEST_P(GLSLTest, SwizzledChainedAssignIncrement)
573 {
574 constexpr char kFS[] =
575 R"(
576 precision mediump float;
577 void main() {
578 vec2 v = vec2(1,5);
579 // at the end of next statement, values in
580 // v.x = 12, v.y = 12
581 v.xy += v.yx += v.xy;
582 // v1 and v2, both are initialized with (12,12)
583 vec2 v1 = v, v2 = v;
584 v1.xy += v2.yx += ++(v.xy); // v1 = 37, v2 = 25 each
585 v1.xy += v2.yx += (v.xy)++; // v1 = 75, v2 = 38 each
586 gl_FragColor = vec4(v1,v2)/255.; // 75, 75, 38, 38
587 })";
588
589 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
590 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
591 ASSERT_GL_NO_ERROR();
592 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(75, 75, 38, 38));
593 }
594
TEST_P(GLSLTest,NamelessScopedStructs)595 TEST_P(GLSLTest, NamelessScopedStructs)
596 {
597 constexpr char kFS[] = R"(precision mediump float;
598 void main()
599 {
600 struct
601 {
602 float q;
603 } b;
604
605 gl_FragColor = vec4(1, 0, 0, 1);
606 gl_FragColor.a += b.q;
607 })";
608
609 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
610 }
611
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)612 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
613 {
614 constexpr char kFS[] = R"(#version 300 es
615 precision mediump float;
616 out vec4 fragColor;
617 uniform vec3 a[3];
618 uniform vec3 b[3];
619 void main() {
620 bool same = a == b;
621 fragColor = vec4(0);
622 if (same) {
623 fragColor = vec4(1);
624 }
625 }
626 )";
627
628 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
629 glUseProgram(program);
630
631 GLint aLocation = glGetUniformLocation(program, "a");
632 GLint bLocation = glGetUniformLocation(program, "b");
633 EXPECT_NE(aLocation, -1);
634 EXPECT_NE(bLocation, -1);
635
636 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
638
639 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
640 glUniform3fv(bLocation, 9, almostZeros);
641
642 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
643 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
644
645 glUniform3fv(aLocation, 9, almostZeros);
646 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
647 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
648
649 ASSERT_GL_NO_ERROR();
650 }
651
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)652 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
653 {
654 constexpr char kFS[] = R"(#version 300 es
655 precision mediump float;
656 out vec4 fragColor;
657 uniform mat3 a[3];
658 uniform mat3 b[3];
659 void main() {
660 bool same = a == b;
661 fragColor = vec4(0);
662 if (same) {
663 fragColor = vec4(1);
664 }
665 }
666 )";
667
668 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
669 glUseProgram(program);
670
671 GLint aLocation = glGetUniformLocation(program, "a");
672 GLint bLocation = glGetUniformLocation(program, "b");
673 EXPECT_NE(aLocation, -1);
674 EXPECT_NE(bLocation, -1);
675
676 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
678
679 static float almostZeros[] = {
680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
681 };
682 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
683
684 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
685 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
686
687 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
688 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
689 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
690
691 ASSERT_GL_NO_ERROR();
692 }
693
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)694 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
695 {
696 constexpr char kFS[] = R"(#version 300 es
697 precision mediump float;
698 out vec4 fragColor;
699 uniform float a[3];
700 uniform float b[3];
701 void main() {
702 bool same = a == b;
703 fragColor = vec4(0);
704 if (same) {
705 fragColor = vec4(1);
706 }
707 }
708 )";
709
710 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
711 glUseProgram(program);
712
713 GLint aLocation = glGetUniformLocation(program, "a");
714 GLint bLocation = glGetUniformLocation(program, "b");
715 EXPECT_NE(aLocation, -1);
716 EXPECT_NE(bLocation, -1);
717
718 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
719 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
720
721 static float almostZeros[] = {
722 0,
723 0,
724 1,
725 };
726 glUniform1fv(bLocation, 3, almostZeros);
727
728 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
730
731 glUniform1fv(aLocation, 3, almostZeros);
732 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
733 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
734
735 ASSERT_GL_NO_ERROR();
736 }
737
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)738 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
739 {
740 constexpr char kFS[] = R"(#version 300 es
741 precision mediump float;
742 out vec4 fragColor;
743 uniform vec3 a[3];
744 uniform vec3 b[3];
745 void main() {
746 bool notSame = a != b;
747 fragColor = vec4(0);
748 if (notSame) {
749 fragColor = vec4(1);
750 }
751 }
752 )";
753
754 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
755 glUseProgram(program);
756
757 GLint aLocation = glGetUniformLocation(program, "a");
758 GLint bLocation = glGetUniformLocation(program, "b");
759 EXPECT_NE(aLocation, -1);
760 EXPECT_NE(bLocation, -1);
761
762 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
763 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
764
765 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
766 glUniform3fv(bLocation, 9, almostZeros);
767
768 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
769 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
770
771 glUniform3fv(aLocation, 9, almostZeros);
772 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
773 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
774
775 ASSERT_GL_NO_ERROR();
776 }
777
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)778 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
779 {
780 constexpr char kFS[] = R"(#version 300 es
781 precision mediump float;
782 out vec4 fragColor;
783 uniform mat3 a[3];
784 uniform mat3 b[3];
785 void main() {
786 bool notSame = a != b;
787 fragColor = vec4(0);
788 if (notSame) {
789 fragColor = vec4(1);
790 }
791 }
792 )";
793
794 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
795 glUseProgram(program);
796
797 GLint aLocation = glGetUniformLocation(program, "a");
798 GLint bLocation = glGetUniformLocation(program, "b");
799 EXPECT_NE(aLocation, -1);
800 EXPECT_NE(bLocation, -1);
801
802 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
803 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
804
805 static float almostZeros[] = {
806 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
807 };
808 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
809
810 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
811 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
812
813 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
814 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
815 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
816
817 ASSERT_GL_NO_ERROR();
818 }
819
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)820 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
821 {
822 constexpr char kFS[] = R"(#version 300 es
823 precision mediump float;
824 out vec4 fragColor;
825 uniform float a[3];
826 uniform float b[3];
827 void main() {
828 bool notSame = a != b;
829 fragColor = vec4(0);
830 if (notSame) {
831 fragColor = vec4(1);
832 }
833 }
834 )";
835
836 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
837 glUseProgram(program);
838
839 GLint aLocation = glGetUniformLocation(program, "a");
840 GLint bLocation = glGetUniformLocation(program, "b");
841 EXPECT_NE(aLocation, -1);
842 EXPECT_NE(bLocation, -1);
843
844 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
845 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
846
847 static float almostZeros[] = {
848 0,
849 0,
850 1,
851 };
852 glUniform1fv(bLocation, 3, almostZeros);
853
854 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
855 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
856
857 glUniform1fv(aLocation, 3, almostZeros);
858 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
859 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
860
861 ASSERT_GL_NO_ERROR();
862 }
863
864 // Test that array of fragment shader outputs is processed properly and draws
865 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)866 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
867 {
868 GLuint fbo;
869 glGenFramebuffers(1, &fbo);
870 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
871
872 GLuint textures[4];
873 glGenTextures(4, textures);
874
875 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
876 {
877 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
878 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
879 GL_UNSIGNED_BYTE, nullptr);
880 }
881
882 GLint maxDrawBuffers;
883 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
884 ASSERT_GE(maxDrawBuffers, 4);
885
886 GLuint readFramebuffer;
887 glGenFramebuffers(1, &readFramebuffer);
888 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
889
890 constexpr char kFS[] = R"(#version 300 es
891 precision highp float;
892
893 out vec4 frag_color[4];
894
895 void main()
896 {
897 frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
898 frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
899 frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
900 frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
901 }
902 )";
903
904 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
905
906 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
907 GL_COLOR_ATTACHMENT3};
908
909 constexpr GLuint kMaxBuffers = 4;
910
911 // Enable all draw buffers.
912 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
913 {
914 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
915 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
916 textures[texIndex], 0);
917 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
918 textures[texIndex], 0);
919 }
920 glDrawBuffers(kMaxBuffers, allBufs);
921
922 // Draw with simple program.
923 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
924 ASSERT_GL_NO_ERROR();
925
926 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
927 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
928 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
929 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
930 }
931
932 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)933 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
934 {
935 constexpr char kFS[] = R"(#version 300 es
936 precision highp float;
937
938 // Make color0 inactive but specify color1 first. The Vulkan backend assigns bogus locations when
939 // compiling and fixes it up in SPIR-V. If color0's location is not fixed, it will return location
940 // 1 (aliasing color1). This will lead to a Vulkan validation warning about attachment 0 not being
941 // written to, which shouldn't be fatal.
942 layout(location = 1) out vec4 color1;
943 layout(location = 0) out vec4 color0;
944
945 void main()
946 {
947 color1 = vec4(0.0, 1.0, 0.0, 1.0);
948 }
949 )";
950
951 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
952
953 constexpr GLint kDrawBufferCount = 2;
954
955 GLint maxDrawBuffers;
956 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
957 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
958
959 GLTexture textures[kDrawBufferCount];
960
961 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
962 {
963 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
964 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
965 GL_UNSIGNED_BYTE, nullptr);
966 }
967
968 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
969
970 GLFramebuffer fbo;
971 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
972
973 // Enable all draw buffers.
974 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
975 {
976 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
977 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
978 textures[texIndex], 0);
979 }
980 glDrawBuffers(kDrawBufferCount, allBufs);
981
982 // Draw with simple program.
983 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
984 ASSERT_GL_NO_ERROR();
985 }
986
TEST_P(GLSLTest,ScopedStructsOrderBug)987 TEST_P(GLSLTest, ScopedStructsOrderBug)
988 {
989 constexpr char kFS[] = R"(precision mediump float;
990
991 struct T
992 {
993 float f;
994 };
995
996 void main()
997 {
998 T a;
999
1000 struct T
1001 {
1002 float q;
1003 };
1004
1005 T b;
1006
1007 gl_FragColor = vec4(1, 0, 0, 1);
1008 gl_FragColor.a += a.f;
1009 gl_FragColor.a += b.q;
1010 })";
1011
1012 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1013 }
1014
1015 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
1016 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)1017 TEST_P(GLSLTest, ScopedStructsOrderBug2)
1018 {
1019 constexpr char kFS[] = R"(precision mediump float;
1020
1021 uniform struct T
1022 {
1023 float f;
1024 } x;
1025
1026 void main()
1027 {
1028 T a;
1029
1030 struct T
1031 {
1032 float q;
1033 };
1034
1035 T b;
1036
1037 gl_FragColor = vec4(1, 0, 0, 1);
1038 gl_FragColor.a += a.f;
1039 gl_FragColor.a += b.q;
1040 })";
1041
1042 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1043 }
1044
1045 // Test that inactive uniforms of struct type don't cause any errors.
TEST_P(GLSLTest,InactiveStructUniform)1046 TEST_P(GLSLTest, InactiveStructUniform)
1047 {
1048 constexpr char kVS[] = R"(
1049 uniform struct
1050 {
1051 vec4 c;
1052 } s;
1053 void main()
1054 {
1055 })";
1056
1057 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
1058 }
1059
1060 // Test that struct with same name can be declared in inner scope.
TEST_P(GLSLTest,SameNameStructInInnerScope)1061 TEST_P(GLSLTest, SameNameStructInInnerScope)
1062 {
1063 constexpr char kVS[] = R"(
1064 void main() {
1065 gl_Position = vec4(0);
1066 })";
1067
1068 constexpr char kFS[] = R"(
1069 struct S
1070 {
1071 mediump float f;
1072 };
1073 void main()
1074 {
1075 struct S
1076 {
1077 S n;
1078 };
1079 })";
1080
1081 ANGLE_GL_PROGRAM(program, kVS, kFS);
1082 }
1083
1084 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)1085 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
1086 {
1087 constexpr char kVS[] = R"(
1088 struct S {
1089 float member;
1090 }, a;
1091 void main() {
1092 a.member = 0.0;
1093 gl_Position = vec4(a.member);
1094 })";
1095
1096 constexpr char kFS[] = R"(precision mediump float;
1097 void main()
1098 {
1099 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1100 })";
1101
1102 ANGLE_GL_PROGRAM(program, kVS, kFS);
1103 }
1104
1105 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1106 TEST_P(GLSLTest, StructConstantFoldingBug)
1107 {
1108 constexpr char kVS[] = R"(
1109 void main()
1110 {
1111
1112 const struct s2 {
1113 int i;
1114 vec3 v3;
1115 bvec4 bv4;
1116 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1117
1118 struct s4 {
1119 int ii;
1120 vec4 v4;
1121 };
1122
1123 const struct s1 {
1124 s2 ss;
1125 int i;
1126 float f;
1127 mat4 m;
1128 s4 s44;
1129 } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1130
1131 const int field3 = s11.i * s11.ss.i; // constant folding (int * int)
1132 const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1133 // 49, 64, 81, 100
1134 const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]); // 10.0, 5.0, 16.0, 81.0
1135 gl_Position = v4;
1136 })";
1137
1138 constexpr char kFS[] = R"(precision mediump float;
1139 precision mediump float;
1140 void main()
1141 {
1142 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1143 })";
1144
1145 ANGLE_GL_PROGRAM(program, kVS, kFS);
1146 }
1147
1148 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1149 TEST_P(GLSLTest, StructConstantFoldingBug2)
1150 {
1151 constexpr char kVS[] = R"(
1152 uniform vec4 u;
1153
1154 void main()
1155 {
1156
1157 const struct s2 {
1158 int i;
1159 vec3 v3;
1160 bvec4 bv4;
1161 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1162
1163 s2 x;
1164 x.v3 = u.xyz;
1165
1166 gl_Position = vec4(x.v3, float(s22.i));
1167 })";
1168
1169 constexpr char kFS[] = R"(precision mediump float;
1170 precision mediump float;
1171 void main()
1172 {
1173 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1174 })";
1175
1176 ANGLE_GL_PROGRAM(program, kVS, kFS);
1177 }
1178
TEST_P(GLSLTest,ScopedStructsBug)1179 TEST_P(GLSLTest, ScopedStructsBug)
1180 {
1181 constexpr char kFS[] = R"(precision mediump float;
1182
1183 struct T_0
1184 {
1185 float f;
1186 };
1187
1188 void main()
1189 {
1190 gl_FragColor = vec4(1, 0, 0, 1);
1191
1192 struct T
1193 {
1194 vec2 v;
1195 };
1196
1197 T_0 a;
1198 T b;
1199
1200 gl_FragColor.a += a.f;
1201 gl_FragColor.a += b.v.x;
1202 })";
1203
1204 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1205 }
1206
TEST_P(GLSLTest,DxPositionBug)1207 TEST_P(GLSLTest, DxPositionBug)
1208 {
1209 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1210 varying float dx_Position;
1211 void main()
1212 {
1213 gl_Position = vec4(inputAttribute);
1214 dx_Position = 0.0;
1215 })";
1216
1217 constexpr char kFS[] = R"(precision mediump float;
1218
1219 varying float dx_Position;
1220
1221 void main()
1222 {
1223 gl_FragColor = vec4(dx_Position, 0, 0, 1);
1224 })";
1225
1226 ANGLE_GL_PROGRAM(program, kVS, kFS);
1227 }
1228
1229 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1230 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1231 {
1232 constexpr int kStartIndex = 0;
1233 constexpr int kArrayLength = 5;
1234 constexpr char kVS[] = R"(#version 300 es
1235 precision highp float;
1236 void main() {
1237 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1238 gl_PointSize = 3.0;
1239 })";
1240
1241 constexpr char kFS[] = R"(#version 300 es
1242 precision highp float;
1243 out vec4 outColor;
1244 void main() {
1245 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1246 })";
1247
1248 ANGLE_GL_PROGRAM(program, kVS, kFS);
1249
1250 glUseProgram(program);
1251 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1252
1253 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1254 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1255 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1256 {
1257 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1258 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1259 static_cast<int>(pointCenterY), GLColor::red);
1260 }
1261 }
1262
GetFirstIntPixelRedValue()1263 GLint GetFirstIntPixelRedValue()
1264 {
1265 GLint pixel[4];
1266 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1267 return pixel[0];
1268 }
1269
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1270 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1271 {
1272 constexpr char kVS[] = R"(#version 300 es
1273 flat out highp int vVertexID;
1274
1275 void main() {
1276 vVertexID = gl_VertexID;
1277 gl_PointSize = 1.0;
1278 gl_Position = vec4(0,0,0,1);
1279 })";
1280
1281 constexpr char kFS[] = R"(#version 300 es
1282 flat in highp int vVertexID;
1283 out highp int oVertexID;
1284 void main() {
1285 oVertexID = vVertexID;
1286 })";
1287
1288 ANGLE_GL_PROGRAM(program, kVS, kFS);
1289 glUseProgram(program);
1290 glViewport(0, 0, 1, 1);
1291
1292 GLTexture tex;
1293 glBindTexture(GL_TEXTURE_2D, tex);
1294 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1295 GLFramebuffer fb;
1296 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1297 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1298
1299 EXPECT_GL_NO_ERROR();
1300
1301 GLint clearData[4] = {42};
1302 glClearBufferiv(GL_COLOR, 0, clearData);
1303 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1304
1305 const int kIndexDataSize = 5;
1306 GLushort indexData[] = {1, 2, 5, 3, 10000};
1307 GLBuffer indexBuffer;
1308 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1309 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1310
1311 for (size_t first = 0; first < kIndexDataSize; ++first)
1312 {
1313 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1314 {
1315 glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1316 reinterpret_cast<const void *>(first * 2u));
1317 GLint expected = indexData[first + count - 1];
1318 GLint actual = GetFirstIntPixelRedValue();
1319 EXPECT_EQ(expected, actual);
1320 }
1321 }
1322 EXPECT_GL_NO_ERROR();
1323 }
1324
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1325 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1326 {
1327 constexpr char kVS[] = R"(#version 300 es
1328 flat out highp int vVertexID;
1329
1330 void main() {
1331 vVertexID = gl_VertexID;
1332 gl_PointSize = 1.0;
1333 gl_Position = vec4(0,0,0,1);
1334 })";
1335
1336 constexpr char kFS[] = R"(#version 300 es
1337 flat in highp int vVertexID;
1338 out highp int oVertexID;
1339 void main() {
1340 oVertexID = vVertexID;
1341 })";
1342
1343 ANGLE_GL_PROGRAM(program, kVS, kFS);
1344 glUseProgram(program);
1345 glViewport(0, 0, 1, 1);
1346
1347 GLTexture tex;
1348 glBindTexture(GL_TEXTURE_2D, tex);
1349 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1350 GLFramebuffer fb;
1351 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1352 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1353
1354 EXPECT_GL_NO_ERROR();
1355
1356 GLint clearData[4] = {42};
1357 glClearBufferiv(GL_COLOR, 0, clearData);
1358 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1359
1360 const int kIndexDataSize = 5;
1361 GLubyte indexData[] = {1, 2, 5, 3, 100};
1362 GLBuffer indexBuffer;
1363 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1364 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1365
1366 for (size_t first = 0; first < kIndexDataSize; ++first)
1367 {
1368 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1369 {
1370 glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1371 reinterpret_cast<const void *>(first));
1372 GLint expected = indexData[first + count - 1];
1373 GLint actual = GetFirstIntPixelRedValue();
1374 EXPECT_EQ(expected, actual);
1375 }
1376 }
1377 EXPECT_GL_NO_ERROR();
1378 }
1379
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1380 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1381 {
1382 glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1383
1384 GLint pixels[8];
1385 glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1386
1387 GLint expected = indices[first + 1];
1388 EXPECT_EQ(expected, pixels[0]);
1389 EXPECT_EQ(expected, pixels[4]);
1390 }
1391
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1392 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1393 {
1394 constexpr char kVS[] = R"(#version 300 es
1395 flat out highp int vVertexID;
1396 layout(location = 0) in vec4 position;
1397
1398 void main() {
1399 vVertexID = gl_VertexID;
1400 gl_Position = position;
1401 })";
1402
1403 constexpr char kFS[] = R"(#version 300 es
1404 flat in highp int vVertexID;
1405 out highp int oVertexID;
1406 void main() {
1407 oVertexID = vVertexID;
1408 })";
1409
1410 ANGLE_GL_PROGRAM(program, kVS, kFS);
1411 glUseProgram(program);
1412 glViewport(0, 0, 2, 1);
1413
1414 GLTexture tex;
1415 glBindTexture(GL_TEXTURE_2D, tex);
1416 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1417 GLFramebuffer fb;
1418 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1419 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1420
1421 EXPECT_GL_NO_ERROR();
1422
1423 struct LR
1424 {
1425 LR() : X0(-1.0f), X1(1.0f) {}
1426 float X0;
1427 float X1;
1428 };
1429 constexpr int kNumVertices = 100;
1430 LR vertData[kNumVertices];
1431 GLBuffer buf;
1432 glBindBuffer(GL_ARRAY_BUFFER, buf);
1433 glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1434 glEnableVertexAttribArray(0);
1435 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1436
1437 GLint clearData[4] = {42};
1438 glClearBufferiv(GL_COLOR, 0, clearData);
1439 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1440
1441 GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1442 GLBuffer indexBuffer;
1443 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1444 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1445
1446 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1447 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1448 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1449 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1450
1451 EXPECT_GL_NO_ERROR();
1452 }
1453
1454 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1455 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1456 {
1457 // Draws lines via indices (glDrawElements). Each pair of indices
1458 // draws the next consecutive pixel. For 2 points, because we're
1459 // using int attributes, they must be "flat" and so the spec
1460 // says for a given line the value should come from the second
1461 // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1462 // Each line is only 1 pixel long so every other pixel should
1463 // be the default value.
1464 constexpr char kVS[] = R"(#version 300 es
1465 flat out highp int vVertexID;
1466 layout(location = 0) in float position;
1467 uniform float width;
1468
1469 void main() {
1470 vVertexID = gl_VertexID;
1471 gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1472 })";
1473
1474 constexpr char kFS[] = R"(#version 300 es
1475 flat in highp int vVertexID;
1476 out highp int oVertexID;
1477 void main() {
1478 oVertexID = vVertexID;
1479 })";
1480
1481 GLubyte indexData[] = {1, 4, 5, 2, 50, 61, 32, 33};
1482 constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1483 GLBuffer indexBuffer;
1484 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1485 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1486
1487 ANGLE_GL_PROGRAM(program, kVS, kFS);
1488 glUseProgram(program);
1489 glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1490 glViewport(0, 0, kNumIndices, 1);
1491
1492 GLTexture tex;
1493 glBindTexture(GL_TEXTURE_2D, tex);
1494 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1495 GLFramebuffer fb;
1496 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1497 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1498
1499 constexpr int kNumVertices = 100;
1500 std::vector<float> vertData(kNumVertices, -1.0f);
1501 {
1502 int i = 0;
1503 for (GLubyte ndx : indexData)
1504 {
1505 vertData[ndx] = i++;
1506 }
1507 }
1508 GLBuffer buf;
1509 glBindBuffer(GL_ARRAY_BUFFER, buf);
1510 glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1511 glEnableVertexAttribArray(0);
1512 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1513
1514 GLint kDefaultValue = 42;
1515 GLint clearData[4] = {kDefaultValue};
1516 glClearBufferiv(GL_COLOR, 0, clearData);
1517 EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1518
1519 EXPECT_GL_NO_ERROR();
1520
1521 glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1522
1523 GLint pixels[kNumIndices * 4];
1524 glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1525
1526 for (size_t i = 0; i < kNumIndices; ++i)
1527 {
1528 const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1529 const int actual = pixels[i * 4];
1530 EXPECT_EQ(expected, actual);
1531 }
1532
1533 EXPECT_GL_NO_ERROR();
1534 }
1535
1536 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1537 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1538 {
1539 glDrawArrays(GL_POINTS, first, count);
1540
1541 int pixel[4];
1542 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1543 // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1544 // pixels.
1545 if (err == static_cast<GLenum>(GL_NO_ERROR))
1546 {
1547 EXPECT_GL_NO_ERROR();
1548 EXPECT_EQ(pixel[0], first + count - 1);
1549 }
1550 else
1551 {
1552 // If we call this function with err set, we will allow the error, but check the pixels if
1553 // the error hasn't occurred.
1554 GLenum glError = glGetError();
1555 if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1556 {
1557 EXPECT_EQ(pixel[0], first + count - 1);
1558 }
1559 }
1560 }
1561
1562 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1563 // is based off the WebGL test:
1564 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1565 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1566 {
1567 constexpr char kVS[] = R"(#version 300 es
1568 flat out highp int vVertexID;
1569 void main() {
1570 vVertexID = gl_VertexID;
1571 gl_Position = vec4(0,0,0,1);
1572 gl_PointSize = 1.0;
1573 })";
1574
1575 constexpr char kFS[] = R"(#version 300 es
1576 flat in highp int vVertexID;
1577 out highp int oVertexID;
1578 void main() {
1579 oVertexID = vVertexID;
1580 })";
1581
1582 ANGLE_GL_PROGRAM(program, kVS, kFS);
1583 glUseProgram(program);
1584 glViewport(0, 0, 1, 1);
1585
1586 GLTexture texture;
1587 glBindTexture(GL_TEXTURE_2D, texture);
1588 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1589 GLFramebuffer fbo;
1590 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1591 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1592 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1593 EXPECT_GL_NO_ERROR();
1594
1595 // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1596 GLint val[4] = {42};
1597 glClearBufferiv(GL_COLOR, 0, val);
1598 int pixel[4];
1599 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1600 EXPECT_EQ(pixel[0], val[0]);
1601
1602 GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1603 GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1604 GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1605 GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1606 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1607 GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1608 GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1609 GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1610 GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1611 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1612
1613 int32_t int32Max = 0x7FFFFFFF;
1614 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1615 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1616 }
1617
1618 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1619 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1620 {
1621 // Bug in Nexus drivers, offset does not work. (anglebug.com/42261941)
1622 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1623
1624 constexpr int kStartIndex = 5;
1625 constexpr int kArrayLength = 5;
1626 constexpr char kVS[] = R"(#version 300 es
1627 precision highp float;
1628 void main() {
1629 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1630 gl_PointSize = 3.0;
1631 })";
1632
1633 constexpr char kFS[] = R"(#version 300 es
1634 precision highp float;
1635 out vec4 outColor;
1636 void main() {
1637 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1638 })";
1639
1640 ANGLE_GL_PROGRAM(program, kVS, kFS);
1641
1642 glUseProgram(program);
1643 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1644
1645 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1646 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1647 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1648 {
1649 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1650 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1651 static_cast<int>(pointCenterY), GLColor::red);
1652 }
1653 }
1654
TEST_P(GLSLTest,ElseIfRewriting)1655 TEST_P(GLSLTest, ElseIfRewriting)
1656 {
1657 constexpr char kVS[] =
1658 "attribute vec4 a_position;\n"
1659 "varying float v;\n"
1660 "void main() {\n"
1661 " gl_Position = a_position;\n"
1662 " v = 1.0;\n"
1663 " if (a_position.x <= 0.5) {\n"
1664 " v = 0.0;\n"
1665 " } else if (a_position.x >= 0.5) {\n"
1666 " v = 2.0;\n"
1667 " }\n"
1668 "}\n";
1669
1670 constexpr char kFS[] =
1671 "precision highp float;\n"
1672 "varying float v;\n"
1673 "void main() {\n"
1674 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1675 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1676 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1677 " gl_FragColor = color;\n"
1678 "}\n";
1679
1680 ANGLE_GL_PROGRAM(program, kVS, kFS);
1681
1682 drawQuad(program, "a_position", 0.5f);
1683
1684 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1685 EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1686 }
1687
TEST_P(GLSLTest,TwoElseIfRewriting)1688 TEST_P(GLSLTest, TwoElseIfRewriting)
1689 {
1690 constexpr char kVS[] =
1691 "attribute vec4 a_position;\n"
1692 "varying float v;\n"
1693 "void main() {\n"
1694 " gl_Position = a_position;\n"
1695 " if (a_position.x == 0.0) {\n"
1696 " v = 1.0;\n"
1697 " } else if (a_position.x > 0.5) {\n"
1698 " v = 0.0;\n"
1699 " } else if (a_position.x > 0.75) {\n"
1700 " v = 0.5;\n"
1701 " }\n"
1702 "}\n";
1703
1704 constexpr char kFS[] =
1705 "precision highp float;\n"
1706 "varying float v;\n"
1707 "void main() {\n"
1708 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1709 "}\n";
1710
1711 ANGLE_GL_PROGRAM(program, kVS, kFS);
1712 }
1713
TEST_P(GLSLTest,FrontFacingAndVarying)1714 TEST_P(GLSLTest, FrontFacingAndVarying)
1715 {
1716 EGLPlatformParameters platform = GetParam().eglParameters;
1717
1718 constexpr char kVS[] = R"(attribute vec4 a_position;
1719 varying float v_varying;
1720 void main()
1721 {
1722 v_varying = a_position.x;
1723 gl_Position = a_position;
1724 })";
1725
1726 constexpr char kFS[] = R"(precision mediump float;
1727 varying float v_varying;
1728 void main()
1729 {
1730 vec4 c;
1731
1732 if (gl_FrontFacing)
1733 {
1734 c = vec4(v_varying, 0, 0, 1.0);
1735 }
1736 else
1737 {
1738 c = vec4(0, v_varying, 0, 1.0);
1739 }
1740 gl_FragColor = c;
1741 })";
1742
1743 GLuint program = CompileProgram(kVS, kFS);
1744
1745 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1746 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1747 {
1748 if (platform.majorVersion == 9 && platform.minorVersion == 3)
1749 {
1750 EXPECT_EQ(0u, program);
1751 return;
1752 }
1753 }
1754
1755 // Otherwise, compilation should succeed
1756 EXPECT_NE(0u, program);
1757 }
1758
1759 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1760 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1761 {
1762 // Draw with the first program.
1763 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1764 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1765 ASSERT_GL_NO_ERROR();
1766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1767
1768 // Clear and release shader compiler.
1769 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1770 glClear(GL_COLOR_BUFFER_BIT);
1771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1772 glReleaseShaderCompiler();
1773 ASSERT_GL_NO_ERROR();
1774
1775 // Draw with a second program.
1776 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1777 drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1778 ASSERT_GL_NO_ERROR();
1779 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1780 }
1781
1782 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1783 TEST_P(GLSLTest_ES3, VersionMismatch)
1784 {
1785 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1786 EXPECT_EQ(0u, program);
1787
1788 program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1789 EXPECT_EQ(0u, program);
1790 }
1791
1792 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1793 TEST_P(GLSLTest, InvariantVaryingOut)
1794 {
1795 constexpr char kFS[] =
1796 "precision mediump float;\n"
1797 "varying float v_varying;\n"
1798 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1799
1800 constexpr char kVS[] =
1801 "attribute vec4 a_position;\n"
1802 "invariant varying float v_varying;\n"
1803 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1804
1805 GLuint program = CompileProgram(kVS, kFS);
1806 EXPECT_EQ(0u, program);
1807 }
1808
1809 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1810 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1811 {
1812 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1813 // for varyings which are invariant in vertex shader (http://anglebug.com/40096344)
1814 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1815
1816 constexpr char kFS[] =
1817 "#version 300 es\n"
1818 "precision mediump float;\n"
1819 "in float v_varying;\n"
1820 "out vec4 my_FragColor;\n"
1821 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1822
1823 constexpr char kVS[] =
1824 "#version 300 es\n"
1825 "in vec4 a_position;\n"
1826 "invariant out float v_varying;\n"
1827 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1828
1829 GLuint program = CompileProgram(kVS, kFS);
1830 EXPECT_NE(0u, program);
1831 }
1832
1833 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1834 TEST_P(GLSLTest, InvariantVaryingIn)
1835 {
1836 constexpr char kFS[] =
1837 "precision mediump float;\n"
1838 "invariant varying float v_varying;\n"
1839 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1840
1841 constexpr char kVS[] =
1842 "attribute vec4 a_position;\n"
1843 "varying float v_varying;\n"
1844 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1845
1846 GLuint program = CompileProgram(kVS, kFS);
1847 EXPECT_EQ(0u, program);
1848 }
1849
1850 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1851 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1852 {
1853 constexpr char kFS[] =
1854 "#version 300 es\n"
1855 "precision mediump float;\n"
1856 "invariant in float v_varying;\n"
1857 "out vec4 my_FragColor;\n"
1858 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1859
1860 constexpr char kVS[] =
1861 "#version 300 es\n"
1862 "in vec4 a_position;\n"
1863 "out float v_varying;\n"
1864 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1865
1866 GLuint program = CompileProgram(kVS, kFS);
1867 EXPECT_EQ(0u, program);
1868 }
1869
1870 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1871 TEST_P(GLSLTest, InvariantVaryingBoth)
1872 {
1873 constexpr char kFS[] =
1874 "precision mediump float;\n"
1875 "invariant varying float v_varying;\n"
1876 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1877
1878 constexpr char kVS[] =
1879 "attribute vec4 a_position;\n"
1880 "invariant varying float v_varying;\n"
1881 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1882
1883 GLuint program = CompileProgram(kVS, kFS);
1884 EXPECT_NE(0u, program);
1885 }
1886
1887 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1888 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1889 {
1890 constexpr char kFS[] =
1891 "#version 300 es\n"
1892 "precision mediump float;\n"
1893 "invariant in float v_varying;\n"
1894 "out vec4 my_FragColor;\n"
1895 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1896
1897 constexpr char kVS[] =
1898 "#version 300 es\n"
1899 "in vec4 a_position;\n"
1900 "invariant out float v_varying;\n"
1901 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1902
1903 GLuint program = CompileProgram(kVS, kFS);
1904 EXPECT_EQ(0u, program);
1905 }
1906
1907 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1908 TEST_P(GLSLTest, InvariantGLPosition)
1909 {
1910 constexpr char kFS[] =
1911 "precision mediump float;\n"
1912 "varying float v_varying;\n"
1913 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1914
1915 constexpr char kVS[] =
1916 "attribute vec4 a_position;\n"
1917 "invariant gl_Position;\n"
1918 "varying float v_varying;\n"
1919 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1920
1921 GLuint program = CompileProgram(kVS, kFS);
1922 EXPECT_NE(0u, program);
1923 }
1924
1925 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1926 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1927 {
1928 constexpr char kFS[] =
1929 "#version 300 es\n"
1930 "precision mediump float;\n"
1931 "in float v_varying;\n"
1932 "out vec4 my_FragColor;\n"
1933 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1934
1935 constexpr char kVS[] =
1936 "#version 300 es\n"
1937 "in vec4 a_position;\n"
1938 "invariant gl_Position;\n"
1939 "out float v_varying;\n"
1940 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1941
1942 GLuint program = CompileProgram(kVS, kFS);
1943 EXPECT_NE(0u, program);
1944 }
1945
1946 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1947 TEST_P(GLSLTest, InvariantAllBoth)
1948 {
1949 constexpr char kFS[] =
1950 "#pragma STDGL invariant(all)\n"
1951 "precision mediump float;\n"
1952 "varying float v_varying;\n"
1953 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1954
1955 constexpr char kVS[] =
1956 "#pragma STDGL invariant(all)\n"
1957 "attribute vec4 a_position;\n"
1958 "varying float v_varying;\n"
1959 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1960
1961 GLuint program = CompileProgram(kVS, kFS);
1962 EXPECT_EQ(0u, program);
1963 }
1964
1965 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1966 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1967 {
1968 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1969
1970 constexpr char kVS[] = R"(#version 310 es
1971 #extension GL_EXT_shader_io_blocks : require
1972
1973 struct S
1974 {
1975 vec4 s;
1976 };
1977
1978 out Output
1979 {
1980 vec4 x;
1981 invariant S s;
1982 };
1983
1984 out S s2;
1985
1986 void main(){
1987 x = vec4(0);
1988 s.s = vec4(1);
1989 s2.s = vec4(2);
1990 S s3 = s;
1991 s.s = s3.s;
1992 })";
1993
1994 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1995 EXPECT_NE(0u, shader);
1996 glDeleteShader(shader);
1997 }
1998
1999 // Verify that using maximum size as atomic counter offset results in compilation failure.
TEST_P(GLSLTest_ES31,CompileWithMaxAtomicCounterOffsetFails)2000 TEST_P(GLSLTest_ES31, CompileWithMaxAtomicCounterOffsetFails)
2001 {
2002 GLint maxSize;
2003 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &maxSize);
2004
2005 std::ostringstream srcStream;
2006 srcStream << "#version 310 es\n"
2007 << "layout(location = 0) out uvec4 color;\n"
2008 << "layout(binding = 0, offset = " << maxSize << ") uniform atomic_uint a_counter;\n"
2009 << "void main() {\n"
2010 << "color = uvec4(atomicCounterIncrement(a_counter)); \n"
2011 << "}";
2012 std::string fsStream = srcStream.str();
2013 const char *strFS = fsStream.c_str();
2014
2015 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, strFS);
2016 EXPECT_EQ(0u, shader);
2017 }
2018
2019 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)2020 TEST_P(GLSLTest, MissingReturnFloat)
2021 {
2022 constexpr char kVS[] =
2023 "varying float v_varying;\n"
2024 "float f() { if (v_varying > 0.0) return 1.0; }\n"
2025 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
2026
2027 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2028 EXPECT_NE(0u, program);
2029 }
2030
2031 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)2032 TEST_P(GLSLTest, MissingReturnVec2)
2033 {
2034 constexpr char kVS[] =
2035 "varying float v_varying;\n"
2036 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
2037 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2038
2039 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2040 EXPECT_NE(0u, program);
2041 }
2042
2043 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)2044 TEST_P(GLSLTest, MissingReturnVec3)
2045 {
2046 constexpr char kVS[] =
2047 "varying float v_varying;\n"
2048 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
2049 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2050
2051 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2052 EXPECT_NE(0u, program);
2053 }
2054
2055 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)2056 TEST_P(GLSLTest, MissingReturnVec4)
2057 {
2058 constexpr char kVS[] =
2059 "varying float v_varying;\n"
2060 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
2061 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2062
2063 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2064 EXPECT_NE(0u, program);
2065 }
2066
2067 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)2068 TEST_P(GLSLTest, MissingReturnIVec4)
2069 {
2070 constexpr char kVS[] =
2071 "varying float v_varying;\n"
2072 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
2073 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2074
2075 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2076 EXPECT_NE(0u, program);
2077 }
2078
2079 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)2080 TEST_P(GLSLTest, MissingReturnMat4)
2081 {
2082 constexpr char kVS[] =
2083 "varying float v_varying;\n"
2084 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
2085 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
2086
2087 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2088 EXPECT_NE(0u, program);
2089 }
2090
2091 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)2092 TEST_P(GLSLTest, MissingReturnStruct)
2093 {
2094 constexpr char kVS[] =
2095 "varying float v_varying;\n"
2096 "struct s { float a; int b; vec2 c; };\n"
2097 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
2098 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
2099
2100 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2101 EXPECT_NE(0u, program);
2102 }
2103
2104 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)2105 TEST_P(GLSLTest_ES3, MissingReturnArray)
2106 {
2107 constexpr char kVS[] =
2108 "#version 300 es\n"
2109 "in float v_varying;\n"
2110 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2111 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2112
2113 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2114 EXPECT_NE(0u, program);
2115 }
2116
2117 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2118 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2119 {
2120 constexpr char kVS[] =
2121 "#version 300 es\n"
2122 "in float v_varying;\n"
2123 "struct s { float a; int b; vec2 c; };\n"
2124 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2125 "vec2(1.0, 1.0))); } }\n"
2126 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2127
2128 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2129 EXPECT_NE(0u, program);
2130 }
2131
2132 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2133 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2134 {
2135 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2136 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2137
2138 constexpr char kVS[] =
2139 "#version 300 es\n"
2140 "in float v_varying;\n"
2141 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2142 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2143 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2144 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2145
2146 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2147 EXPECT_NE(0u, program);
2148 }
2149
2150 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2151 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2152 {
2153 constexpr char kVS[] = R"(#version 300 es
2154 in float v_varying;
2155 struct s { float a; int b; vec2 c; };
2156 s[2] f()
2157 {
2158 return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2159 }
2160 void main()
2161 {
2162 gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2163 })";
2164
2165 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2166 EXPECT_NE(0u, program);
2167 }
2168
2169 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2170 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2171 {
2172 constexpr char kFS[] =
2173 "#version 300 es\n"
2174 "#pragma STDGL invariant(all)\n"
2175 "precision mediump float;\n"
2176 "in float v_varying;\n"
2177 "out vec4 my_FragColor;\n"
2178 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2179
2180 constexpr char kVS[] =
2181 "#version 300 es\n"
2182 "#pragma STDGL invariant(all)\n"
2183 "in vec4 a_position;\n"
2184 "out float v_varying;\n"
2185 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2186
2187 GLuint program = CompileProgram(kVS, kFS);
2188 EXPECT_EQ(0u, program);
2189 }
2190
2191 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2192 TEST_P(GLSLTest, InvariantAllIn)
2193 {
2194 constexpr char kFS[] =
2195 "#pragma STDGL invariant(all)\n"
2196 "precision mediump float;\n"
2197 "varying float v_varying;\n"
2198 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2199
2200 constexpr char kVS[] =
2201 "attribute vec4 a_position;\n"
2202 "varying float v_varying;\n"
2203 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2204
2205 GLuint program = CompileProgram(kVS, kFS);
2206 EXPECT_NE(0u, program);
2207 }
2208
2209 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2210 TEST_P(GLSLTest_ES3, InvariantAllIn)
2211 {
2212 constexpr char kFS[] =
2213 "#version 300 es\n"
2214 "#pragma STDGL invariant(all)\n"
2215 "precision mediump float;\n"
2216 "in float v_varying;\n"
2217 "out vec4 my_FragColor;\n"
2218 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2219
2220 constexpr char kVS[] =
2221 "#version 300 es\n"
2222 "in vec4 a_position;\n"
2223 "out float v_varying;\n"
2224 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2225
2226 GLuint program = CompileProgram(kVS, kFS);
2227 EXPECT_EQ(0u, program);
2228 }
2229
2230 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2231 TEST_P(GLSLTest, InvariantAllOut)
2232 {
2233 constexpr char kFS[] =
2234 "precision mediump float;\n"
2235 "varying float v_varying;\n"
2236 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2237
2238 constexpr char kVS[] =
2239 "#pragma STDGL invariant(all)\n"
2240 "attribute vec4 a_position;\n"
2241 "varying float v_varying;\n"
2242 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2243
2244 GLuint program = CompileProgram(kVS, kFS);
2245 EXPECT_EQ(0u, program);
2246 }
2247
2248 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2249 TEST_P(GLSLTest_ES3, InvariantAllOut)
2250 {
2251 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2252 // for varyings which are invariant in vertex shader,
2253 // because of invariant(all) being used in vertex shader (http://anglebug.com/40096344)
2254 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2255
2256 constexpr char kFS[] =
2257 "#version 300 es\n"
2258 "precision mediump float;\n"
2259 "in float v_varying;\n"
2260 "out vec4 my_FragColor;\n"
2261 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2262
2263 constexpr char kVS[] =
2264 "#version 300 es\n"
2265 "#pragma STDGL invariant(all)\n"
2266 "in vec4 a_position;\n"
2267 "out float v_varying;\n"
2268 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2269
2270 GLuint program = CompileProgram(kVS, kFS);
2271 EXPECT_NE(0u, program);
2272 }
2273
TEST_P(GLSLTest,MaxVaryingVec4)2274 TEST_P(GLSLTest, MaxVaryingVec4)
2275 {
2276 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2277 // (http://anglebug.com/42260302)
2278 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2279
2280 GLint maxVaryings = 0;
2281 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2282
2283 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2284 }
2285
2286 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2287 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2288 {
2289 GLint maxVaryings = 0;
2290 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2291
2292 // Generate shader code that uses gl_FragCoord.
2293 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2294 }
2295
2296 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2297 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2298 {
2299 GLint maxVaryings = 0;
2300 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2301
2302 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2303 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2304 }
2305
2306 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2307 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2308 {
2309 GLint maxVaryings = 0;
2310 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2311
2312 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2313 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2314 }
2315
2316 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2317 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2318 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2319 {
2320 ANGLE_SKIP_TEST_IF(!IsD3D9());
2321
2322 GLint maxVaryings = 0;
2323 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2324
2325 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2326 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2327 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2328
2329 // Special case for gl_PointSize: we get it for free on D3D9.
2330 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2331 }
2332
2333 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2334 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2335 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2336 {
2337 GLint maxVaryings = 0;
2338 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2339
2340 // Generate shader code that uses gl_FragCoord.
2341 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2342 }
2343
TEST_P(GLSLTest,MaxVaryingVec3)2344 TEST_P(GLSLTest, MaxVaryingVec3)
2345 {
2346 GLint maxVaryings = 0;
2347 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2348
2349 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2350 }
2351
TEST_P(GLSLTest,MaxVaryingVec3Array)2352 TEST_P(GLSLTest, MaxVaryingVec3Array)
2353 {
2354 GLint maxVaryings = 0;
2355 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2356
2357 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2358 }
2359
2360 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2361 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2362 {
2363 GLint maxVaryings = 0;
2364 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2365
2366 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2367 }
2368
2369 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2370 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2371 {
2372 GLint maxVaryings = 0;
2373 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2374
2375 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2376 }
2377
2378 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2379 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2380 {
2381 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2382 // (http://anglebug.com/42262492)
2383 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2384
2385 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2386 // (http://anglebug.com/42260302)
2387 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2388
2389 GLint maxVaryings = 0;
2390 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2391
2392 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2393 }
2394
2395 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2396 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2397 {
2398 ANGLE_SKIP_TEST_IF(IsD3D9());
2399
2400 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2401 ANGLE_SKIP_TEST_IF(IsOpenGLES());
2402
2403 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2404 // (http://anglebug.com/42260302)
2405 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2406
2407 GLint maxVaryings = 0;
2408 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2409
2410 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2411 // we should be aware that when we're packing into an odd number of varying registers the
2412 // last row will be empty and can not fit the final vec2 arrary.
2413 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2414
2415 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2416 }
2417
2418 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2419 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2420 {
2421 // (http://anglebug.com/42263058)
2422 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2423
2424 // http://anglebug.com/42263066
2425 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
2426
2427 GLint maxVaryings = 0;
2428 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2429
2430 std::stringstream vertexShaderSource;
2431 std::stringstream fragmentShaderSource;
2432
2433 // substract 1 here for gl_PointSize
2434 const GLint vec4Count = maxVaryings - 1;
2435 unsigned int varyingCount = 0;
2436 std::string varyingDeclaration;
2437 for (GLint i = 0; i < vec4Count; i++)
2438 {
2439 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2440 varyingCount += 1;
2441 }
2442 // Generate the vertex shader
2443 vertexShaderSource.clear();
2444 vertexShaderSource << varyingDeclaration;
2445 vertexShaderSource << "\nattribute vec4 a_position;\n";
2446 vertexShaderSource << "\nvoid main()\n{\n";
2447 unsigned int currentVSVarying = 0;
2448 for (GLint i = 0; i < vec4Count; i++)
2449 {
2450 vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2451 currentVSVarying += 1;
2452 }
2453 vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2454 vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2455 vertexShaderSource << "}\n";
2456
2457 // Generate the fragment shader
2458 fragmentShaderSource.clear();
2459 fragmentShaderSource << "precision highp float;\n";
2460 fragmentShaderSource << varyingDeclaration;
2461 fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2462 unsigned int currentFSVarying = 0;
2463 // Make use of the vec4 varyings
2464 fragmentShaderSource << "\tretColor += ";
2465 for (GLint i = 0; i < vec4Count; i++)
2466 {
2467 fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2468 currentFSVarying += 1;
2469 }
2470 fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2471 constexpr GLuint testValue = 234;
2472 fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2473 << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2474 fragmentShaderSource << "}\n";
2475
2476 std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2477 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2478 fragmentShaderSource.str().c_str(), tfVaryings,
2479 GL_INTERLEAVED_ATTRIBS);
2480
2481 GLBuffer xfbBuffer;
2482 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2483 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2484 GL_STATIC_DRAW);
2485
2486 GLTransformFeedback xfb;
2487 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2488 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2489
2490 glUseProgram(program1);
2491
2492 const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2493 GLBuffer vertexBuffer;
2494 // need to shift half pixel to make sure the line covers the center of the pixel
2495 const Vector3 vertices[2] = {
2496 {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2497 {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2498 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2499 glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2500 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2501 glEnableVertexAttribArray(positionLocation);
2502
2503 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2504 glClear(GL_COLOR_BUFFER_BIT);
2505
2506 glBeginTransformFeedback(GL_LINES);
2507 glDrawArrays(GL_LINES, 0, 2);
2508 glEndTransformFeedback();
2509
2510 ASSERT_GL_NO_ERROR();
2511
2512 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2513 }
2514
2515 // Verify shader source with a fixed length that is less than the null-terminated length will
2516 // compile.
TEST_P(GLSLTest,FixedShaderLength)2517 TEST_P(GLSLTest, FixedShaderLength)
2518 {
2519 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2520
2521 const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2522 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2523 const char *sourceArray[1] = {source.c_str()};
2524 GLint lengths[1] = {static_cast<GLint>(source.length() - appendGarbage.length())};
2525 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2526 glCompileShader(shader);
2527
2528 GLint compileResult;
2529 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2530 EXPECT_NE(compileResult, 0);
2531 }
2532
2533 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2534 TEST_P(GLSLTest, NegativeShaderLength)
2535 {
2536 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2537
2538 const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2539 GLint lengths[1] = {-10};
2540 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2541 glCompileShader(shader);
2542
2543 GLint compileResult;
2544 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2545 EXPECT_NE(compileResult, 0);
2546 }
2547
2548 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2549 TEST_P(GLSLTest, InvalidFieldFirstChar)
2550 {
2551 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
2552 const char *source = "void main() {vec4 x; x.}";
2553 glShaderSource(shader, 1, &source, 0);
2554 glCompileShader(shader);
2555
2556 GLint compileResult;
2557 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2558 EXPECT_EQ(0, compileResult);
2559 }
2560
2561 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2562 TEST_P(GLSLTest, MixedShaderLengths)
2563 {
2564 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2565
2566 const char *sourceArray[] = {
2567 "void main()",
2568 "{",
2569 " gl_FragColor = vec4(0, 0, 0, 0);",
2570 "}",
2571 };
2572 GLint lengths[] = {
2573 -10,
2574 1,
2575 static_cast<GLint>(strlen(sourceArray[2])),
2576 -1,
2577 };
2578 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2579
2580 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2581 glCompileShader(shader);
2582
2583 GLint compileResult;
2584 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2585 EXPECT_NE(compileResult, 0);
2586 }
2587
2588 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2589 TEST_P(GLSLTest, ZeroShaderLength)
2590 {
2591 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2592
2593 const char *sourceArray[] = {
2594 "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2595 };
2596 GLint lengths[] = {
2597 0, 0, -1, 0, 0,
2598 };
2599 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2600
2601 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2602 glCompileShader(shader);
2603
2604 GLint compileResult;
2605 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2606 EXPECT_NE(compileResult, 0);
2607 }
2608
2609 // Tests that bad index expressions don't crash ANGLE's translator.
2610 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2611 TEST_P(GLSLTest, BadIndexBug)
2612 {
2613 constexpr char kFSSourceVec[] =
2614 "precision mediump float;\n"
2615 "uniform vec4 uniformVec;\n"
2616 "void main()\n"
2617 "{\n"
2618 " gl_FragColor = vec4(uniformVec[int()]);\n"
2619 "}";
2620
2621 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2622 EXPECT_EQ(0u, shader);
2623
2624 if (shader != 0)
2625 {
2626 glDeleteShader(shader);
2627 }
2628
2629 constexpr char kFSSourceMat[] =
2630 "precision mediump float;\n"
2631 "uniform mat4 uniformMat;\n"
2632 "void main()\n"
2633 "{\n"
2634 " gl_FragColor = vec4(uniformMat[int()]);\n"
2635 "}";
2636
2637 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2638 EXPECT_EQ(0u, shader);
2639
2640 if (shader != 0)
2641 {
2642 glDeleteShader(shader);
2643 }
2644
2645 constexpr char kFSSourceArray[] =
2646 "precision mediump float;\n"
2647 "uniform vec4 uniformArray;\n"
2648 "void main()\n"
2649 "{\n"
2650 " gl_FragColor = vec4(uniformArray[int()]);\n"
2651 "}";
2652
2653 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2654 EXPECT_EQ(0u, shader);
2655
2656 if (shader != 0)
2657 {
2658 glDeleteShader(shader);
2659 }
2660 }
2661
2662 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2663 TEST_P(GLSLTest, StructSpecifiersUniforms)
2664 {
2665 constexpr char kFS[] = R"(precision mediump float;
2666
2667 uniform struct S { float field; } s;
2668
2669 void main()
2670 {
2671 gl_FragColor = vec4(1, 0, 0, 1);
2672 gl_FragColor.a += s.field;
2673 })";
2674
2675 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2676 EXPECT_NE(0u, program);
2677 }
2678
2679 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2680 TEST_P(GLSLTest, StructWithInitializer)
2681 {
2682 constexpr char kFS[] = R"(precision mediump float;
2683
2684 struct S { float a; } s = S(1.0);
2685
2686 void main()
2687 {
2688 gl_FragColor = vec4(0, 0, 0, 1);
2689 gl_FragColor.r += s.a;
2690 })";
2691
2692 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2693 glUseProgram(program);
2694
2695 // Test drawing, should be red.
2696 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2697
2698 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2699 EXPECT_GL_NO_ERROR();
2700 }
2701
2702 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2703 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2704 {
2705 constexpr char kFS[] = R"(precision mediump float;
2706
2707 struct S { float a; };
2708 uniform S u_s;
2709
2710 void main()
2711 {
2712 gl_FragColor = vec4(u_s.a);
2713 })";
2714
2715 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2716 glUseProgram(program);
2717
2718 // Test drawing, should be red.
2719 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2720
2721 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2722 EXPECT_GL_NO_ERROR();
2723 }
2724
2725 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2726 TEST_P(GLSLTest, StructWithUniformInitializer)
2727 {
2728 constexpr char kFS[] = R"(precision mediump float;
2729
2730 struct S { float a; } s = S(1.0);
2731 uniform S us;
2732
2733 void main()
2734 {
2735 gl_FragColor = vec4(0, 0, 0, 1);
2736 gl_FragColor.r += s.a;
2737 gl_FragColor.g += us.a;
2738 })";
2739
2740 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2741 glUseProgram(program);
2742
2743 // Test drawing, should be red.
2744 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2745
2746 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2747 EXPECT_GL_NO_ERROR();
2748 }
2749
2750 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2751 // beginning with "gl_" are filtered out by our validation logic, we must
2752 // bypass the validation to test the behaviour of the implementation.
2753 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2754 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2755 {
2756 constexpr char kFS[] = R"(precision mediump float;
2757
2758 void main()
2759 {
2760 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2761 })";
2762
2763 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2764
2765 // We need to bypass validation for this call.
2766 GLint nearIndex = glGetUniformLocation(program, "gl_DepthRange.near");
2767 EXPECT_EQ(-1, nearIndex);
2768
2769 // Test drawing does not throw an exception.
2770 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2771
2772 EXPECT_GL_NO_ERROR();
2773 }
2774
GenerateSmallPowShader(double base,double exponent)2775 std::string GenerateSmallPowShader(double base, double exponent)
2776 {
2777 std::stringstream stream;
2778
2779 stream.precision(8);
2780
2781 double result = pow(base, exponent);
2782
2783 stream << "precision highp float;\n"
2784 << "float fun(float arg)\n"
2785 << "{\n"
2786 << " return pow(arg, " << std::fixed << exponent << ");\n"
2787 << "}\n"
2788 << "\n"
2789 << "void main()\n"
2790 << "{\n"
2791 << " const float a = " << std::scientific << base << ";\n"
2792 << " float b = fun(a);\n"
2793 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2794 << " {\n"
2795 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2796 << " }\n"
2797 << " else\n"
2798 << " {\n"
2799 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2800 << " }\n"
2801 << "}\n";
2802
2803 return stream.str();
2804 }
2805
2806 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2807 // See http://anglebug.com/40096900
TEST_P(GLSLTest,PowOfSmallConstant)2808 TEST_P(GLSLTest, PowOfSmallConstant)
2809 {
2810 // Test with problematic exponents that are close to an integer.
2811 std::vector<double> testExponents;
2812 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2813 for (double epsilonMultiplier : epsilonMultipliers)
2814 {
2815 for (int i = -4; i <= 5; ++i)
2816 {
2817 if (i >= -1 && i <= 1)
2818 continue;
2819 const double epsilon = 1.0e-8;
2820 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
2821 testExponents.push_back(bad);
2822 }
2823 }
2824
2825 // Also test with a few exponents that are not close to an integer.
2826 testExponents.push_back(3.6);
2827 testExponents.push_back(3.4);
2828
2829 for (double testExponent : testExponents)
2830 {
2831 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2832
2833 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2834
2835 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2836
2837 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2838 EXPECT_GL_NO_ERROR();
2839 }
2840 }
2841
2842 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2843 TEST_P(GLSLTest, LoopIndexingValidation)
2844 {
2845 constexpr char kFS[] = R"(precision mediump float;
2846
2847 uniform float loopMax;
2848
2849 void main()
2850 {
2851 gl_FragColor = vec4(1, 0, 0, 1);
2852 for (float l = 0.0; l < loopMax; l++)
2853 {
2854 if (loopMax > 3.0)
2855 {
2856 gl_FragColor.a += 0.1;
2857 }
2858 }
2859 })";
2860
2861 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2862
2863 const char *sourceArray[1] = {kFS};
2864 glShaderSource(shader, 1, sourceArray, nullptr);
2865 glCompileShader(shader);
2866
2867 GLint compileResult;
2868 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2869
2870 // If the test is configured to run limited to Feature Level 9_3, then it is
2871 // assumed that shader compilation will fail with an expected error message containing
2872 // "Loop index cannot be compared with non-constant expression"
2873 if (GetParam() == ES2_D3D9())
2874 {
2875 if (compileResult != 0)
2876 {
2877 FAIL() << "Shader compilation succeeded, expected failure";
2878 }
2879 else
2880 {
2881 GLint infoLogLength;
2882 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2883
2884 std::string infoLog;
2885 infoLog.resize(infoLogLength);
2886 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2887
2888 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2889 std::string::npos)
2890 {
2891 FAIL() << "Shader compilation failed with unexpected error message";
2892 }
2893 }
2894 }
2895 else
2896 {
2897 EXPECT_NE(0, compileResult);
2898 }
2899
2900 if (shader != 0)
2901 {
2902 glDeleteShader(shader);
2903 }
2904 }
2905
2906 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2907 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2908 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2909 {
2910 // crbug.com/680631
2911 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2912
2913 int maxUniforms = 10000;
2914 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2915 EXPECT_GL_NO_ERROR();
2916 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2917
2918 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2919 }
2920
2921 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2922 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2923 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2924 {
2925 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2926
2927 // Times out on D3D11 on test infra. http://anglebug.com/42263645
2928 ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2929
2930 int maxUniforms = 10000;
2931 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2932 EXPECT_GL_NO_ERROR();
2933 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2934
2935 int maxTextureImageUnits = 0;
2936 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2937
2938 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2939 }
2940
2941 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2942 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2943 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2944 {
2945 int maxUniforms = 10000;
2946 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2947 EXPECT_GL_NO_ERROR();
2948 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2949
2950 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2951 }
2952
2953 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2954 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2955 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2956 {
2957 // crbug.com/680631
2958 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2959
2960 int maxUniforms = 10000;
2961 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2962 EXPECT_GL_NO_ERROR();
2963 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2964
2965 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2966 }
2967
2968 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2969 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2970 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2971 {
2972 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2973
2974 int maxUniforms = 10000;
2975 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2976 EXPECT_GL_NO_ERROR();
2977
2978 int maxTextureImageUnits = 0;
2979 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2980
2981 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2982 }
2983
2984 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2985 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2986 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2987 {
2988 int maxUniforms = 10000;
2989 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2990 EXPECT_GL_NO_ERROR();
2991 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2992 << std::endl;
2993
2994 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2995 }
2996
2997 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2998 TEST_P(GLSLTest, TextureLOD)
2999 {
3000 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
3001
3002 constexpr char kFS[] =
3003 "#extension GL_EXT_shader_texture_lod : require\n"
3004 "uniform sampler2D u_texture;\n"
3005 "void main() {\n"
3006 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
3007 "0.0));\n"
3008 "}\n";
3009
3010 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3011 ASSERT_NE(0u, shader);
3012 glDeleteShader(shader);
3013 }
3014
3015 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
3016 // function calls to use them in vertex shaders. http://anglebug.com/42262136
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)3017 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
3018 {
3019 constexpr char kVS[] = R"(
3020 precision highp float;
3021 uniform int uni;
3022 uniform sampler2D texture;
3023
3024 vec4 A();
3025
3026 vec4 B() {
3027 vec4 a;
3028 for(int r=0; r<14; r++){
3029 if (r < uni) return vec4(0.0);
3030 a = A();
3031 }
3032 return a;
3033 }
3034
3035 vec4 A() {
3036 return texture2D(texture, vec2(0.0, 0.0));
3037 }
3038
3039 void main() {
3040 gl_Position = B();
3041 })";
3042
3043 constexpr char kFS[] = R"(
3044 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
3045 )";
3046
3047 ANGLE_GL_PROGRAM(program, kVS, kFS);
3048 }
3049
3050 // Test to verify the a shader can have a sampler unused in a vertex shader
3051 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)3052 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
3053 {
3054 constexpr char kVS[] = R"(
3055 attribute vec2 position;
3056 varying mediump vec2 texCoord;
3057 uniform sampler2D tex;
3058 void main()
3059 {
3060 gl_Position = vec4(position, 0, 1);
3061 texCoord = position * 0.5 + vec2(0.5);
3062 })";
3063
3064 constexpr char kFS[] = R"(
3065 varying mediump vec2 texCoord;
3066 uniform sampler2D tex;
3067 void main()
3068 {
3069 gl_FragColor = texture2D(tex, texCoord);
3070 })";
3071
3072 ANGLE_GL_PROGRAM(program, kVS, kFS);
3073
3074 // Initialize basic red texture.
3075 const std::vector<GLColor> redColors(4, GLColor::red);
3076 GLTexture texture;
3077 glBindTexture(GL_TEXTURE_2D, texture);
3078 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
3079 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3080 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3081 ASSERT_GL_NO_ERROR();
3082
3083 drawQuad(program, "position", 0.0f);
3084
3085 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
3086 }
3087
3088 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)3089 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
3090 {
3091 constexpr char kFS[] =
3092 "precision mediump float;\n"
3093 "struct Data { mediump sampler2D data[2]; };\n"
3094 "uniform Data test[2];\n"
3095 "void main() {\n"
3096 " gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
3097 " texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
3098 " texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
3099 " texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
3100 "}\n";
3101
3102 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3103 glUseProgram(program);
3104 GLTexture textures[4];
3105 GLColor expected = MakeGLColor(32, 64, 96, 255);
3106 GLubyte data[8] = {}; // 4 bytes of padding, so that texture can be initialized with 4 bytes
3107 memcpy(data, expected.data(), sizeof(expected));
3108 for (int i = 0; i < 4; i++)
3109 {
3110 int outerIdx = i % 2;
3111 int innerIdx = i / 2;
3112 glActiveTexture(GL_TEXTURE0 + i);
3113 glBindTexture(GL_TEXTURE_2D, textures[i]);
3114 // Each element provides two components.
3115 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3116 std::stringstream uniformName;
3117 uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3118 // Then send it as a uniform
3119 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
3120 // The uniform should be active.
3121 EXPECT_NE(uniformLocation, -1);
3122
3123 glUniform1i(uniformLocation, 3 - i);
3124 }
3125 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3126 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3127 }
3128
3129 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3130 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3131 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3132 {
3133 constexpr const char *kFS = R"(
3134 #if __VERSION__ >= 300
3135 inout mediump vec4 fragData;
3136 #else
3137 #extension GL_EXT_shader_texture_lod :enable
3138 #endif
3139
3140 void main()
3141 {
3142 }
3143 )";
3144
3145 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3146 EXPECT_NE(0u, shader);
3147 }
3148
3149 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3150 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3151 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3152 {
3153 constexpr char kVS[] =
3154 "#version 300 es\n"
3155 "precision highp float;\n"
3156 "in vec4 a_vec;\n"
3157 "in mat2 a_mat;\n"
3158 "void main()\n"
3159 "{\n"
3160 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3161 "}";
3162
3163 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3164 EXPECT_NE(0u, program);
3165 }
3166
3167 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3168 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3169 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3170 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3171 {
3172 constexpr char kVS[] =
3173 "#version 300 es\n"
3174 "precision highp float;\n"
3175 "in mat3x2 a_matA;\n"
3176 "in mat2x3 a_matB;\n"
3177 "void main()\n"
3178 "{\n"
3179 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3180 "}";
3181
3182 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3183 EXPECT_NE(0u, program);
3184 }
3185
3186 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3187 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3188 {
3189 constexpr char kVS[] =
3190 "#version 300 es\n"
3191 "precision highp float;\n"
3192 "in vec4 a_vec;\n"
3193 "in mat2 a_mat;\n"
3194 "vec4 foo(vec4 a)\n"
3195 "{\n"
3196 " return a;\n"
3197 "}\n"
3198 "vec4 foo(mat2 a)\n"
3199 "{\n"
3200 " return vec4(a[0][0]);\n"
3201 "}\n"
3202 "void main()\n"
3203 "{\n"
3204 " gl_Position = foo(a_vec) + foo(a_mat);\n"
3205 "}";
3206
3207 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3208 EXPECT_NE(0u, program);
3209 }
3210
3211 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3212 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3213 {
3214 constexpr char kFS[] = R"(#version 300 es
3215 precision highp float;
3216 out vec4 color;
3217
3218 uniform int i;
3219 uniform uint u;
3220 uniform bool b;
3221
3222 void main()
3223 {
3224 mat3x2 mi = mat3x2(i);
3225 mat4 mu = mat4(u);
3226 mat2x4 mb = mat2x4(b);
3227
3228 mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3229
3230 color = vec4(mi[0][0] == -123.0 ? 1 : 0,
3231 mu[2][2] == 456.0 ? 1 : 0,
3232 mb[1][1] == 1.0 ? 1 : 0,
3233 m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0);
3234 })";
3235
3236 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3237 glUseProgram(program);
3238
3239 GLint iloc = glGetUniformLocation(program, "i");
3240 GLint uloc = glGetUniformLocation(program, "u");
3241 GLint bloc = glGetUniformLocation(program, "b");
3242 ASSERT_NE(iloc, -1);
3243 ASSERT_NE(uloc, -1);
3244 ASSERT_NE(bloc, -1);
3245 glUniform1i(iloc, -123);
3246 glUniform1ui(uloc, 456);
3247 glUniform1ui(bloc, 1);
3248
3249 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3250 EXPECT_GL_NO_ERROR();
3251
3252 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3253 }
3254
3255 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3256 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3257 {
3258 constexpr char kFS[] = R"(#version 300 es
3259 precision highp float;
3260 out vec4 color;
3261
3262 uniform ivec2 i;
3263 uniform uvec2 u;
3264 uniform bvec2 b;
3265
3266 void main()
3267 {
3268 vec2 v2 = vec2(i.x, b);
3269 vec3 v3 = vec3(b, u);
3270 vec4 v4 = vec4(i, u);
3271
3272 color = vec4(v2.x == -123.0 && v2.y == 1.0 ? 1 : 0,
3273 v3.x == 1.0 && v3.y == 0.0 && v3.z == 456.0 ? 1 : 0,
3274 v4.x == -123.0 && v4.y == -23.0 && v4.z == 456.0 && v4.w == 76.0 ? 1 : 0,
3275 1);
3276 })";
3277
3278 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3279 glUseProgram(program);
3280
3281 GLint iloc = glGetUniformLocation(program, "i");
3282 GLint uloc = glGetUniformLocation(program, "u");
3283 GLint bloc = glGetUniformLocation(program, "b");
3284 ASSERT_NE(iloc, -1);
3285 ASSERT_NE(uloc, -1);
3286 ASSERT_NE(bloc, -1);
3287 glUniform2i(iloc, -123, -23);
3288 glUniform2ui(uloc, 456, 76);
3289 glUniform2ui(bloc, 1, 0);
3290
3291 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3292 EXPECT_GL_NO_ERROR();
3293
3294 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3295 }
3296
3297 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3298 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3299 {
3300 constexpr char kFS[] = R"(#version 300 es
3301 precision highp float;
3302 out vec4 color;
3303
3304 uniform float f;
3305
3306 void main()
3307 {
3308 mat4 m = mat4(f);
3309 ivec3 vi = ivec3(m);
3310 uvec2 vu = uvec2(m);
3311 bvec4 vb = bvec4(m);
3312 bvec2 vb2 = bvec2(vi.x, m);
3313
3314 color = vec4(vi.x == int(f) ? 1 : 0,
3315 vu.x == uint(f) ? 1 : 0,
3316 vb.x == bool(f) ? 1 : 0,
3317 vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3318 })";
3319
3320 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3321 glUseProgram(program);
3322
3323 GLint floc = glGetUniformLocation(program, "f");
3324 ASSERT_NE(floc, -1);
3325 glUniform1f(floc, 123);
3326
3327 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3328 EXPECT_GL_NO_ERROR();
3329
3330 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3331 }
3332
3333 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3334 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3335 {
3336 constexpr char kFS[] = R"(#version 300 es
3337 precision highp float;
3338 out vec4 color;
3339
3340 uniform float f;
3341 uniform int i;
3342 uniform uint u;
3343
3344 void main()
3345 {
3346 mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3347 mat3x2 m32_2 = mat3x2(m32_1);
3348 mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3349 mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3350 mat2x3 m23_2 = mat2x3(m23_1);
3351 mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3352 vec2 v2_1 = m32_1[0];
3353 vec2 v2_2 = m32_2[0];
3354 ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3355 ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3356 uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3357 uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3358
3359 color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3360 v2_1 == v2_2 ? 1 : 0,
3361 (v3_1 == v3_2 ? 0.5 : 0.0) +
3362 (v4_1 == v4_2 ? 0.5 : 0.0),
3363 (m32_1 != m32_3 ? 0.125 : 0.0) +
3364 (m23_1 != m23_3 ? 0.125 : 0.0) +
3365 (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3366 (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3367 (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3368 })";
3369
3370 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3371 glUseProgram(program);
3372
3373 GLint floc = glGetUniformLocation(program, "f");
3374 GLint iloc = glGetUniformLocation(program, "i");
3375 GLint uloc = glGetUniformLocation(program, "u");
3376 ASSERT_NE(floc, -1);
3377 ASSERT_NE(iloc, -1);
3378 ASSERT_NE(uloc, -1);
3379 glUniform1f(floc, 1.5);
3380 glUniform1i(iloc, -123);
3381 glUniform1ui(uloc, 456);
3382
3383 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3384 EXPECT_GL_NO_ERROR();
3385
3386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3387 }
3388
3389 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3390 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3391 {
3392 constexpr char kFS[] = R"(#version 310 es
3393 precision highp float;
3394 out vec4 color;
3395
3396 uniform float f;
3397 uniform int i;
3398 uniform uint u;
3399
3400 struct S
3401 {
3402 float f;
3403 int i;
3404 uint u;
3405 vec4 v;
3406 ivec3 iv;
3407 uvec2 uv;
3408 mat3x2 m32;
3409 mat2x3 m23;
3410 float fa[3][4][5];
3411 int ia[4];
3412 uint ua[6][2];
3413 };
3414
3415 struct T
3416 {
3417 S s1;
3418 S s2[3][2];
3419 };
3420
3421 void main()
3422 {
3423 float fa[5] = float[5](f, f, f, f, f);
3424 int ia[4] = int[4](i, i, i, i);
3425 uint ua[2] = uint[2](u, u);
3426
3427 S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3428 mat3x2(vec2(f), vec2(i), vec2(u)),
3429 mat2x3(vec3(f), vec3(i)),
3430 float[3][4][5](
3431 float[4][5](fa, fa, fa, fa),
3432 float[4][5](fa, fa, fa, fa),
3433 float[4][5](fa, fa, fa, fa)),
3434 ia,
3435 uint[6][2](ua, ua, ua, ua, ua, ua));
3436
3437 S s2[2] = S[2](s1, s1);
3438 s2[1].fa[0][1][2] = float(i);
3439
3440 T t1 = T(s1, S[3][2](s2, s2, s2));
3441 T t2 = T(s2[1], S[3][2](s2, s2, s2));
3442
3443 T ta1[2] = T[2](t1, t2);
3444 T ta2[2] = T[2](t1, t2);
3445 T ta3[2] = T[2](t2, t1);
3446
3447 color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3448 (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3449 (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3450 (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3451 })";
3452
3453 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3454 glUseProgram(program);
3455
3456 GLint floc = glGetUniformLocation(program, "f");
3457 GLint iloc = glGetUniformLocation(program, "i");
3458 GLint uloc = glGetUniformLocation(program, "u");
3459 ASSERT_NE(floc, -1);
3460 ASSERT_NE(iloc, -1);
3461 ASSERT_NE(uloc, -1);
3462 glUniform1f(floc, 1.5);
3463 glUniform1i(iloc, -123);
3464 glUniform1ui(uloc, 456);
3465
3466 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3467 EXPECT_GL_NO_ERROR();
3468
3469 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3470 }
3471
3472 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3473 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3474 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3475 {
3476 std::stringstream vertexShaderStream;
3477 // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3478 const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3479
3480 vertexShaderStream << "#version 300 es\n"
3481 "precision highp float;\n"
3482 "in vec4 a_vec;\n"
3483 "vec4 lotsOfVec4Parameters(";
3484 for (unsigned int i = 0; i < paramCount - 1; ++i)
3485 {
3486 vertexShaderStream << "vec4 a" << i << ", ";
3487 }
3488 vertexShaderStream << "vec4 aLast)\n"
3489 "{\n"
3490 " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3491 for (unsigned int i = 0; i < paramCount - 1; ++i)
3492 {
3493 vertexShaderStream << " sum += a" << i << ";\n";
3494 }
3495 vertexShaderStream << " sum += aLast;\n"
3496 " return sum;\n "
3497 "}\n"
3498 "void main()\n"
3499 "{\n"
3500 " gl_Position = lotsOfVec4Parameters(";
3501 for (unsigned int i = 0; i < paramCount - 1; ++i)
3502 {
3503 vertexShaderStream << "a_vec, ";
3504 }
3505 vertexShaderStream << "a_vec);\n"
3506 "}";
3507
3508 GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3509 EXPECT_NE(0u, program);
3510 }
3511
3512 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3513 // Test a shader where a global constant array is initialized with an expression containing array
3514 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3515 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3516 // Also includes multiple array initializers in one declaration, where only the second one has
3517 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3518 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3519 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3520 {
3521 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260423 is fixed
3522 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3523
3524 constexpr char kFS[] =
3525 "#version 300 es\n"
3526 "precision highp float;\n"
3527 "out vec4 my_FragColor;\n"
3528 "const highp float f[2] = float[2](0.1, 0.2);\n"
3529 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3530 "void main()\n"
3531 "{\n"
3532 " my_FragColor = vec4(h[1]);\n"
3533 "}";
3534
3535 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3536 EXPECT_NE(0u, program);
3537 }
3538
3539 // Test that constant global matrix array with an initializer compiles.
TEST_P(GLSLTest_ES3,InitConstantMatrixArray)3540 TEST_P(GLSLTest_ES3, InitConstantMatrixArray)
3541 {
3542 constexpr char kFS[] = R"(#version 300 es
3543 precision highp float;
3544 uniform int index;
3545
3546 const mat4 matrix = mat4(1.0);
3547 const mat4 array[1] = mat4[1](matrix);
3548 out vec4 my_FragColor;
3549 void main() {
3550 my_FragColor = vec4(array[index][1].rgb, 1.0);
3551 })";
3552
3553 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3554
3555 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3556 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3557 }
3558
3559 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3560 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3561 {
3562 constexpr char kFS[] =
3563 "precision mediump float;\n"
3564 "uniform sampler2D uni[2];\n"
3565 "\n"
3566 "float zero(int x)\n"
3567 "{\n"
3568 " return float(x) - float(x);\n"
3569 "}\n"
3570 "\n"
3571 "void main()\n"
3572 "{\n"
3573 " vec4 c = vec4(0,0,0,0);\n"
3574 " for (int ii = 1; ii < 3; ++ii) {\n"
3575 " if (c.x > 255.0) {\n"
3576 " c.x = 255.0 + zero(ii);\n"
3577 " break;\n"
3578 " }\n"
3579 // Index the sampler array with a predictable loop index (index-constant) as opposed to
3580 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3581 // without an extension.
3582 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3583 " }\n"
3584 " gl_FragColor = c;\n"
3585 "}";
3586
3587 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3588 EXPECT_NE(0u, program);
3589 }
3590
3591 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3592 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3593 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3594 TEST_P(GLSLTest, PragmaDirective)
3595 {
3596 constexpr char kVS[] =
3597 "#pragma STDGL invariant(all)\n"
3598 "void main()\n"
3599 "{\n"
3600 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3601 "}\n";
3602
3603 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3604 EXPECT_NE(0u, program);
3605 }
3606
3607 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3608 // The function call that returns the array needs to be evaluated after ++j for the expression to
3609 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3610 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3611 {
3612 constexpr char kFS[] =
3613 "#version 300 es\n"
3614 "precision mediump float;\n"
3615 "out vec4 my_FragColor; \n"
3616 "int[2] func(int param) {\n"
3617 " return int[2](param, param);\n"
3618 "}\n"
3619 "void main() {\n"
3620 " int a[2]; \n"
3621 " for (int i = 0; i < 2; ++i) {\n"
3622 " a[i] = 1;\n"
3623 " }\n"
3624 " int j = 0; \n"
3625 " bool result = ((++j), (a == func(j)));\n"
3626 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3627 "}\n";
3628
3629 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3630 ASSERT_NE(0u, program);
3631
3632 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3633
3634 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3635 }
3636
3637 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3638 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3639 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3640 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3641 {
3642 constexpr char kFS[] =
3643 "#version 300 es\n"
3644 "precision mediump float;\n"
3645 "out vec4 my_FragColor; \n"
3646 "void main() {\n"
3647 " int j = 0; \n"
3648 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3649 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3650 "}\n";
3651
3652 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3653 ASSERT_NE(0u, program);
3654
3655 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3656
3657 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3658 }
3659
3660 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3661 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3662 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3663 {
3664 constexpr char kFS[] =
3665 "#version 300 es\n"
3666 "precision mediump float;\n"
3667 "out vec4 my_FragColor;\n"
3668 "uniform int u_zero;\n"
3669 "int sideEffectCount = 0;\n"
3670 "float func() {\n"
3671 " ++sideEffectCount;\n"
3672 " return -1.0;\n"
3673 "}\n"
3674 "void main() {\n"
3675 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3676 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3677 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3678 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3679 "}\n";
3680
3681 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3682 ASSERT_NE(0u, program);
3683
3684 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3685
3686 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3687 }
3688
3689 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3690 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3691 // See http://anglebug.com/42260376
TEST_P(GLSLTest,RenderTrisWithPointCoord)3692 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3693 {
3694 constexpr char kVS[] =
3695 "attribute vec2 aPosition;\n"
3696 "void main()\n"
3697 "{\n"
3698 " gl_Position = vec4(aPosition, 0, 1);\n"
3699 " gl_PointSize = 1.0;\n"
3700 "}";
3701 constexpr char kFS[] =
3702 "void main()\n"
3703 "{\n"
3704 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3705 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3706 "}";
3707
3708 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3709 drawQuad(prog, "aPosition", 0.5f);
3710 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3711 }
3712
3713 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3714 TEST_P(GLSLTest, NestedPowStatements)
3715 {
3716 // https://crbug.com/1127866 - possible NVIDIA driver issue
3717 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3718
3719 constexpr char kFS[] =
3720 "precision mediump float;\n"
3721 "float func(float v)\n"
3722 "{\n"
3723 " float f1 = pow(v, 2.0);\n"
3724 " return pow(f1 + v, 2.0);\n"
3725 "}\n"
3726 "void main()\n"
3727 "{\n"
3728 " float v = func(2.0);\n"
3729 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3730 "}";
3731
3732 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3733 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3734 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3735 }
3736
3737 // This test covers a crash seen in an application during SPIR-V compilation
TEST_P(GLSLTest_ES3,NestedPowFromUniform)3738 TEST_P(GLSLTest_ES3, NestedPowFromUniform)
3739 {
3740 constexpr char kVS[] = R"(#version 300 es
3741 in vec2 position;
3742 void main()
3743 {
3744 gl_Position = vec4(position, 0, 1);
3745 })";
3746
3747 constexpr char kFS[] = R"(#version 300 es
3748 precision mediump float;
3749 precision mediump int;
3750
3751 uniform highp vec4 scale;
3752 out mediump vec4 out_FragColor;
3753 void main()
3754 {
3755 highp vec4 v0;
3756 v0 = scale;
3757 highp vec3 v1;
3758 v1.xyz = v0.xyz;
3759 if ((v0.y!=1.0))
3760 {
3761 vec3 v3;
3762 v3.xyz = pow(v0.xyz,v0.xxx);
3763 float h0;
3764 if ((v3.x < 3.13))
3765 {
3766 h0 = (v3.x * 1.29);
3767 }
3768 else
3769 {
3770 h0 = ((pow(v3.x,4.16)*1.055)+-5.5);
3771 }
3772 float h1;
3773 if ((v3.y<3.13))
3774 {
3775 h1 = (v3.y*1.29);
3776 }
3777 else
3778 {
3779 h1 = ((pow(v3.y,4.16)*1.055)+-5.5);
3780 }
3781 float h2;
3782 if ((v3.z<3.13))
3783 {
3784 h2 = (v3.z*1.29);
3785 }
3786 else
3787 {
3788 h2 = ((pow(v3.z,4.16)*1.055)+-5.5);
3789 }
3790 v1.xyz = vec3(h0, h1, h2);
3791 }
3792 out_FragColor = vec4(v1, v0.w);
3793 }
3794 )";
3795
3796 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3797
3798 GLint scaleIndex = glGetUniformLocation(prog, "scale");
3799 ASSERT_NE(-1, scaleIndex);
3800
3801 glUseProgram(prog);
3802 glUniform4f(scaleIndex, 0.5, 0.5, 0.5, 0.5);
3803
3804 // Don't crash
3805 drawQuad(prog, "position", 0.5f);
3806 }
3807
3808 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3809 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3810 {
3811 constexpr char kFS[] =
3812 "#version 300 es\n"
3813 "out highp vec4 o_color;\n"
3814 "void main() {\n"
3815 " highp float f = -1.0;\n"
3816 " // atan(tan(0.5), -f) should be 0.5.\n"
3817 " highp float v = atan(tan(0.5), -f);\n"
3818 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3819 "}\n";
3820
3821 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3822 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3823 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3824 }
3825
3826 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3827 TEST_P(GLSLTest_ES3, AtanVec2)
3828 {
3829 constexpr char kFS[] =
3830 "#version 300 es\n"
3831 "out highp vec4 o_color;\n"
3832 "void main() {\n"
3833 " highp float f = 1.0;\n"
3834 " // atan(tan(0.5), f) should be 0.5.\n"
3835 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3836 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3837 "vec4(1, 0, 0, 1);\n"
3838 "}\n";
3839
3840 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3841 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3842 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3843 }
3844
3845 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3846 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3847 {
3848 constexpr char kVS[] =
3849 "#version 300 es\n"
3850 "in highp vec4 position;\n"
3851 "out mediump vec4 v_color;\n"
3852 "uniform int ui_one;\n"
3853 "uniform int ui_two;\n"
3854 "uniform int ui_three;\n"
3855 "void main() {\n"
3856 " int s[3];\n"
3857 " s[0] = ui_one;\n"
3858 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
3859 " s[2] = ui_three;\n"
3860 " int result = 0;\n"
3861 " for (int i = 0; i < ui_three; i++) {\n"
3862 " result += s[i];\n"
3863 " }\n"
3864 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3865 " gl_Position = position;\n"
3866 "}\n";
3867 constexpr char kFS[] =
3868 "#version 300 es\n"
3869 "in mediump vec4 v_color;\n"
3870 "layout(location=0) out mediump vec4 o_color;\n"
3871 "void main() {\n"
3872 " o_color = v_color;\n"
3873 "}\n";
3874
3875 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3876
3877 GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3878 ASSERT_NE(-1, oneIndex);
3879 GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3880 ASSERT_NE(-1, twoIndex);
3881 GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3882 ASSERT_NE(-1, threeIndex);
3883 glUseProgram(prog);
3884 glUniform1i(oneIndex, 1);
3885 glUniform1i(twoIndex, 2);
3886 glUniform1i(threeIndex, 3);
3887
3888 drawQuad(prog, "position", 0.5f);
3889 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3890 }
3891
3892 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3893 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3894 {
3895 constexpr char kVS[] =
3896 "#version 300 es\n"
3897 "in highp vec4 position;\n"
3898 "out mediump vec4 v_color;\n"
3899 "uniform uint ui_one;\n"
3900 "uniform uint ui_two;\n"
3901 "uniform uint ui_three;\n"
3902 "void main() {\n"
3903 " uint s[3];\n"
3904 " s[0] = ui_one;\n"
3905 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
3906 " s[2] = ui_three;\n"
3907 " uint result = 0u;\n"
3908 " for (uint i = 0u; i < ui_three; i++) {\n"
3909 " result += s[i];\n"
3910 " }\n"
3911 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3912 " gl_Position = position;\n"
3913 "}\n";
3914 constexpr char kFS[] =
3915 "#version 300 es\n"
3916 "in mediump vec4 v_color;\n"
3917 "layout(location=0) out mediump vec4 o_color;\n"
3918 "void main() {\n"
3919 " o_color = v_color;\n"
3920 "}\n";
3921
3922 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3923
3924 GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3925 ASSERT_NE(-1, oneIndex);
3926 GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3927 ASSERT_NE(-1, twoIndex);
3928 GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3929 ASSERT_NE(-1, threeIndex);
3930 glUseProgram(prog);
3931 glUniform1ui(oneIndex, 1u);
3932 glUniform1ui(twoIndex, 2u);
3933 glUniform1ui(threeIndex, 3u);
3934
3935 drawQuad(prog, "position", 0.5f);
3936 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3937 }
3938
3939 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3940 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3941 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3942 {
3943 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3944 // its default value false.
3945 constexpr char kFS[] =
3946 "precision mediump float;\n"
3947 "uniform bool keep_flop_positive;\n"
3948 "float flop;\n"
3949 "void main() {\n"
3950 " flop = -1.0,\n"
3951 " (flop *= -1.0,\n"
3952 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3953 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
3954 "}";
3955
3956 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3957 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3958 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3959 }
3960
3961 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3962 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3963 {
3964 // Note that the uniform doesn't need to be set, and will contain the default value of false.
3965 constexpr char kFS[] = R"(
3966 precision mediump float;
3967 uniform bool u;
3968 void main()
3969 {
3970 int a = u ? 12345 : 2; // will be 2
3971 int b = u ? 12345 : 4; // will be 4
3972 int c = u ? 12345 : 0; // will be 0
3973
3974 if (a == 2 // true path is taken
3975 ? (b == 3 // false path is taken
3976 ? (a=0) != 0
3977 : b != 0 // true
3978 ) && ( // short-circuit evaluates RHS
3979 (a=7) == 7 // true, modifies a
3980 || // short-circuit doesn't evaluate RHS
3981 (b=8) == 8
3982 )
3983 : (a == 0 && b == 0
3984 ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3985 : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3986 {
3987 c += 15; // will execute
3988 }
3989
3990 // Verify that a is 7, b is 4 and c is 15.
3991 gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3992 })";
3993
3994 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3995 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3996 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3997 }
3998
3999 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)4000 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
4001 {
4002 constexpr char kFS[] = R"(#version 300 es
4003 precision mediump float;
4004 uniform bvec4 u;
4005 out vec4 color;
4006
4007 bool f(bvec4 bv)
4008 {
4009 return all(bv.xz) && !any(bv.yw);
4010 }
4011
4012 void main() {
4013 color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
4014 })";
4015
4016 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
4017 glUseProgram(prog);
4018
4019 GLint uloc = glGetUniformLocation(prog, "u");
4020 ASSERT_NE(uloc, -1);
4021 glUniform4ui(uloc, true, false, true, false);
4022
4023 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
4024 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4025 }
4026
4027 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)4028 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
4029 {
4030 constexpr char kCS[] = R"(#version 310 es
4031 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4032 layout(binding = 0, std430) buffer Output {
4033 bvec4 b;
4034 bool valid;
4035 } outbuf;
4036
4037 bool f_in(bvec4 bv)
4038 {
4039 return all(bv.xz) && !any(bv.yw);
4040 }
4041
4042 bool f_inout(inout bvec4 bv)
4043 {
4044 bool ok = all(bv.xz) && !any(bv.yw);
4045 bv.xw = bvec2(false, true);
4046 return ok;
4047 }
4048
4049 void f_out(out bvec4 bv)
4050 {
4051 bv = bvec4(false, true, false, true);
4052 }
4053
4054 void main() {
4055 bool valid = f_in(outbuf.b);
4056 valid = f_inout(outbuf.b) && valid;
4057 f_out(outbuf.b);
4058 outbuf.valid = valid;
4059 })";
4060
4061 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4062 glUseProgram(program);
4063
4064 constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
4065 GLBuffer outputBuffer;
4066 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4067 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4068 GL_STATIC_DRAW);
4069 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4070 EXPECT_GL_NO_ERROR();
4071
4072 glDispatchCompute(1, 1, 1);
4073 EXPECT_GL_NO_ERROR();
4074
4075 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4076
4077 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4078 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4079 fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
4080 EXPECT_FALSE(ptr[0]);
4081 EXPECT_TRUE(ptr[1]);
4082 EXPECT_FALSE(ptr[2]);
4083 EXPECT_TRUE(ptr[3]);
4084 EXPECT_TRUE(ptr[4]);
4085 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4086 }
4087
4088 // Test that using a sampler2D and samplerExternalOES in the same shader works
4089 // (anglebug.com/42260512)
TEST_P(GLSLTest,ExternalAnd2DSampler)4090 TEST_P(GLSLTest, ExternalAnd2DSampler)
4091 {
4092 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
4093
4094 constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
4095 precision mediump float;
4096 uniform samplerExternalOES tex0;
4097 uniform sampler2D tex1;
4098 void main(void)
4099 {
4100 vec2 uv = vec2(0.0, 0.0);
4101 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
4102 })";
4103
4104 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4105 }
4106
4107 // Tests that monomorphizing functions does not crash if there is a main prototype.
TEST_P(GLSLTest,MonomorphizeMainPrototypeNoCrash)4108 TEST_P(GLSLTest, MonomorphizeMainPrototypeNoCrash)
4109 {
4110 constexpr char kFS[] = R"(precision mediump float;
4111 struct S { sampler2D source; };
4112 vec4 f(S s)
4113 {
4114 return texture2D(s.source, vec2(5));
4115 }
4116 uniform S green;
4117 void main();
4118 void main() {
4119 f(green);
4120 })";
4121 CompileShader(GL_FRAGMENT_SHADER, kFS);
4122 ASSERT_GL_NO_ERROR();
4123 }
4124
4125 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)4126 TEST_P(GLSLTest, VaryingMatrixArray)
4127 {
4128 constexpr char kVS[] =
4129 "uniform vec2 u_a1;\n"
4130 "uniform vec2 u_a2;\n"
4131 "attribute vec4 a_position;\n"
4132 "varying mat2 v_mat[2];\n"
4133 "void main() {\n"
4134 " v_mat[0] = mat2(u_a1, u_a2);\n"
4135 " v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
4136 " gl_Position = a_position;\n"
4137 "}";
4138
4139 constexpr char kFS[] =
4140 "precision mediump float;\n"
4141 "varying mat2 v_mat[2];\n"
4142 "void main(void)\n"
4143 "{\n"
4144 " gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4145 "}";
4146
4147 ANGLE_GL_PROGRAM(program, kVS, kFS);
4148
4149 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4150 ASSERT_NE(-1, oneIndex);
4151 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4152 ASSERT_NE(-1, twoIndex);
4153 glUseProgram(program);
4154 glUniform2f(oneIndex, 1, 0.5f);
4155 glUniform2f(twoIndex, 0.25f, 0.125f);
4156
4157 drawQuad(program, "a_position", 0.5f);
4158 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4159 }
4160
4161 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)4162 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
4163 {
4164 constexpr char kVS[] =
4165 "#version 300 es\n"
4166 "uniform vec2 u_a1;\n"
4167 "uniform vec2 u_a2;\n"
4168 "in vec4 a_position;\n"
4169 "centroid out mat3x2 v_mat[2];\n"
4170 "void main() {\n"
4171 " v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
4172 " v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
4173 " gl_Position = a_position;\n"
4174 "}";
4175
4176 constexpr char kFS[] =
4177 "#version 300 es\n"
4178 "precision mediump float;\n"
4179 "centroid in mat3x2 v_mat[2];\n"
4180 "layout(location = 0) out vec4 out_color;\n"
4181 "void main(void)\n"
4182 "{\n"
4183 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
4184 "}";
4185
4186 ANGLE_GL_PROGRAM(program, kVS, kFS);
4187
4188 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4189 ASSERT_NE(-1, oneIndex);
4190 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4191 ASSERT_NE(-1, twoIndex);
4192 glUseProgram(program);
4193 glUniform2f(oneIndex, 1, 0.5f);
4194 glUniform2f(twoIndex, 0.25f, 0.125f);
4195
4196 drawQuad(program, "a_position", 0.5f);
4197 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4198 }
4199
4200 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)4201 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
4202 {
4203 constexpr char kVS[] =
4204 "#version 300 es\n"
4205 "uniform vec2 u_a1;\n"
4206 "uniform vec2 u_a2;\n"
4207 "in vec4 a_position;\n"
4208 "flat out mat2 v_mat[2];\n"
4209 "void main() {\n"
4210 " v_mat[0] = mat2(u_a1, u_a2);\n"
4211 " v_mat[1] = mat2(u_a2, u_a1);\n"
4212 " gl_Position = a_position;\n"
4213 "}";
4214
4215 constexpr char kFS[] =
4216 "#version 300 es\n"
4217 "precision mediump float;\n"
4218 "flat in mat2 v_mat[2];\n"
4219 "layout(location = 0) out vec4 out_color;\n"
4220 "void main(void)\n"
4221 "{\n"
4222 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4223 "}";
4224
4225 ANGLE_GL_PROGRAM(program, kVS, kFS);
4226
4227 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4228 ASSERT_NE(-1, oneIndex);
4229 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4230 ASSERT_NE(-1, twoIndex);
4231 glUseProgram(program);
4232 glUniform2f(oneIndex, 1, 0.5f);
4233 glUniform2f(twoIndex, 0.25f, 0.125f);
4234
4235 drawQuad(program, "a_position", 0.5f);
4236 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4237 }
4238
4239 // Test that using a varying matrix array works with a particular input names scheme.
4240 // Test that having "mat3 a[*]" and "mat2 a_0" does not cause internal shader compile failures.
4241 // For a buggy naming scheme both would expand into a_0_0 and cause problems.
TEST_P(GLSLTest_ES3,VaryingMatrixArrayNaming2)4242 TEST_P(GLSLTest_ES3, VaryingMatrixArrayNaming2)
4243 {
4244 constexpr char kVS[] = R"(#version 300 es
4245 precision mediump float;
4246 uniform mat3 r0;
4247 uniform mat2 r1;
4248 in vec4 a_position;
4249 out mat2 a_0;
4250 out mat3 a[2];
4251 void main() {
4252 a[0] = r0;
4253 a[1] = r0 + mat3(1, 1, 1, 1, 1, 1, 1, 1, 1);
4254 a_0 = r1;
4255 gl_Position = a_position;
4256 })";
4257 constexpr char kFS[] = R"(#version 300 es
4258 precision mediump float;
4259 in mat2 a_0;
4260 in mat3 a[2];
4261 layout(location = 0) out vec4 o;
4262 void main(void) {
4263 mat3 diff0 = a[0] - mat3(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8);
4264 mat3 diff1 = a[1] - mat3(1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8);
4265 mat2 diff2 = a_0 - mat2(3.0, 3.1, 3.2, 3.3);
4266 o.r = all(lessThan(abs(diff0[0]) + abs(diff0[1]) + abs(diff0[2]), vec3(0.01))) ? 1.0 : 0.0;
4267 o.g = all(lessThan(abs(diff1[0]) + abs(diff1[1]) + abs(diff1[2]), vec3(0.01))) ? 1.0 : 0.0;
4268 o.b = all(lessThan(abs(diff2[0]) + abs(diff2[1]), vec2(0.01))) ? 1.0 : 0.0;
4269 o.a = 1.0;
4270 })";
4271 ANGLE_GL_PROGRAM(program, kVS, kFS);
4272
4273 GLint r0 = glGetUniformLocation(program, "r0");
4274 ASSERT_NE(-1, r0);
4275 GLint r1 = glGetUniformLocation(program, "r1");
4276 ASSERT_NE(-1, r1);
4277 glUseProgram(program);
4278 float r0v[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f};
4279 glUniformMatrix3fv(r0, 1, false, r0v);
4280 float r1v[] = {3.0f, 3.1f, 3.2f, 3.3f};
4281 glUniformMatrix2fv(r1, 1, false, r1v);
4282 drawQuad(program, "a_position", 0.5f);
4283 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0);
4284 }
4285
4286 // Test that literal infinity can be written out from the shader translator.
4287 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralInfinityOutput)4288 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4289 {
4290 constexpr char kFS[] =
4291 "#version 300 es\n"
4292 "precision highp float;\n"
4293 "out vec4 out_color;\n"
4294 "uniform float u;\n"
4295 "void main()\n"
4296 "{\n"
4297 " float infVar = 1.0e40 - u;\n"
4298 " bool correct = isinf(infVar) && infVar > 0.0;\n"
4299 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4300 "}\n";
4301
4302 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4303 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4304 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4305 }
4306
4307 // Test that literal negative infinity can be written out from the shader translator.
4308 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralNegativeInfinityOutput)4309 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4310 {
4311 constexpr char kFS[] =
4312 "#version 300 es\n"
4313 "precision highp float;\n"
4314 "out vec4 out_color;\n"
4315 "uniform float u;\n"
4316 "void main()\n"
4317 "{\n"
4318 " float infVar = -1.0e40 + u;\n"
4319 " bool correct = isinf(infVar) && infVar < 0.0;\n"
4320 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4321 "}\n";
4322
4323 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4324 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4325 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4326 }
4327
4328 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4329 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4330 // a unittest for them. Instead we add the tests as end2end so will in particular test
4331 // TranslatorHLSL when run on Windows.
4332
4333 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4334 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4335 {
4336 constexpr char kFS[] = R"(#version 300 es
4337 precision mediump float;
4338 out vec4 color;
4339
4340 uniform float u;
4341 float c = 0.0;
4342 float sideEffect()
4343 {
4344 c = u;
4345 return c;
4346 }
4347
4348 void main(void)
4349 {
4350 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4351 color = vec4(b + c);
4352 })";
4353
4354 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4355 }
4356
4357 // Test that passes splitting multiple declarations and comma operators and for loops are
4358 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4359 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4360 {
4361 constexpr char kFS[] = R"(#version 300 es
4362 precision mediump float;
4363 out vec4 color;
4364
4365 uniform float u;
4366 float c = 0.0;
4367 float sideEffect()
4368 {
4369 c = u;
4370 return c;
4371 }
4372
4373 void main(void)
4374 {
4375 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4376 {
4377 b += 1.0;
4378 color = vec4(b);
4379 }
4380 })";
4381
4382 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4383 }
4384
4385 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4386 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4387 {
4388 constexpr char kFS[] =
4389 "#version 300 es\n"
4390 "precision mediump float;\n"
4391 "out vec4 color;\n"
4392 "void main(void)\n"
4393 "{\n"
4394 " for(float a = 0.0, b = 1.0;; a++)\n"
4395 " {\n"
4396 " b += 1.0;\n"
4397 " if (a > 10.0) {break;}\n"
4398 " color = vec4(b);\n"
4399 " }\n"
4400 "}\n";
4401
4402 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4403 }
4404
4405 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4406 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4407 {
4408 constexpr char kFS[] =
4409 "#version 300 es\n"
4410 "precision mediump float;\n"
4411 "out vec4 color;\n"
4412 "void main(void)\n"
4413 "{\n"
4414 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4415 " {\n"
4416 " b += 1.0;\n"
4417 " a += 1.0;\n"
4418 " color = vec4(b);\n"
4419 " }\n"
4420 "}\n";
4421
4422 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4423 }
4424
4425 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4426 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4427 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4428 {
4429 constexpr char kFS[] =
4430 "#version 300 es\n"
4431 "precision mediump float;\n"
4432 "out vec4 my_FragColor;\n"
4433 "uniform int u_zero;\n"
4434 "void main() {\n"
4435 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4436 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4437 " float f = m[1][1];\n"
4438 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4439 "}\n";
4440
4441 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4442 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4443 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4444 }
4445
4446 class WebGLGLSLTest : public GLSLTest
4447 {
4448 protected:
WebGLGLSLTest()4449 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4450 };
4451
4452 class WebGL2GLSLTest : public GLSLTest
4453 {
4454 protected:
WebGL2GLSLTest()4455 WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4456 };
4457
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4458 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4459 {
4460 GLint maxVaryings = 0;
4461 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4462
4463 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4464 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4465 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4466 }
4467
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4468 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4469 {
4470 GLint maxVaryings = 0;
4471 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4472
4473 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4474 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4475 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4476 }
4477
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4478 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4479 {
4480 GLint maxVaryings = 0;
4481 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4482
4483 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4484 }
4485
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4486 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4487 {
4488 GLint maxVaryings = 0;
4489 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4490
4491 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4492 }
4493
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4494 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4495 {
4496 GLint maxVaryings = 0;
4497 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4498
4499 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4500 }
4501
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4502 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4503 {
4504 GLint maxVaryings = 0;
4505 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4506
4507 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4508 }
4509
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4510 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4511 {
4512 GLint maxVaryings = 0;
4513 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4514
4515 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4516 false);
4517 }
4518
4519 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4520 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4521 {
4522 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4523 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4524
4525 // Failing on N5X Oreo http://anglebug.com/42261013
4526 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4527
4528 constexpr char kFS[] =
4529 "#version 310 es\n"
4530 "precision mediump float;\n"
4531 "out vec4 my_FragColor;\n"
4532 "uniform int u_zero;\n"
4533 "void main() {\n"
4534 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4535 " {\n"
4536 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4537 " }\n"
4538 " else\n"
4539 " {\n"
4540 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4541 " }\n"
4542 "}\n";
4543
4544 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4545 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4546 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4547 }
4548
4549 // Test that reading from a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,ReadFromDynamicIndexingOfSwizzledVector)4550 TEST_P(GLSLTest_ES3, ReadFromDynamicIndexingOfSwizzledVector)
4551 {
4552 constexpr char kFS[] = R"(#version 300 es
4553 precision highp float;
4554
4555 uniform int index;
4556 uniform vec4 data;
4557
4558 out vec4 color;
4559 void main() {
4560 color = vec4(vec4(data.x, data.y, data.z, data.w).zyxw[index], 0, 0, 1);
4561 })";
4562
4563 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4564 glUseProgram(program);
4565
4566 GLint dataLoc = glGetUniformLocation(program, "data");
4567 glUniform4f(dataLoc, 0.2, 0.4, 0.6, 0.8);
4568 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4569
4570 EXPECT_PIXEL_NEAR(0, 0, 153, 0, 0, 255, 1);
4571 }
4572
4573 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4574 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4575 {
4576 // http://anglebug.com/40644616
4577 ANGLE_SKIP_TEST_IF(IsOpenGL());
4578
4579 // The shader first assigns v.x to v.z (1.0)
4580 // Then v.y to v.y (2.0)
4581 // Then v.z to v.x (1.0)
4582 constexpr char kFS[] =
4583 "#version 300 es\n"
4584 "precision highp float;\n"
4585 "out vec4 my_FragColor;\n"
4586 "void main() {\n"
4587 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
4588 " for (int i = 0; i < 3; i++) {\n"
4589 " v.zyx[i] = v[i];\n"
4590 " }\n"
4591 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4592 "0, 0, 1);\n"
4593 "}\n";
4594
4595 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4596 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4597 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4598 }
4599
4600 // Test including Ternary using a uniform block is correctly
4601 // expanded.
TEST_P(GLSLTest_ES3,NamelessUniformBlockTernary)4602 TEST_P(GLSLTest_ES3, NamelessUniformBlockTernary)
4603 {
4604 const char kVS[] = R"(#version 300 es
4605 precision highp float;
4606 out vec4 color_interp;
4607 void main()
4608 {
4609 color_interp = vec4(0.0);
4610 }
4611 )";
4612 const char kFS[] = R"(#version 300 es
4613 precision highp float;
4614 out vec4 fragColor;
4615 in vec4 color_interp;
4616 layout(std140) uniform TestData {
4617 int a;
4618 int b;
4619 };
4620 void main()
4621 {
4622 int c, a1;
4623 a1 += c > 0 ? a : b;
4624 fragColor = vec4(a1,a1,a1,1.0);
4625 }
4626 )";
4627 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4628 }
4629
4630 // Test that uniform block variables work as comma expression results.
TEST_P(GLSLTest_ES3,UniformBlockCommaExpressionResult)4631 TEST_P(GLSLTest_ES3, UniformBlockCommaExpressionResult)
4632 {
4633 constexpr char kFS[] = R"(#version 300 es
4634 precision highp float;
4635 layout (std140) uniform C {
4636 float u;
4637 float v;
4638 };
4639 out vec4 o;
4640 void main() {
4641 vec2 z = vec2(1.0 - u, v);
4642 vec2 b = vec2((z=z, u)); // Being tested.
4643 o = vec4(b.x, z.x, b.x, 1.0);
4644 })";
4645 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4646 glUseProgram(program);
4647
4648 constexpr GLfloat kInput1Data[2] = {1.f, 0.f};
4649 GLBuffer input1;
4650 glBindBuffer(GL_UNIFORM_BUFFER, input1);
4651 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat) * 2, &kInput1Data, GL_STATIC_COPY);
4652 const GLuint kInput1Index = glGetUniformBlockIndex(program, "C");
4653 glUniformBlockBinding(program, kInput1Index, 1);
4654 glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
4655 glBindBuffer(GL_UNIFORM_BUFFER, 0);
4656 ASSERT_GL_NO_ERROR();
4657
4658 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4659 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4660 ASSERT_GL_NO_ERROR();
4661 }
4662
4663 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4664 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4665 {
4666 // Crashes on an assertion. The driver reports no atomic counter buffers when queried from the
4667 // program, but ANGLE believes there to be one.
4668 //
4669 // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4670 // the code on which .length() is being called:
4671 //
4672 // _uac1[(_uvalue = _utestSideEffectValue)];
4673 //
4674 // The driver is optimizing the subscription out, and calling the atomic counter inactive. This
4675 // was observed on nvidia, mesa and amd/windows.
4676 //
4677 // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4678 // driver says don't.
4679 //
4680 // http://anglebug.com/42262426
4681 ANGLE_SKIP_TEST_IF(IsOpenGL());
4682
4683 constexpr char kCS[] = R"(#version 310 es
4684 precision mediump float;
4685 layout(local_size_x=1) in;
4686
4687 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4688 uniform uint testSideEffectValue;
4689
4690 layout(binding = 1, std140) buffer Result
4691 {
4692 uint value;
4693 } result;
4694
4695 void main() {
4696 bool passed = true;
4697 if (ac1.length() != 2)
4698 {
4699 passed = false;
4700 }
4701 uint value = 0u;
4702 if (ac1[value = testSideEffectValue].length() != 3)
4703 {
4704 passed = false;
4705 }
4706 if (value != testSideEffectValue)
4707 {
4708 passed = false;
4709 }
4710 if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4711 {
4712 passed = false;
4713 }
4714 if (value != testSideEffectValue + 1u)
4715 {
4716 passed = false;
4717 }
4718 result.value = passed ? 255u : 127u;
4719 })";
4720
4721 constexpr unsigned int kUniformTestValue = 17;
4722 constexpr unsigned int kExpectedSuccessValue = 255;
4723 constexpr unsigned int kAtomicCounterRows = 2;
4724 constexpr unsigned int kAtomicCounterCols = 3;
4725
4726 GLint maxAtomicCounters = 0;
4727 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4728 EXPECT_GL_NO_ERROR();
4729
4730 // Required minimum is 8 by the spec
4731 EXPECT_GE(maxAtomicCounters, 8);
4732 ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4733 kAtomicCounterRows * kAtomicCounterCols);
4734
4735 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4736 glUseProgram(program);
4737
4738 constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4739 GLBuffer atomicCounterBuffer;
4740 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4741 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4742 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4743
4744 constexpr unsigned int kOutputInitValue = 0;
4745 GLBuffer shaderStorageBuffer;
4746 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4747 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4748 GL_STATIC_DRAW);
4749 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4750
4751 GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4752 EXPECT_NE(uniformLocation, -1);
4753 glUniform1ui(uniformLocation, kUniformTestValue);
4754 EXPECT_GL_NO_ERROR();
4755
4756 glDispatchCompute(1, 1, 1);
4757
4758 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4759
4760 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4761 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4762 EXPECT_EQ(*ptr, kExpectedSuccessValue);
4763 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4764 }
4765
4766 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4767 TEST_P(GLSLTest_ES31, InactiveImages)
4768 {
4769 ANGLE_SKIP_TEST_IF(IsD3D11());
4770
4771 constexpr char kCS[] = R"(#version 310 es
4772 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4773 layout(rgba32ui) uniform highp readonly uimage2D image1;
4774 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4775 void main()
4776 {
4777 })";
4778
4779 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4780
4781 glUseProgram(program);
4782 glDispatchCompute(1, 1, 1);
4783 EXPECT_GL_NO_ERROR();
4784
4785 // Verify that the images are indeed inactive.
4786 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4787 EXPECT_GL_NO_ERROR();
4788 EXPECT_EQ(GL_INVALID_INDEX, index);
4789
4790 index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4791 EXPECT_GL_NO_ERROR();
4792 EXPECT_EQ(GL_INVALID_INDEX, index);
4793 }
4794
4795 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4796 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4797 {
4798 constexpr char kCS[] = R"(#version 310 es
4799 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4800 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4801 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4802 void main()
4803 {
4804 })";
4805
4806 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4807
4808 glUseProgram(program);
4809 glDispatchCompute(1, 1, 1);
4810 EXPECT_GL_NO_ERROR();
4811
4812 // Verify that the atomic counters are indeed inactive.
4813 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4814 EXPECT_GL_NO_ERROR();
4815 EXPECT_EQ(GL_INVALID_INDEX, index);
4816
4817 index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4818 EXPECT_GL_NO_ERROR();
4819 EXPECT_EQ(GL_INVALID_INDEX, index);
4820 }
4821
4822 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4823 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4824 {
4825 constexpr char kCS[] = R"(#version 310 es
4826 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4827 struct S
4828 {
4829 vec4 v;
4830 sampler2D t[10];
4831 };
4832 uniform S s;
4833 void main()
4834 {
4835 })";
4836
4837 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4838
4839 glUseProgram(program);
4840 glDispatchCompute(1, 1, 1);
4841 EXPECT_GL_NO_ERROR();
4842 }
4843
4844 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4845 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4846 {
4847 constexpr char kFS[] =
4848 "#version 310 es\n"
4849 "precision mediump float;\n"
4850 "out vec4 my_FragColor;\n"
4851 "uniform ivec2 test[2][2];\n"
4852 "void main() {\n"
4853 " bool passed = true;\n"
4854 " for (int i = 0; i < 2; i++) {\n"
4855 " for (int j = 0; j < 2; j++) {\n"
4856 " if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4857 " passed = false;\n"
4858 " }\n"
4859 " }\n"
4860 " }\n"
4861 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4862 "}\n";
4863
4864 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4865 glUseProgram(program);
4866 for (int i = 0; i < 2; i++)
4867 {
4868 for (int j = 0; j < 2; j++)
4869 {
4870 std::stringstream uniformName;
4871 uniformName << "test[" << i << "][" << j << "]";
4872 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4873 // All array indices should be used.
4874 EXPECT_NE(uniformLocation, -1);
4875 glUniform2i(uniformLocation, i + 1, j + 1);
4876 }
4877 }
4878 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4879 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4880 }
4881
4882 // Test that array indices for arrays of arrays of basic types work as expected
4883 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4884 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4885 {
4886 // anglebug.com/42262465 - fails on AMD Windows
4887 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4888 constexpr char kFS[] =
4889 "#version 310 es\n"
4890 "precision mediump float;\n"
4891 "out vec4 my_FragColor;\n"
4892 "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4893 "void main() {\n"
4894 " bool passed = true;\n"
4895 " for (int i = 0; i < 2; i++) {\n"
4896 " for (int j = 0; j < 2; j++) {\n"
4897 " if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4898 " passed = false;\n"
4899 " }\n"
4900 " }\n"
4901 " }\n"
4902 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4903 "}\n";
4904
4905 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4906 glUseProgram(program);
4907 // Use interface queries to determine buffer size and offset
4908 GLuint uboBlockIndex = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "UBO");
4909 GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4910 GLint uboDataSize;
4911 glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4912 nullptr, &uboDataSize);
4913 std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4914 for (int i = 0; i < 2; i++)
4915 {
4916 std::stringstream resourceName;
4917 resourceName << "UBO.test[" << i << "][0]";
4918 GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4919 struct
4920 {
4921 GLint stride;
4922 GLint offset;
4923 } values;
4924 GLuint resourceIndex =
4925 glGetProgramResourceIndex(program, GL_UNIFORM, resourceName.str().c_str());
4926 ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4927 glGetProgramResourceiv(program, GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2, nullptr,
4928 &values.stride);
4929 for (int j = 0; j < 2; j++)
4930 {
4931 GLint(&dataPtr)[2] =
4932 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4933 dataPtr[0] = i + 1;
4934 dataPtr[1] = j + 1;
4935 }
4936 }
4937 GLBuffer ubo;
4938 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
4939 glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4940 GLuint ubo_index = glGetUniformBlockIndex(program, "UBO");
4941 ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4942 glUniformBlockBinding(program, ubo_index, 5);
4943 glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo);
4944 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4945 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4946 }
4947
4948 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4949 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4950 {
4951 constexpr char kFS[] =
4952 "#version 310 es\n"
4953 "precision mediump float;\n"
4954 "out vec4 my_FragColor;\n"
4955 "uniform mediump isampler2D test[2][2];\n"
4956 "void main() {\n"
4957 " bool passed = true;\n"
4958 "#define DO_CHECK(i,j) \\\n"
4959 " if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4960 " passed = false; \\\n"
4961 " }\n"
4962 " DO_CHECK(0, 0)\n"
4963 " DO_CHECK(0, 1)\n"
4964 " DO_CHECK(1, 0)\n"
4965 " DO_CHECK(1, 1)\n"
4966 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4967 "}\n";
4968
4969 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4970 glUseProgram(program);
4971 GLTexture textures[2][2];
4972 for (int i = 0; i < 2; i++)
4973 {
4974 for (int j = 0; j < 2; j++)
4975 {
4976 // First generate the texture
4977 int textureUnit = i * 2 + j;
4978 glActiveTexture(GL_TEXTURE0 + textureUnit);
4979 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4980 GLint texData[2] = {i + 1, j + 1};
4981 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4983 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4984 // Then send it as a uniform
4985 std::stringstream uniformName;
4986 uniformName << "test[" << i << "][" << j << "]";
4987 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4988 // All array indices should be used.
4989 EXPECT_NE(uniformLocation, -1);
4990 glUniform1i(uniformLocation, textureUnit);
4991 }
4992 }
4993 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4994 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4995 }
4996
4997 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4998 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4999 {
5000 // http://anglebug.com/42263641
5001 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5002
5003 // Fails on D3D due to mistranslation.
5004 ANGLE_SKIP_TEST_IF(IsD3D());
5005
5006 // Fails on Android on GLES.
5007 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5008
5009 GLint maxTextures, maxComputeImageUniforms;
5010 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
5011 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5012 ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
5013 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
5014
5015 constexpr char kComputeShader[] = R"(#version 310 es
5016 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5017 layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
5018 layout(binding = 1, std430) buffer Output {
5019 uint image_value;
5020 } outbuf;
5021
5022 void main(void)
5023 {
5024 outbuf.image_value = uint(0.0);
5025 outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
5026 outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
5027 outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
5028 outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
5029 outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
5030 outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
5031 })";
5032 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5033 EXPECT_GL_NO_ERROR();
5034
5035 glUseProgram(program);
5036
5037 GLuint outputInitData[1] = {10};
5038 GLBuffer outputBuffer;
5039 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5040 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
5041 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
5042 EXPECT_GL_NO_ERROR();
5043
5044 GLuint imageData = 200u;
5045 GLTexture images[1][2][3];
5046 for (int i = 0; i < 1; i++)
5047 {
5048 for (int j = 0; j < 2; j++)
5049 {
5050 for (int k = 0; k < 3; k++)
5051 {
5052 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
5053 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5054 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5055 &imageData);
5056 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
5057 GL_R32UI);
5058 EXPECT_GL_NO_ERROR();
5059 }
5060 }
5061 }
5062
5063 glDispatchCompute(1, 1, 1);
5064 EXPECT_GL_NO_ERROR();
5065
5066 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5067
5068 // read back
5069 const GLuint *ptr = reinterpret_cast<const GLuint *>(
5070 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
5071 memcpy(outputInitData, ptr, sizeof(outputInitData));
5072 EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
5073 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5074 }
5075
5076 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)5077 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
5078 {
5079 // http://anglebug.com/42263641
5080 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5081
5082 // Fails on D3D due to mistranslation.
5083 ANGLE_SKIP_TEST_IF(IsD3D());
5084
5085 constexpr GLsizei kImage1Layers = 3;
5086 constexpr GLsizei kImage1Rows = 2;
5087 constexpr GLsizei kImage1Cols = 1;
5088 constexpr GLsizei kImage2Rows = 2;
5089 constexpr GLsizei kImage2Cols = 4;
5090
5091 constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
5092 constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
5093 constexpr GLsizei kImage3Units = 1;
5094
5095 constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
5096
5097 GLint maxTextures, maxComputeImageUniforms;
5098 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
5099 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5100 ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
5101 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
5102
5103 constexpr char kComputeShader[] = R"(#version 310 es
5104 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5105 layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
5106 layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
5107 layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
5108 layout(binding = 0, std430) buffer Output {
5109 uint image_value;
5110 } outbuf;
5111
5112 void main(void)
5113 {
5114 outbuf.image_value = uint(0.0);
5115
5116 outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
5117 outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
5118 outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
5119 outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
5120 outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
5121 outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
5122
5123 outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
5124 outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
5125 outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
5126 outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
5127 outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
5128 outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
5129 outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
5130 outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
5131
5132 outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
5133 })";
5134 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5135 EXPECT_GL_NO_ERROR();
5136
5137 glUseProgram(program);
5138
5139 constexpr GLuint kOutputInitData = 10;
5140 GLBuffer outputBuffer;
5141 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5142 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
5143 GL_STATIC_DRAW);
5144 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5145 EXPECT_GL_NO_ERROR();
5146
5147 constexpr GLsizei kImage1Binding = 0;
5148 constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
5149 constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
5150
5151 constexpr GLuint kImage1Data = 13;
5152 GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
5153 for (int layer = 0; layer < kImage1Layers; layer++)
5154 {
5155 for (int row = 0; row < kImage1Rows; row++)
5156 {
5157 for (int col = 0; col < kImage1Cols; col++)
5158 {
5159 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
5160 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5161 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5162 &kImage1Data);
5163 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
5164 images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
5165 GL_R32UI);
5166 EXPECT_GL_NO_ERROR();
5167 }
5168 }
5169 }
5170
5171 constexpr GLuint kImage2Data = 17;
5172 GLTexture images2[kImage2Rows][kImage2Cols];
5173 for (int row = 0; row < kImage2Rows; row++)
5174 {
5175 for (int col = 0; col < kImage2Cols; col++)
5176 {
5177 glBindTexture(GL_TEXTURE_2D, images2[row][col]);
5178 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5179 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5180 &kImage2Data);
5181 glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
5182 GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5183 EXPECT_GL_NO_ERROR();
5184 }
5185 }
5186
5187 constexpr GLuint kImage3Data = 19;
5188 GLTexture image3;
5189 glBindTexture(GL_TEXTURE_2D, image3);
5190 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5191 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
5192 glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5193 EXPECT_GL_NO_ERROR();
5194
5195 glDispatchCompute(1, 1, 1);
5196 EXPECT_GL_NO_ERROR();
5197
5198 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5199
5200 // read back
5201 const GLuint *ptr = reinterpret_cast<const GLuint *>(
5202 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5203 EXPECT_EQ(*ptr,
5204 kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
5205 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5206 }
5207
5208 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)5209 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
5210 {
5211 // Skip if GL_OES_shader_image_atomic is not enabled.
5212 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
5213
5214 // http://anglebug.com/42263641
5215 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5216
5217 // Fails on D3D due to mistranslation.
5218 ANGLE_SKIP_TEST_IF(IsD3D());
5219
5220 // Fails on Android on GLES.
5221 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5222
5223 // http://anglebug.com/42263895
5224 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
5225
5226 GLint maxComputeImageUniforms;
5227 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5228 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
5229
5230 constexpr char kComputeShader[] = R"(#version 310 es
5231 #extension GL_OES_shader_image_atomic : require
5232
5233 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5234 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
5235 layout(binding = 6, r32f) uniform highp image2D image2;
5236
5237 void testFunction(highp image2D imageOut[2][3])
5238 {
5239 // image1 is an array of 1x1 images.
5240 // image2 is a 1x4 image with the following data:
5241 //
5242 // (0, 0): 234.5
5243 // (0, 1): 4.0
5244 // (0, 2): 456.0
5245 // (0, 3): 987.0
5246
5247
5248 // Write to [0][0]
5249 imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
5250
5251 // Write to [0][1]
5252 imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
5253
5254 // Write to [0][2]
5255 imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
5256
5257 // Write to [1][0]
5258 imageStore(imageOut[1][0], ivec2(0,
5259 imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
5260 ), vec4(678.0));
5261
5262 // Write to [1][1]
5263 imageStore(imageOut[1][1], ivec2(0, 0),
5264 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
5265
5266 // Write to [1][2]
5267 imageStore(imageOut[1][2], ivec2(0, 0),
5268 imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
5269 }
5270
5271 void main(void)
5272 {
5273 testFunction(image1);
5274 })";
5275 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5276 EXPECT_GL_NO_ERROR();
5277
5278 glUseProgram(program);
5279
5280 constexpr GLsizei kImageRows = 2;
5281 constexpr GLsizei kImageCols = 3;
5282 constexpr GLfloat kImageData = 0;
5283 GLTexture images[kImageRows][kImageCols];
5284 for (size_t row = 0; row < kImageRows; row++)
5285 {
5286 for (size_t col = 0; col < kImageCols; col++)
5287 {
5288 glBindTexture(GL_TEXTURE_2D, images[row][col]);
5289 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
5290 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
5291 glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
5292 GL_READ_WRITE, GL_R32F);
5293 EXPECT_GL_NO_ERROR();
5294 }
5295 }
5296
5297 constexpr GLsizei kImage2Size = 4;
5298 constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
5299 234.5f,
5300 4.0f,
5301 456.0f,
5302 987.0f,
5303 };
5304 GLTexture image2;
5305 glBindTexture(GL_TEXTURE_2D, image2);
5306 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
5307 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
5308 glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
5309 EXPECT_GL_NO_ERROR();
5310
5311 glDispatchCompute(1, 1, 1);
5312 EXPECT_GL_NO_ERROR();
5313
5314 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5315
5316 // Verify the previous dispatch with another dispatch
5317 constexpr char kVerifyShader[] = R"(#version 310 es
5318 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5319 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
5320 layout(binding = 6, r32f) uniform highp readonly image2D image2;
5321 layout(binding = 0, std430) buffer Output {
5322 float image2Data[4];
5323 float image1Data[6];
5324 } outbuf;
5325
5326 void main(void)
5327 {
5328 for (int i = 0; i < 4; ++i)
5329 {
5330 outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
5331 }
5332 outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
5333 outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
5334 outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
5335 outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
5336 outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
5337 outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
5338 })";
5339 ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
5340 EXPECT_GL_NO_ERROR();
5341
5342 glUseProgram(verifyProgram);
5343
5344 constexpr std::array<GLfloat, kImage2Size + kImageRows * kImageCols> kOutputInitData = {};
5345 GLBuffer outputBuffer;
5346 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5347 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
5348 GL_STATIC_DRAW);
5349 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5350 EXPECT_GL_NO_ERROR();
5351
5352 glDispatchCompute(1, 1, 1);
5353 EXPECT_GL_NO_ERROR();
5354
5355 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5356
5357 // Verify
5358 const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5359 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5360
5361 EXPECT_EQ(ptr[0], kImage2Data[0]);
5362 EXPECT_EQ(ptr[1], kImage2Data[1]);
5363 EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5364 EXPECT_EQ(ptr[3], kImage2Data[3]);
5365
5366 EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5367 EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5368 EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5369 EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5370 EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5371 EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5372
5373 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5374 }
5375
5376 // Check that imageLoad gives the correct color after clearing the texture -- anglebug.com/42265826
TEST_P(GLSLTest_ES31,ImageLoadAfterClear)5377 TEST_P(GLSLTest_ES31, ImageLoadAfterClear)
5378 {
5379 ANGLE_GL_PROGRAM(program,
5380 R"(#version 310 es
5381 precision highp float;
5382 void main()
5383 {
5384 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5385 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5386 gl_Position.zw = vec2(0, 1);
5387 })",
5388
5389 R"(#version 310 es
5390 precision highp float;
5391 layout(binding=0, rgba8) readonly highp uniform image2D img;
5392 out vec4 fragColor;
5393 void main()
5394 {
5395 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5396 fragColor = vec4(1, 0, 0, 0) + imageLoad(img, imgcoord);
5397 })");
5398 ASSERT_TRUE(program.valid());
5399 glUseProgram(program);
5400
5401 GLTexture tex;
5402 glBindTexture(GL_TEXTURE_2D, tex);
5403 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5404 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5405
5406 // Clear the texture to green.
5407 GLFramebuffer fbo;
5408 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5409 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5410 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5411 glClearColor(0, 1, 0, 1);
5412 glClear(GL_COLOR_BUFFER_BIT);
5413 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
5414
5415 // Draw the texture via imageLoad, plus red, into the main framebuffer. Make sure the texture
5416 // was still green. (green + red == yellow.)
5417 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5418 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5419 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5420
5421 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5422 ASSERT_GL_NO_ERROR();
5423 }
5424
5425 // Check that writeonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,WriteOnlyImage2DAsFunctionArg)5426 TEST_P(GLSLTest_ES31, WriteOnlyImage2DAsFunctionArg)
5427 {
5428 // Create an image.
5429 GLTexture tex;
5430 glBindTexture(GL_TEXTURE_2D, tex);
5431 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5432
5433 // Clear the image to red.
5434 GLFramebuffer fbo;
5435 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5436 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5437 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5438
5439 glClearColor(1, 0, 0, 1);
5440 glClear(GL_COLOR_BUFFER_BIT);
5441 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5442
5443 const char kVS[] = R"(#version 310 es
5444 precision highp float;
5445 void main()
5446 {
5447 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5448 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5449 gl_Position.zw = vec2(0, 1);
5450 })";
5451
5452 const char kFS[] = R"(#version 310 es
5453 precision highp float;
5454 layout(binding=0, rgba8) writeonly highp uniform image2D uniformImage;
5455 void store(writeonly highp image2D img, vec4 color)
5456 {
5457 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5458 imageStore(img, imgcoord, color);
5459 }
5460 void main()
5461 {
5462 store(uniformImage, vec4(1, 1, 0, 1));
5463 })";
5464
5465 // Store yellow to the image.
5466 ANGLE_GL_PROGRAM(program, kVS, kFS);
5467 glUseProgram(program);
5468
5469 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5470 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5471 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5472 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5473
5474 // Check that the image is yellow.
5475 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5476 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5477 ASSERT_GL_NO_ERROR();
5478 }
5479
5480 // Check that readonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,ReadOnlyImage2DAsFunctionArg)5481 TEST_P(GLSLTest_ES31, ReadOnlyImage2DAsFunctionArg)
5482 {
5483 const int w = getWindowWidth();
5484 const int h = getWindowHeight();
5485
5486 // Create an image.
5487 GLTexture tex;
5488 glBindTexture(GL_TEXTURE_2D, tex);
5489 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5490
5491 const std::vector<GLColor> kInitData(w * h, GLColor::red);
5492 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, kInitData.data());
5493
5494 // Create a framebuffer.
5495 GLTexture color;
5496 glBindTexture(GL_TEXTURE_2D, color);
5497 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5498
5499 GLFramebuffer fbo;
5500 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5501 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5502 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5503
5504 // Initialize the framebuffer with the contents of the texture.
5505 glClearColor(0, 0, 0, 0);
5506 glClear(GL_COLOR_BUFFER_BIT);
5507
5508 const char kVS[] = R"(#version 310 es
5509 precision highp float;
5510 void main()
5511 {
5512 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5513 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5514 gl_Position.zw = vec2(0, 1);
5515 })";
5516
5517 const char kFS[] = R"(#version 310 es
5518 precision highp float;
5519 layout(binding=0, rgba8) readonly highp uniform image2D uniformImage;
5520 out vec4 color;
5521 vec4 load(readonly highp image2D img)
5522 {
5523 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5524 return imageLoad(img, imgcoord);
5525 }
5526 void main()
5527 {
5528 color = load(uniformImage);
5529 })";
5530
5531 ANGLE_GL_PROGRAM(program, kVS, kFS);
5532 glUseProgram(program);
5533
5534 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5535 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5536
5537 // Check that the framebuffer is red.
5538 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
5539 ASSERT_GL_NO_ERROR();
5540 }
5541
5542 // Check that the volatile keyword combined with memoryBarrierImage() allow load/store from
5543 // different aliases of the same image -- anglebug.com/42265813
5544 //
5545 // ES 3.1 requires most image formats to be either readonly or writeonly. (It appears that this
5546 // limitation exists due to atomics, since we still have the volatile keyword and the built-in
5547 // memoryBarrierImage(), which ought to allow us to load and store different aliases of the same
5548 // image.) To test this, we create two aliases of the same image -- one for reading and one for
5549 // writing.
TEST_P(GLSLTest_ES31,AliasedLoadStore)5550 TEST_P(GLSLTest_ES31, AliasedLoadStore)
5551 {
5552
5553 GLTexture tex;
5554 glBindTexture(GL_TEXTURE_2D, tex);
5555 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5556
5557 GLFramebuffer fbo;
5558 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5559 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5560 glClearColor(1, 0, 0, 1);
5561 glClear(GL_COLOR_BUFFER_BIT);
5562 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5563
5564 ANGLE_GL_PROGRAM(program,
5565
5566 R"(#version 310 es
5567 precision highp float;
5568 void main()
5569 {
5570 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5571 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5572 gl_Position.zw = vec2(0, 1);
5573 })",
5574
5575 R"(#version 310 es
5576 precision highp float;
5577 layout(binding=0, rgba8) volatile readonly highp uniform image2D img_r;
5578 layout(binding=0, rgba8) volatile writeonly highp uniform image2D img_w;
5579 uniform vec4 drawColor;
5580 void main()
5581 {
5582 ivec2 coord = ivec2(floor(gl_FragCoord.xy));
5583 vec4 oldval = imageLoad(img_r, coord);
5584 memoryBarrierImage();
5585 imageStore(img_w, coord, oldval + drawColor);
5586 })");
5587
5588 ASSERT_TRUE(program.valid());
5589 glUseProgram(program);
5590 GLint drawColorLocation = glGetUniformLocation(program, "drawColor");
5591
5592 // Tell the driver the binding is GL_READ_WRITE, since it will be referenced by two image2Ds:
5593 // one readeonly and one writeonly.
5594 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
5595
5596 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5597 glUniform4f(drawColorLocation, 0, 1, 0, 0);
5598 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5599 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5600
5601 // Ensure the cleared color was loaded before we stored.
5602 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5603 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5604
5605 ASSERT_GL_NO_ERROR();
5606
5607 // Now make two draws to ensure the imageStore is coherent.
5608 glClear(GL_COLOR_BUFFER_BIT);
5609 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5610 glUniform4f(drawColorLocation, 0, 1, 0, 0);
5611 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5612 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5613 glUniform4f(drawColorLocation, 0, 0, 1, 0);
5614 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5615 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5616
5617 // Ensure the first imageStore was loaded by the second imageLoad.
5618 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5619 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
5620
5621 ASSERT_GL_NO_ERROR();
5622 }
5623
5624 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5625 TEST_P(GLSLTest_ES31, StructArraySampler)
5626 {
5627 constexpr char kFS[] =
5628 "#version 310 es\n"
5629 "precision mediump float;\n"
5630 "out vec4 my_FragColor;\n"
5631 "struct Data { mediump sampler2D data[2]; };\n"
5632 "uniform Data test;\n"
5633 "void main() {\n"
5634 " my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5635 " texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5636 "}\n";
5637
5638 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5639 glUseProgram(program);
5640 GLTexture textures[2];
5641 GLColor expected = MakeGLColor(32, 64, 96, 255);
5642 GLubyte data[6] = {}; // Two bytes of padding, so that texture can be initialized with 4 bytes
5643 memcpy(data, expected.data(), sizeof(expected));
5644 for (int i = 0; i < 2; i++)
5645 {
5646 glActiveTexture(GL_TEXTURE0 + i);
5647 glBindTexture(GL_TEXTURE_2D, textures[i]);
5648 // Each element provides two components.
5649 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5650 std::stringstream uniformName;
5651 uniformName << "test.data[" << i << "]";
5652 // Then send it as a uniform
5653 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5654 // The uniform should be active.
5655 EXPECT_NE(uniformLocation, -1);
5656 glUniform1i(uniformLocation, i);
5657 }
5658 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5659 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5660 }
5661
5662 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5663 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5664 {
5665 constexpr char kFS[] =
5666 "#version 310 es\n"
5667 "precision mediump float;\n"
5668 "out vec4 my_FragColor;\n"
5669 "struct Data { mediump isampler2D data[2][2]; };\n"
5670 "uniform Data test;\n"
5671 "void main() {\n"
5672 " bool passed = true;\n"
5673 "#define DO_CHECK(i,j) \\\n"
5674 " if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5675 " passed = false; \\\n"
5676 " }\n"
5677 " DO_CHECK(0, 0)\n"
5678 " DO_CHECK(0, 1)\n"
5679 " DO_CHECK(1, 0)\n"
5680 " DO_CHECK(1, 1)\n"
5681 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5682 "}\n";
5683
5684 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5685 glUseProgram(program);
5686 GLTexture textures[2][2];
5687 for (int i = 0; i < 2; i++)
5688 {
5689 for (int j = 0; j < 2; j++)
5690 {
5691 // First generate the texture
5692 int textureUnit = i * 2 + j;
5693 glActiveTexture(GL_TEXTURE0 + textureUnit);
5694 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5695 GLint texData[2] = {i + 1, j + 1};
5696 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5699 // Then send it as a uniform
5700 std::stringstream uniformName;
5701 uniformName << "test.data[" << i << "][" << j << "]";
5702 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5703 // All array indices should be used.
5704 EXPECT_NE(uniformLocation, -1);
5705 glUniform1i(uniformLocation, textureUnit);
5706 }
5707 }
5708 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5709 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5710 }
5711
5712 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5713 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5714 {
5715 GLint numTextures;
5716 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5717 ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5718 constexpr char kFS[] =
5719 "#version 310 es\n"
5720 "precision mediump float;\n"
5721 "out vec4 my_FragColor;\n"
5722 "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5723 "uniform Data test[2];\n"
5724 "void main() {\n"
5725 " bool passed = true;\n"
5726 "#define DO_CHECK_ikl(i,k,l) \\\n"
5727 " if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5728 " passed = false; \\\n"
5729 " } \\\n"
5730 " if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5731 " passed = false; \\\n"
5732 " }\n"
5733 "#define DO_CHECK_ik(i,k) \\\n"
5734 " DO_CHECK_ikl(i, k, 0) \\\n"
5735 " DO_CHECK_ikl(i, k, 1)\n"
5736 "#define DO_CHECK_i(i) \\\n"
5737 " DO_CHECK_ik(i, 0) \\\n"
5738 " DO_CHECK_ik(i, 1)\n"
5739 " DO_CHECK_i(0)\n"
5740 " DO_CHECK_i(1)\n"
5741 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5742 "}\n";
5743
5744 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5745 glUseProgram(program);
5746 GLTexture textures[2][2][2][2];
5747 for (int i = 0; i < 2; i++)
5748 {
5749 for (int j = 0; j < 2; j++)
5750 {
5751 for (int k = 0; k < 2; k++)
5752 {
5753 for (int l = 0; l < 2; l++)
5754 {
5755 // First generate the texture
5756 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5757 glActiveTexture(GL_TEXTURE0 + textureUnit);
5758 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5759 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5760 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5761 &texData[0]);
5762 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5763 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5764 // Then send it as a uniform
5765 std::stringstream uniformName;
5766 uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5767 GLint uniformLocation =
5768 glGetUniformLocation(program, uniformName.str().c_str());
5769 // All array indices should be used.
5770 EXPECT_NE(uniformLocation, -1);
5771 glUniform1i(uniformLocation, textureUnit);
5772 }
5773 }
5774 }
5775 }
5776 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5777 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5778 }
5779
5780 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5781 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5782 {
5783 GLint numTextures;
5784 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5785 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5786 constexpr char kFS[] =
5787 "#version 310 es\n"
5788 "precision mediump float;\n"
5789 "out vec4 my_FragColor;\n"
5790 "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5791 "uniform Data test[2][3];\n"
5792 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5793 "void main() {\n"
5794 " bool passed = true;\n"
5795 "#define DO_CHECK_INNER0(i,j,l) \\\n"
5796 " if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5797 " passed = false; \\\n"
5798 " }\n"
5799 "#define DO_CHECK_INNER1(i,j,l) \\\n"
5800 " if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5801 " passed = false; \\\n"
5802 " }\n"
5803 "#define DO_CHECK(i,j) \\\n"
5804 " DO_CHECK_INNER0(i, j, 0) \\\n"
5805 " DO_CHECK_INNER0(i, j, 1) \\\n"
5806 " DO_CHECK_INNER1(i, j, 0) \\\n"
5807 " DO_CHECK_INNER1(i, j, 1) \\\n"
5808 " DO_CHECK_INNER1(i, j, 2)\n"
5809 " DO_CHECK(0, 0)\n"
5810 " DO_CHECK(0, 1)\n"
5811 " DO_CHECK(0, 2)\n"
5812 " DO_CHECK(1, 0)\n"
5813 " DO_CHECK(1, 1)\n"
5814 " DO_CHECK(1, 2)\n"
5815 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5816 "}\n";
5817
5818 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5819 glUseProgram(program);
5820 struct Data
5821 {
5822 GLTexture data1[2];
5823 GLTexture data2[3];
5824 };
5825 Data textures[2][3];
5826 for (int i = 0; i < 2; i++)
5827 {
5828 for (int j = 0; j < 3; j++)
5829 {
5830 GLTexture *arrays[] = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5831 size_t arrayLengths[] = {2, 3};
5832 size_t arrayOffsets[] = {0, 2};
5833 size_t totalArrayLength = 5;
5834 for (int k = 0; k < 2; k++)
5835 {
5836 GLTexture *array = arrays[k];
5837 size_t arrayLength = arrayLengths[k];
5838 size_t arrayOffset = arrayOffsets[k];
5839 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5840 {
5841 // First generate the texture
5842 int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5843 glActiveTexture(GL_TEXTURE0 + textureUnit);
5844 glBindTexture(GL_TEXTURE_2D, array[l]);
5845 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5846 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5847 &texData[0]);
5848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5849 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5850 // Then send it as a uniform
5851 std::stringstream uniformName;
5852 uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5853 GLint uniformLocation =
5854 glGetUniformLocation(program, uniformName.str().c_str());
5855 // All array indices should be used.
5856 EXPECT_NE(uniformLocation, -1);
5857 glUniform1i(uniformLocation, textureUnit);
5858 }
5859 }
5860 }
5861 }
5862 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5863 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5864 }
5865
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5866 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5867 {
5868 GLint numTextures;
5869 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5870 ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5871 constexpr char kFS[] =
5872 "#version 310 es\n"
5873 "precision mediump float;\n"
5874 "out vec4 my_FragColor;\n"
5875 "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5876 "uniform Data test[3];\n"
5877 "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5878 "void main() {\n"
5879 " bool passed = true;\n"
5880 "#define DO_CHECK_ik(i,k) \\\n"
5881 " if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5882 " passed = false; \\\n"
5883 " } \\\n"
5884 " if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5885 " passed = false; \\\n"
5886 " }\n"
5887 "#define DO_CHECK_i(i) \\\n"
5888 " DO_CHECK_ik(i, 0) \\\n"
5889 " DO_CHECK_ik(i, 1)\n"
5890 " DO_CHECK_i(0)\n"
5891 " DO_CHECK_i(1)\n"
5892 " DO_CHECK_i(2)\n"
5893 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5894 "}\n";
5895
5896 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5897 glUseProgram(program);
5898 GLTexture textures[3][2][2];
5899 for (int i = 0; i < 3; i++)
5900 {
5901 for (int j = 0; j < 2; j++)
5902 {
5903 for (int k = 0; k < 2; k++)
5904 {
5905 // First generate the texture
5906 int textureUnit = k + 2 * (j + 2 * i);
5907 glActiveTexture(GL_TEXTURE0 + textureUnit);
5908 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5909 GLint texData[4] = {i + 1, j + 1, k + 1, 1};
5910 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5911 static_cast<GLubyte>((j + 1) * 64 - 1),
5912 static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5913 if (j == 0)
5914 {
5915 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5916 &texData[0]);
5917 }
5918 else
5919 {
5920 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5921 &texDataFloat[0]);
5922 }
5923 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5924 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5925 // Then send it as a uniform
5926 std::stringstream uniformName;
5927 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5928 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5929 // All array indices should be used.
5930 EXPECT_NE(uniformLocation, -1);
5931 glUniform1i(uniformLocation, textureUnit);
5932 }
5933 }
5934 }
5935 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5936 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5937 }
5938
5939 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5940 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5941 {
5942 // anglebug.com/42262476 - no sampler array params on Android
5943 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5944
5945 constexpr char kFS[] =
5946 "#version 310 es\n"
5947 "precision mediump float;\n"
5948 "out vec4 my_FragColor;\n"
5949 "uniform mediump isampler2D test[2][3];\n"
5950 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5951 "\n"
5952 "bool check(mediump isampler2D data[2][3]);\n"
5953 "bool check(mediump isampler2D data[2][3]) {\n"
5954 "#define DO_CHECK(i,j) \\\n"
5955 " if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5956 " return false; \\\n"
5957 " }\n"
5958 " DO_CHECK(0, 0)\n"
5959 " DO_CHECK(0, 1)\n"
5960 " DO_CHECK(0, 2)\n"
5961 " DO_CHECK(1, 0)\n"
5962 " DO_CHECK(1, 1)\n"
5963 " DO_CHECK(1, 2)\n"
5964 " return true;\n"
5965 "}\n"
5966 "void main() {\n"
5967 " bool passed = check(test);\n"
5968 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5969 "}\n";
5970
5971 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5972 glUseProgram(program);
5973 GLTexture textures[2][3];
5974 for (int i = 0; i < 2; i++)
5975 {
5976 for (int j = 0; j < 3; j++)
5977 {
5978 // First generate the texture
5979 int textureUnit = i * 3 + j;
5980 glActiveTexture(GL_TEXTURE0 + textureUnit);
5981 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5982 GLint texData[2] = {i + 1, j + 1};
5983 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5984 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5985 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5986 // Then send it as a uniform
5987 std::stringstream uniformName;
5988 uniformName << "test[" << i << "][" << j << "]";
5989 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5990 // All array indices should be used.
5991 EXPECT_NE(uniformLocation, -1);
5992 glUniform1i(uniformLocation, textureUnit);
5993 }
5994 }
5995 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5996 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5997 }
5998
5999 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)6000 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
6001 {
6002 // anglebug.com/42262476 - no sampler array params on Android
6003 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6004
6005 constexpr char kFS[] =
6006 "#version 310 es\n"
6007 "precision mediump float;\n"
6008 "out vec4 my_FragColor;\n"
6009 "struct Data { mediump isampler2D data[2][3]; };\n"
6010 "uniform Data test;\n"
6011 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6012 "\n"
6013 "bool check(Data data) {\n"
6014 "#define DO_CHECK(i,j) \\\n"
6015 " if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
6016 " return false; \\\n"
6017 " }\n"
6018 " DO_CHECK(0, 0)\n"
6019 " DO_CHECK(0, 1)\n"
6020 " DO_CHECK(0, 2)\n"
6021 " DO_CHECK(1, 0)\n"
6022 " DO_CHECK(1, 1)\n"
6023 " DO_CHECK(1, 2)\n"
6024 " return true;\n"
6025 "}\n"
6026 "void main() {\n"
6027 " bool passed = check(test);\n"
6028 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6029 "}\n";
6030
6031 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6032 glUseProgram(program);
6033 GLTexture textures[2][3];
6034 for (int i = 0; i < 2; i++)
6035 {
6036 for (int j = 0; j < 3; j++)
6037 {
6038 // First generate the texture
6039 int textureUnit = i * 3 + j;
6040 glActiveTexture(GL_TEXTURE0 + textureUnit);
6041 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
6042 GLint texData[2] = {i + 1, j + 1};
6043 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
6044 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6045 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6046 // Then send it as a uniform
6047 std::stringstream uniformName;
6048 uniformName << "test.data[" << i << "][" << j << "]";
6049 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6050 // All array indices should be used.
6051 EXPECT_NE(uniformLocation, -1);
6052 glUniform1i(uniformLocation, textureUnit);
6053 }
6054 }
6055 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6056 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6057 }
6058
6059 // Test that arrays of arrays of structs with arrays of arrays of samplers
6060 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)6061 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
6062 {
6063 // anglebug.com/42262476 - no sampler array params on Android
6064 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6065
6066 GLint numTextures;
6067 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6068 ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
6069 constexpr char kFS[] =
6070 "#version 310 es\n"
6071 "precision mediump float;\n"
6072 "out vec4 my_FragColor;\n"
6073 "struct Data { mediump isampler2D data[2][2]; };\n"
6074 "uniform Data test[3][2];\n"
6075 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6076 "\n"
6077 "bool check(Data data[3][2]) {\n"
6078 "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
6079 " if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
6080 " return false; \\\n"
6081 " }\n"
6082 "#define DO_CHECK_ij(i,j) \\\n"
6083 " DO_CHECK_ijkl(i, j, 0, 0) \\\n"
6084 " DO_CHECK_ijkl(i, j, 0, 1) \\\n"
6085 " DO_CHECK_ijkl(i, j, 1, 0) \\\n"
6086 " DO_CHECK_ijkl(i, j, 1, 1)\n"
6087 " DO_CHECK_ij(0, 0)\n"
6088 " DO_CHECK_ij(1, 0)\n"
6089 " DO_CHECK_ij(2, 0)\n"
6090 " DO_CHECK_ij(0, 1)\n"
6091 " DO_CHECK_ij(1, 1)\n"
6092 " DO_CHECK_ij(2, 1)\n"
6093 " return true;\n"
6094 "}\n"
6095 "void main() {\n"
6096 " bool passed = check(test);\n"
6097 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6098 "}\n";
6099
6100 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6101 glUseProgram(program);
6102 GLTexture textures[3][2][2][2];
6103 for (int i = 0; i < 3; i++)
6104 {
6105 for (int j = 0; j < 2; j++)
6106 {
6107 for (int k = 0; k < 2; k++)
6108 {
6109 for (int l = 0; l < 2; l++)
6110 {
6111 // First generate the texture
6112 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
6113 glActiveTexture(GL_TEXTURE0 + textureUnit);
6114 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
6115 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
6116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
6117 &texData[0]);
6118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6120 // Then send it as a uniform
6121 std::stringstream uniformName;
6122 uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
6123 GLint uniformLocation =
6124 glGetUniformLocation(program, uniformName.str().c_str());
6125 // All array indices should be used.
6126 EXPECT_NE(uniformLocation, -1);
6127 glUniform1i(uniformLocation, textureUnit);
6128 }
6129 }
6130 }
6131 }
6132 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6133 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6134 }
6135
6136 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)6137 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
6138 {
6139 GLint numTextures;
6140 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6141 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
6142
6143 // anglebug.com/42262476 - no sampler array params on Android
6144 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6145
6146 // http://anglebug.com/42264082
6147 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
6148
6149 constexpr char kFS[] =
6150 "#version 310 es\n"
6151 "precision mediump float;\n"
6152 "out vec4 my_FragColor;\n"
6153 "uniform mediump isampler2D test[2][3][4];\n"
6154 "uniform mediump isampler2D test2[4];\n"
6155 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6156 "\n"
6157 "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
6158 " if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
6159 " if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
6160 " if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
6161 " if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
6162 " return true;\n"
6163 "}\n"
6164 "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
6165 " if (!check1D(arr[0], x, 0)) return false;\n"
6166 " if (!check1D(arr[1], x, 1)) return false;\n"
6167 " if (!check1D(arr[2], x, 2)) return false;\n"
6168 " return true;\n"
6169 "}\n"
6170 "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
6171 " if (!check2D(arr[0], 0)) return false;\n"
6172 " if (!check2D(arr[1], 1)) return false;\n"
6173 " return true;\n"
6174 "}\n"
6175 "void main() {\n"
6176 " bool passed = check3D(test) && check1D(test2, 7, 8);\n"
6177 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6178 "}\n";
6179
6180 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6181 glUseProgram(program);
6182 GLTexture textures1[2][3][4];
6183 GLTexture textures2[4];
6184 for (int i = 0; i < 2; i++)
6185 {
6186 for (int j = 0; j < 3; j++)
6187 {
6188 for (int k = 0; k < 4; k++)
6189 {
6190 // First generate the texture
6191 int textureUnit = k + 4 * (j + 3 * i);
6192 glActiveTexture(GL_TEXTURE0 + textureUnit);
6193 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
6194 GLint texData[3] = {i + 1, j + 1, k + 1};
6195 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
6196 &texData[0]);
6197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6199 // Then send it as a uniform
6200 std::stringstream uniformName;
6201 uniformName << "test[" << i << "][" << j << "][" << k << "]";
6202 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6203 // All array indices should be used.
6204 EXPECT_NE(uniformLocation, -1);
6205 glUniform1i(uniformLocation, textureUnit);
6206 }
6207 }
6208 }
6209 for (int k = 0; k < 4; k++)
6210 {
6211 // First generate the texture
6212 int textureUnit = 2 * 3 * 4 + k;
6213 glActiveTexture(GL_TEXTURE0 + textureUnit);
6214 glBindTexture(GL_TEXTURE_2D, textures2[k]);
6215 GLint texData[3] = {7 + 1, 8 + 1, k + 1};
6216 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
6217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6219 // Then send it as a uniform
6220 std::stringstream uniformName;
6221 uniformName << "test2[" << k << "]";
6222 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6223 // All array indices should be used.
6224 EXPECT_NE(uniformLocation, -1);
6225 glUniform1i(uniformLocation, textureUnit);
6226 }
6227 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6228 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6229 }
6230
6231 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)6232 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
6233 {
6234 ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/42262269 - rewriter can create name collisions
6235 GLint numTextures;
6236 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6237 ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
6238 // anglebug.com/42262476 - no sampler array params on Android
6239 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6240 constexpr char kFS[] =
6241 "#version 310 es\n"
6242 "precision mediump sampler2D;\n"
6243 "precision mediump float;\n"
6244 "uniform sampler2D test_field1_field2[2][2];\n"
6245 "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
6246 "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
6247 "vec4 func1(sampler2D param_field1_field2[2][2],\n"
6248 " int param_field1_field2_offset,\n"
6249 " S1 param_field1,\n"
6250 " S2 param) {\n"
6251 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
6252 "}\n"
6253 "out vec4 my_FragColor;\n"
6254 "void main() {\n"
6255 " my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
6256 " my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
6257 " vec2 uv = vec2(0.0);\n"
6258 " my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
6259 " texture(test_field1.field2[0][0], uv) +\n"
6260 " texture(test.field1_field2[0][0], uv);\n"
6261 "}\n";
6262 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6263 glActiveTexture(GL_TEXTURE0);
6264 GLTexture tex;
6265 glBindTexture(GL_TEXTURE_2D, tex);
6266 GLint zero = 0;
6267 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6268 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6269 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6270 }
6271
6272 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)6273 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
6274 {
6275 constexpr char kFS[] =
6276 "#version 310 es\n"
6277 "precision mediump sampler2D;\n"
6278 "precision mediump float;\n"
6279 "uniform sampler2D sampler_array[2][2];\n"
6280 "uniform int array[3][2];\n"
6281 "vec4 func1(int param[2],\n"
6282 " int param2[3]) {\n"
6283 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
6284 "}\n"
6285 "out vec4 my_FragColor;\n"
6286 "void main() {\n"
6287 " my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
6288 " my_FragColor += func1(array[1], int[](1, 2, 3));\n"
6289 "}\n";
6290 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6291 glActiveTexture(GL_TEXTURE0);
6292 GLTexture tex;
6293 glBindTexture(GL_TEXTURE_2D, tex);
6294 GLint zero = 0;
6295 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6296 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6297 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6298 }
6299
6300 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
6301 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)6302 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
6303 {
6304 // This seems to be bugged on some version of Android. Might not affect the newest versions.
6305 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
6306 // Test skipped on Android because of bug with Nexus 5X.
6307 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6308
6309 constexpr char kVS[] =
6310 "#version 300 es\n"
6311 "out vec2 texCoord;\n"
6312 "in vec2 position;\n"
6313 "void main()\n"
6314 "{\n"
6315 " gl_Position = vec4(position, 0, 1);\n"
6316 " texCoord = position * 0.5 + vec2(0.5);\n"
6317 "}\n";
6318
6319 constexpr char kSimpleFS[] =
6320 "#version 300 es\n"
6321 "in mediump vec2 texCoord;\n"
6322 "out mediump vec4 fragColor;\n"
6323 "void main()\n"
6324 "{\n"
6325 " fragColor = vec4(texCoord, 0, 1);\n"
6326 "}\n";
6327
6328 constexpr char kNestedFS[] =
6329 "#version 300 es\n"
6330 "uniform mediump sampler2D samplerA;\n"
6331 "uniform mediump sampler2D samplerB;\n"
6332 "in mediump vec2 texCoord;\n"
6333 "out mediump vec4 fragColor;\n"
6334 "void main ()\n"
6335 "{\n"
6336 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
6337 "}\n";
6338
6339 ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
6340 ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
6341
6342 // Initialize a first texture with default texCoord data.
6343 GLTexture texA;
6344 glActiveTexture(GL_TEXTURE0);
6345 glBindTexture(GL_TEXTURE_2D, texA);
6346 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6347 GL_UNSIGNED_BYTE, nullptr);
6348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6350
6351 GLFramebuffer fbo;
6352 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6353 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
6354
6355 drawQuad(initProg, "position", 0.5f);
6356 ASSERT_GL_NO_ERROR();
6357
6358 // Initialize a second texture with a simple color pattern.
6359 GLTexture texB;
6360 glActiveTexture(GL_TEXTURE1);
6361 glBindTexture(GL_TEXTURE_2D, texB);
6362
6363 std::array<GLColor, 4> simpleColors = {
6364 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6365 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6366 simpleColors.data());
6367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6369
6370 // Draw with the nested program, using the first texture to index the second.
6371 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6372 glUseProgram(nestedProg);
6373 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
6374 ASSERT_NE(-1, samplerALoc);
6375 glUniform1i(samplerALoc, 0);
6376 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
6377 ASSERT_NE(-1, samplerBLoc);
6378 glUniform1i(samplerBLoc, 1);
6379
6380 drawQuad(nestedProg, "position", 0.5f);
6381 ASSERT_GL_NO_ERROR();
6382
6383 // Compute four texel centers.
6384 Vector2 windowSize(getWindowWidth(), getWindowHeight());
6385 Vector2 quarterWindowSize = windowSize / 4;
6386 Vector2 ul = quarterWindowSize;
6387 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
6388 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
6389 Vector2 lr = windowSize - quarterWindowSize;
6390
6391 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
6392 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
6393 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
6394 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
6395 }
6396
6397 // Tests that using a constant declaration as the only statement in a for loop without curly braces
6398 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)6399 TEST_P(GLSLTest, ConstantStatementInForLoop)
6400 {
6401 constexpr char kVS[] =
6402 "void main()\n"
6403 "{\n"
6404 " for (int i = 0; i < 10; ++i)\n"
6405 " const int b = 0;\n"
6406 "}\n";
6407
6408 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6409 EXPECT_NE(0u, shader);
6410 glDeleteShader(shader);
6411 }
6412
6413 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
6414 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)6415 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
6416 {
6417 constexpr char kVS[] =
6418 "void main()\n"
6419 "{\n"
6420 " for (const int i = 0; i < 0;) {}\n"
6421 "}\n";
6422
6423 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6424 EXPECT_NE(0u, shader);
6425 glDeleteShader(shader);
6426 }
6427
6428 // Tests that using a constant condition guarding a discard works
6429 // Covers a failing case in the Vulkan backend: http://anglebug.com/42265506
TEST_P(GLSLTest_ES3,ConstantConditionGuardingDiscard)6430 TEST_P(GLSLTest_ES3, ConstantConditionGuardingDiscard)
6431 {
6432 constexpr char kFS[] = R"(#version 300 es
6433 void main()
6434 {
6435 if (true)
6436 {
6437 discard;
6438 }
6439 })";
6440
6441 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6442 EXPECT_NE(0u, shader);
6443 glDeleteShader(shader);
6444 }
6445
6446 // Tests that nesting a discard in unconditional blocks works
6447 // Covers a failing case in the Vulkan backend: http://anglebug.com/42265506
TEST_P(GLSLTest_ES3,NestedUnconditionalDiscards)6448 TEST_P(GLSLTest_ES3, NestedUnconditionalDiscards)
6449 {
6450 constexpr char kFS[] = R"(#version 300 es
6451 out mediump vec4 c;
6452 void main()
6453 {
6454 {
6455 c = vec4(0);
6456 {
6457 discard;
6458 }
6459 }
6460 })";
6461
6462 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6463 EXPECT_NE(0u, shader);
6464 glDeleteShader(shader);
6465 }
6466
6467 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)6468 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
6469 {
6470 // Test skipped on Android GLES because local variable initialization is disabled.
6471 // http://anglebug.com/40096454
6472 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6473
6474 constexpr char kFS[] =
6475 "#version 300 es\n"
6476 "precision mediump float;\n"
6477 "out vec4 my_FragColor;\n"
6478 "int result = 0;\n"
6479 "void main()\n"
6480 "{\n"
6481 " int u;\n"
6482 " result += u;\n"
6483 " int k = 0;\n"
6484 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
6485 " {\n"
6486 " result += j;\n"
6487 " }\n"
6488 " if (result == 2)\n"
6489 " {\n"
6490 " my_FragColor = vec4(0, 1, 0, 1);\n"
6491 " }\n"
6492 " else\n"
6493 " {\n"
6494 " my_FragColor = vec4(1, 0, 0, 1);\n"
6495 " }\n"
6496 "}\n";
6497
6498 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6499
6500 // [WebGL 1.0]
6501 // DrawArrays or drawElements will generate an INVALID_OPERATION error
6502 // if a vertex attribute is enabled as an array via enableVertexAttribArray
6503 // but no buffer is bound to that attribute.
6504 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6505 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6506 }
6507
6508 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
6509 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)6510 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
6511 {
6512 // Test skipped on Android GLES because local variable initialization is disabled.
6513 // http://anglebug.com/40096454
6514 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6515
6516 constexpr char kFS[] =
6517 "precision mediump float;\n"
6518 "struct T\n"
6519 "{\n"
6520 " int a[2];\n"
6521 "};\n"
6522 "struct S\n"
6523 "{\n"
6524 " T t[2];\n"
6525 "};\n"
6526 "void main()\n"
6527 "{\n"
6528 " S s;\n"
6529 " S s2;\n"
6530 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
6531 " {\n"
6532 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6533 " }\n"
6534 " else\n"
6535 " {\n"
6536 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6537 " }\n"
6538 "}\n";
6539
6540 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6541 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6542 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6543 }
6544
6545 // Verify that two shaders with the same uniform name and members but different structure names will
6546 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)6547 TEST_P(GLSLTest, StructureNameMatchingTest)
6548 {
6549 const char *vsSource =
6550 "// Structures must have the same name, sequence of type names, and\n"
6551 "// type definitions, and field names to be considered the same type.\n"
6552 "// GLSL 1.017 4.2.4\n"
6553 "precision mediump float;\n"
6554 "struct info {\n"
6555 " vec4 pos;\n"
6556 " vec4 color;\n"
6557 "};\n"
6558 "\n"
6559 "uniform info uni;\n"
6560 "void main()\n"
6561 "{\n"
6562 " gl_Position = uni.pos;\n"
6563 "}\n";
6564
6565 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
6566 ASSERT_NE(0u, vs);
6567 glDeleteShader(vs);
6568
6569 const char *fsSource =
6570 "// Structures must have the same name, sequence of type names, and\n"
6571 "// type definitions, and field names to be considered the same type.\n"
6572 "// GLSL 1.017 4.2.4\n"
6573 "precision mediump float;\n"
6574 "struct info1 {\n"
6575 " vec4 pos;\n"
6576 " vec4 color;\n"
6577 "};\n"
6578 "\n"
6579 "uniform info1 uni;\n"
6580 "void main()\n"
6581 "{\n"
6582 " gl_FragColor = uni.color;\n"
6583 "}\n";
6584
6585 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
6586 ASSERT_NE(0u, fs);
6587 glDeleteShader(fs);
6588
6589 GLuint program = CompileProgram(vsSource, fsSource);
6590 EXPECT_EQ(0u, program);
6591 }
6592
6593 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)6594 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
6595 {
6596 // Test skipped on Android GLES because local variable initialization is disabled.
6597 // http://anglebug.com/40096454
6598 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6599
6600 constexpr char kFS[] =
6601 "#version 300 es\n"
6602 "precision highp float;\n"
6603 "out vec4 my_FragColor;\n"
6604 "void main()\n"
6605 "{\n"
6606 " my_FragColor = vec4(1, 0, 0, 1);\n"
6607 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
6608 " my_FragColor = vec4(0, 1, 0, 1);\n"
6609 " }\n"
6610 "}\n";
6611
6612 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6613 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6614 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6615 }
6616
6617 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)6618 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
6619 {
6620 // http://anglebug.com/42261561
6621 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6622
6623 constexpr char kFS[] =
6624 "precision mediump float;\n"
6625 "int result;\n"
6626 "int i[2], j = i[0] + 1;\n"
6627 "void main()\n"
6628 "{\n"
6629 " result += j;\n"
6630 " if (result == 1)\n"
6631 " {\n"
6632 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6633 " }\n"
6634 " else\n"
6635 " {\n"
6636 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6637 " }\n"
6638 "}\n";
6639
6640 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6641 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6642 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6643 }
6644
6645 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6646 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6647 {
6648 constexpr char kFS[] =
6649 "precision mediump float;\n"
6650 "struct { float q; } b;\n"
6651 "void main()\n"
6652 "{\n"
6653 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6654 " if (b.q == 0.0)\n"
6655 " {\n"
6656 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6657 " }\n"
6658 "}\n";
6659
6660 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6661 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6662 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6663 }
6664
6665 // Test that uninitialized output arguments are initialized to 0.
TEST_P(WebGL2GLSLTest,InitOutputParams)6666 TEST_P(WebGL2GLSLTest, InitOutputParams)
6667 {
6668 constexpr char kFS[] = R"(#version 300 es
6669 precision mediump float;
6670
6671 struct S { float a; };
6672
6673 out vec4 color;
6674
6675 float f(out float, out vec2 o1, out S o2[2], out float o3[3])
6676 {
6677 float uninitialized_local;
6678
6679 // leave o1 uninitialized
6680 // leave o2 partially uninitialized
6681 o2[0].a = 1.0;
6682
6683 // leave o3 partially uninitialized
6684 o3[1] = 0.5;
6685
6686 return uninitialized_local;
6687 }
6688
6689 void main()
6690 {
6691 float v0 = 345.;
6692 vec2 v1 = vec2(123., 234.);
6693 S v2[2] = S[2](S(-1111.), S(55.));
6694 float v3[3] = float[3](20., 30., 40.);
6695 float v4 = f(v0, v1, v2, v3);
6696
6697 // Everything should be 0 now except for v2[0].a and v3[1] which should be 1.0 and 0.5
6698 // respectively.
6699 color = vec4(v0 + v1.x + v2[0].a + v3[0], // 1.0
6700 v1.y + v2[1].a + v3[1], // 0.5
6701 v3[2] + v4, // 0
6702 1.0);
6703 })";
6704
6705 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6706 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6707 EXPECT_PIXEL_NEAR(0, 0, 255, 127, 0, 255, 1);
6708 }
6709
6710 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6711 TEST_P(GLSLTest, EmbeddedStructUniform)
6712 {
6713 const char kFragmentShader[] = R"(precision mediump float;
6714 uniform struct { float q; } b;
6715 void main()
6716 {
6717 gl_FragColor = vec4(1, 0, 0, 1);
6718 if (b.q == 0.5)
6719 {
6720 gl_FragColor = vec4(0, 1, 0, 1);
6721 }
6722 })";
6723
6724 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6725 glUseProgram(program);
6726 GLint uniLoc = glGetUniformLocation(program, "b.q");
6727 ASSERT_NE(-1, uniLoc);
6728 glUniform1f(uniLoc, 0.5f);
6729
6730 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6731 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6732 }
6733
6734 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6735 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6736 {
6737 const char kFragmentShader[] = R"(precision mediump float;
6738 uniform struct { float q; } b[2];
6739 void main()
6740 {
6741 gl_FragColor = vec4(1, 0, 0, 1);
6742 if (b[0].q == 0.5)
6743 {
6744 gl_FragColor = vec4(0, 1, 0, 1);
6745 }
6746 })";
6747
6748 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6749 glUseProgram(program);
6750 GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6751 ASSERT_NE(-1, uniLoc);
6752 glUniform1f(uniLoc, 0.5f);
6753
6754 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6755 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6756 }
6757
6758 // Test that samplers in structs can be extracted if the first reference to the struct does not
6759 // select an attribute.
TEST_P(GLSLTest,SamplerInStructNoMemberIndexing)6760 TEST_P(GLSLTest, SamplerInStructNoMemberIndexing)
6761 {
6762 constexpr char kVS[] = R"(
6763 uniform struct {
6764 sampler2D n;
6765 vec2 c;
6766 } s;
6767 void main()
6768 {
6769 s;
6770 })";
6771
6772 constexpr char kFS[] = R"(void main()
6773 {
6774 gl_FragColor = vec4(1);
6775 })";
6776
6777 ANGLE_GL_PROGRAM(program, kVS, kFS);
6778 }
6779
6780 // Similar test to SamplerInStructNoMemberIndexing, but the struct variable is an array.
TEST_P(GLSLTest,SamplerInStructArrayNoMemberIndexing)6781 TEST_P(GLSLTest, SamplerInStructArrayNoMemberIndexing)
6782 {
6783 constexpr char kVS[] = R"(
6784 uniform struct
6785 {
6786 sampler2D K;
6787 vec4 c;
6788 } s[6];
6789 void main()
6790 {
6791 s[0];
6792 })";
6793
6794 constexpr char kFS[] = R"(void main()
6795 {
6796 gl_FragColor = vec4(1);
6797 })";
6798
6799 ANGLE_GL_PROGRAM(program, kVS, kFS);
6800 }
6801
6802 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6803 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6804 {
6805 const char kVertexShader[] = R"(attribute vec2 position;
6806 varying vec2 texCoord;
6807 void main()
6808 {
6809 gl_Position = vec4(position, 0, 1);
6810 texCoord = position * 0.5 + vec2(0.5);
6811 })";
6812
6813 const char kFragmentShader[] = R"(precision mediump float;
6814 struct S { sampler2D samp; bool b; };
6815 uniform S uni;
6816 varying vec2 texCoord;
6817 void main()
6818 {
6819 uni;
6820 if (uni.b)
6821 {
6822 gl_FragColor = texture2D(uni.samp, texCoord);
6823 }
6824 else
6825 {
6826 gl_FragColor = vec4(1, 0, 0, 1);
6827 }
6828 })";
6829
6830 ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6831 glUseProgram(program);
6832
6833 GLint bLoc = glGetUniformLocation(program, "uni.b");
6834 ASSERT_NE(-1, bLoc);
6835 GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6836 ASSERT_NE(-1, sampLoc);
6837
6838 glUniform1i(bLoc, 1);
6839
6840 std::array<GLColor, 4> kGreenPixels = {
6841 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6842
6843 GLTexture tex;
6844 glBindTexture(GL_TEXTURE_2D, tex);
6845 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6846 kGreenPixels.data());
6847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6849 ASSERT_GL_NO_ERROR();
6850
6851 drawQuad(program, "position", 0.5f);
6852 ASSERT_GL_NO_ERROR();
6853
6854 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6855 }
6856
6857 // Tests that rewriting samplers in structs works when passed as function argument. In this test,
6858 // the function references another struct, which is not being modified. Regression test for AST
6859 // validation applied to a multipass transformation, where references to declarations were attempted
6860 // to be validated without having the entire shader. In this case, the reference to S2 was flagged
6861 // as invalid because S2's declaration was not visible.
TEST_P(GLSLTest,SamplerInStructAsFunctionArg)6862 TEST_P(GLSLTest, SamplerInStructAsFunctionArg)
6863 {
6864 const char kFS[] = R"(precision mediump float;
6865 struct S { sampler2D samp; bool b; };
6866 struct S2 { float f; };
6867
6868 uniform S us;
6869
6870 float f(S s)
6871 {
6872 S2 s2;
6873 s2.f = float(s.b);
6874 return s2.f;
6875 }
6876
6877 void main()
6878 {
6879 gl_FragColor = vec4(f(us), 0, 0, 1);
6880 })";
6881
6882 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6883 EXPECT_NE(fs, 0u);
6884 ASSERT_GL_NO_ERROR();
6885 }
6886
6887 // Test that structs with samplers are not allowed in interface blocks. This is forbidden per
6888 // GLES3:
6889 //
6890 // > Types and declarators are the same as for other uniform variable declarations outside blocks,
6891 // > with these exceptions:
6892 // > * opaque types are not allowed
TEST_P(GLSLTest_ES3,StructWithSamplersDisallowedInInterfaceBlock)6893 TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock)
6894 {
6895 const char kFS[] = R"(#version 300 es
6896 precision mediump float;
6897 struct S { sampler2D samp; bool b; };
6898
6899 layout(std140) uniform Buffer { S s; } buffer;
6900
6901 out vec4 color;
6902
6903 void main()
6904 {
6905 color = texture(buffer.s.samp, vec2(0));
6906 })";
6907
6908 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6909 EXPECT_EQ(fs, 0u);
6910 ASSERT_GL_NO_ERROR();
6911 }
6912
6913 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6914 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6915 {
6916 const char kFragmentShader[] = R"(precision mediump float;
6917 uniform struct { float q; } b, c;
6918 void main()
6919 {
6920 gl_FragColor = vec4(1, 0, 0, 1);
6921 if (b.q == 0.5 && c.q == 1.0)
6922 {
6923 gl_FragColor = vec4(0, 1, 0, 1);
6924 }
6925 })";
6926
6927 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6928 glUseProgram(program);
6929
6930 GLint uniLocB = glGetUniformLocation(program, "b.q");
6931 ASSERT_NE(-1, uniLocB);
6932 glUniform1f(uniLocB, 0.5f);
6933
6934 GLint uniLocC = glGetUniformLocation(program, "c.q");
6935 ASSERT_NE(-1, uniLocC);
6936 glUniform1f(uniLocC, 1.0f);
6937
6938 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6939 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6940 }
6941
6942 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6943 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6944 {
6945 constexpr char kFS[] =
6946 "#version 300 es\n"
6947 "precision highp float;\n"
6948 "out vec4 my_FragColor;\n"
6949 "void main()\n"
6950 "{\n"
6951 " float i = 0.0;\n"
6952 " while (bool foo = (i < 1.5))\n"
6953 " {\n"
6954 " if (!foo)\n"
6955 " {\n"
6956 " ++i;\n"
6957 " }\n"
6958 " if (i > 3.5)\n"
6959 " {\n"
6960 " break;\n"
6961 " }\n"
6962 " ++i;\n"
6963 " }\n"
6964 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6965 "}\n";
6966
6967 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6968 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
6969 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6970 }
6971
6972 // Test that a variable hides a user-defined function with the same name after its initializer.
6973 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6974 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6975 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6976 {
6977 constexpr char kFS[] =
6978 "precision mediump float;\n"
6979 "uniform vec4 u;\n"
6980 "vec4 foo()\n"
6981 "{\n"
6982 " return u;\n"
6983 "}\n"
6984 "void main()\n"
6985 "{\n"
6986 " vec4 foo = foo();\n"
6987 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6988 "}\n";
6989
6990 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6991 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6992 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6993 }
6994
6995 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6996 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6997 {
6998 constexpr char kFS[] =
6999 "precision mediump float;\n"
7000 "uniform float u_zero;\n"
7001 "struct S { float foo; };\n"
7002 "struct S2 { float foo; };\n"
7003 "float get(S s) { return s.foo + u_zero; }\n"
7004 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
7005 "void main()\n"
7006 "{\n"
7007 " S s;\n"
7008 " s.foo = 0.5;\n"
7009 " S2 s2;\n"
7010 " s2.foo = 0.25;\n"
7011 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
7012 "}\n";
7013
7014 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7015 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7016 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7017 }
7018
7019 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
7020 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)7021 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
7022 {
7023 // http://anglebug.com/42263408
7024 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
7025
7026 constexpr char kVS[] =
7027 "attribute vec4 inputAttribute;\n"
7028 "varying vec4 varColor;\n"
7029 "void main()\n"
7030 "{\n"
7031 " gl_Position = inputAttribute;\n"
7032 "}\n";
7033
7034 constexpr char kFS[] =
7035 "precision mediump float;\n"
7036 "varying vec4 varColor;\n"
7037 "void main()\n"
7038 "{\n"
7039 " gl_FragColor = varColor;\n"
7040 "}\n";
7041
7042 ANGLE_GL_PROGRAM(program, kVS, kFS);
7043 drawQuad(program, "inputAttribute", 0.5f);
7044 ASSERT_GL_NO_ERROR();
7045 }
7046
7047 // Test that a varying struct that's not statically used in the fragment shader works.
7048 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)7049 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
7050 {
7051 constexpr char kVS[] =
7052 "#version 300 es\n"
7053 "struct S {\n"
7054 " vec4 field;\n"
7055 "};\n"
7056 "out S varStruct;\n"
7057 "void main()\n"
7058 "{\n"
7059 " gl_Position = vec4(1.0);\n"
7060 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7061 "}\n";
7062
7063 constexpr char kFS[] =
7064 "#version 300 es\n"
7065 "precision mediump float;\n"
7066 "struct S {\n"
7067 " vec4 field;\n"
7068 "};\n"
7069 "in S varStruct;\n"
7070 "out vec4 col;\n"
7071 "void main()\n"
7072 "{\n"
7073 " col = vec4(1.0);\n"
7074 "}\n";
7075
7076 ANGLE_GL_PROGRAM(program, kVS, kFS);
7077 }
7078
7079 // Test that inactive shader IO block varying are ok.
TEST_P(GLSLTest_ES31,InactiveVaryingIOBlock)7080 TEST_P(GLSLTest_ES31, InactiveVaryingIOBlock)
7081 {
7082 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7083
7084 constexpr char kVS[] =
7085 R"(#version 310 es
7086 #extension GL_EXT_shader_io_blocks : require
7087
7088 precision highp float;
7089 in vec4 inputAttribute;
7090 out Block { vec4 v; };
7091 out Inactive1 { vec4 value; };
7092 out Inactive2 { vec4 value; } named;
7093
7094 void main()
7095 {
7096 gl_Position = inputAttribute;
7097 v = vec4(0);
7098 })";
7099
7100 constexpr char kFS[] =
7101 R"(#version 310 es
7102 #extension GL_EXT_shader_io_blocks : require
7103
7104 precision highp float;
7105
7106 in Block { vec4 v; };
7107 in Inactive3 { vec4 value; };
7108 in Inactive4 { vec4 value; } named2;
7109
7110 layout(location = 0) out mediump vec4 color;
7111 void main()
7112 {
7113 color = vec4(1, v.xy, 1);
7114 })";
7115
7116 ANGLE_GL_PROGRAM(program, kVS, kFS);
7117 drawQuad(program, "inputAttribute", 0.5f);
7118 ASSERT_GL_NO_ERROR();
7119
7120 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7121 }
7122
7123 // Test that a shader IO block varying that's not declared in the fragment shader links
7124 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)7125 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
7126 {
7127 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7128
7129 constexpr char kVS[] =
7130 R"(#version 310 es
7131 #extension GL_EXT_shader_io_blocks : require
7132
7133 precision highp float;
7134 in vec4 inputAttribute;
7135 out Block_inout { vec4 value; } user_out;
7136
7137 void main()
7138 {
7139 gl_Position = inputAttribute;
7140 user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
7141 })";
7142
7143 constexpr char kFS[] =
7144 R"(#version 310 es
7145 #extension GL_EXT_shader_io_blocks : require
7146
7147 precision highp float;
7148 layout(location = 0) out mediump vec4 color;
7149 void main()
7150 {
7151 color = vec4(1, 0, 0, 1);
7152 })";
7153
7154 ANGLE_GL_PROGRAM(program, kVS, kFS);
7155 drawQuad(program, "inputAttribute", 0.5f);
7156 ASSERT_GL_NO_ERROR();
7157
7158 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7159 }
7160
7161 // Test that a shader IO block varying that's not declared in the vertex shader links
7162 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)7163 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
7164 {
7165 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7166
7167 constexpr char kVS[] =
7168 R"(#version 310 es
7169 #extension GL_EXT_shader_io_blocks : require
7170
7171 precision highp float;
7172 in vec4 inputAttribute;
7173
7174 void main()
7175 {
7176 gl_Position = inputAttribute;
7177 })";
7178
7179 constexpr char kFS[] =
7180 R"(#version 310 es
7181 #extension GL_EXT_shader_io_blocks : require
7182
7183 precision highp float;
7184 in Block_inout { vec4 value; } user_in;
7185 layout(location = 0) out mediump vec4 color;
7186
7187 void main()
7188 {
7189 color = vec4(1, 0, 0, 1);
7190 })";
7191
7192 ANGLE_GL_PROGRAM(program, kVS, kFS);
7193 drawQuad(program, "inputAttribute", 0.5f);
7194 ASSERT_GL_NO_ERROR();
7195
7196 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7197 }
7198
7199 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)7200 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
7201 {
7202 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7203 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7204
7205 constexpr char kVS[] =
7206 R"(#version 310 es
7207 #extension GL_OES_shader_multisample_interpolation : require
7208
7209 precision highp float;
7210 in vec4 inputAttribute;
7211
7212 sample out mediump float tc_in;
7213 void main()
7214 {
7215 tc_in = inputAttribute[0];
7216 gl_Position = inputAttribute;
7217 })";
7218
7219 constexpr char kTCS[] =
7220 R"(#version 310 es
7221 #extension GL_EXT_tessellation_shader : require
7222 #extension GL_OES_shader_multisample_interpolation : require
7223 layout (vertices=3) out;
7224
7225 sample in mediump float tc_in[];
7226 sample out mediump float tc_out[];
7227 void main()
7228 {
7229 tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
7230 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7231 gl_TessLevelInner[0] = 2.0;
7232 gl_TessLevelInner[1] = 2.0;
7233 gl_TessLevelOuter[0] = 2.0;
7234 gl_TessLevelOuter[1] = 2.0;
7235 gl_TessLevelOuter[2] = 2.0;
7236 gl_TessLevelOuter[3] = 2.0;
7237 })";
7238
7239 constexpr char kTES[] =
7240 R"(#version 310 es
7241 #extension GL_EXT_tessellation_shader : require
7242 #extension GL_OES_shader_multisample_interpolation : require
7243 layout (triangles) in;
7244
7245 sample in mediump float tc_out[];
7246 sample out mediump float te_out;
7247 void main()
7248 {
7249 te_out = tc_out[2];
7250 gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
7251 })";
7252
7253 constexpr char kFS[] =
7254 R"(#version 310 es
7255 #extension GL_OES_shader_multisample_interpolation : require
7256
7257 precision highp float;
7258 sample in mediump float te_out;
7259 layout(location = 0) out mediump vec4 color;
7260
7261 void main()
7262 {
7263 float out0 = te_out;
7264 color = vec4(1, 0, 0, 1);
7265 })";
7266
7267 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7268 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7269 ASSERT_GL_NO_ERROR();
7270 }
7271
7272 // Test that `smooth sample` and `flat sample` pass the validation.
TEST_P(GLSLTest_ES3,AliasedSampleQualifiers)7273 TEST_P(GLSLTest_ES3, AliasedSampleQualifiers)
7274 {
7275 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7276
7277 constexpr char kVS[] =
7278 R"(#version 300 es
7279 #extension GL_OES_shader_multisample_interpolation : require
7280
7281 smooth sample out mediump float f;
7282 flat sample out mediump int i;
7283 void main()
7284 {
7285 f = 1.0;
7286 i = 1;
7287 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7288 })";
7289
7290 constexpr char kFS[] =
7291 R"(#version 300 es
7292 #extension GL_OES_shader_multisample_interpolation : require
7293
7294 smooth sample in mediump float f;
7295 flat sample in mediump int i;
7296 out mediump vec4 color;
7297 void main()
7298 {
7299 color = vec4(f, float(i), 0, 1);
7300 })";
7301
7302 ANGLE_GL_PROGRAM(program, kVS, kFS);
7303 }
7304
7305 // Test that `noperspective centroid` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveCentroid)7306 TEST_P(GLSLTest_ES3, NoPerspectiveCentroid)
7307 {
7308 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7309
7310 constexpr char kVS[] =
7311 R"(#version 300 es
7312 #extension GL_NV_shader_noperspective_interpolation : require
7313
7314 noperspective centroid out mediump float f;
7315 void main()
7316 {
7317 f = 1.0;
7318 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7319 })";
7320
7321 constexpr char kFS[] =
7322 R"(#version 300 es
7323 #extension GL_NV_shader_noperspective_interpolation : require
7324
7325 noperspective centroid in mediump float f;
7326 out mediump vec4 color;
7327 void main()
7328 {
7329 color = vec4(f, 0.0, 0.0, 1.0);
7330 })";
7331
7332 ANGLE_GL_PROGRAM(program, kVS, kFS);
7333 }
7334
7335 // Test that `noperspective sample` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveSample)7336 TEST_P(GLSLTest_ES3, NoPerspectiveSample)
7337 {
7338 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7339 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7340
7341 constexpr char kVS[] =
7342 R"(#version 300 es
7343 #extension GL_OES_shader_multisample_interpolation : require
7344 #extension GL_NV_shader_noperspective_interpolation : require
7345
7346 noperspective sample out mediump float f;
7347 void main()
7348 {
7349 f = 1.0;
7350 gl_Position = vec4(f, 0.0, 0.0, 1.0);
7351 })";
7352
7353 constexpr char kFS[] =
7354 R"(#version 300 es
7355 #extension GL_OES_shader_multisample_interpolation : require
7356 #extension GL_NV_shader_noperspective_interpolation : require
7357
7358 noperspective sample in mediump float f;
7359 out mediump vec4 color;
7360 void main()
7361 {
7362 color = vec4(f, 0.0, 0.0, 1.0);
7363 })";
7364
7365 ANGLE_GL_PROGRAM(program, kVS, kFS);
7366 }
7367
7368 // Test that a shader with sample in / sample out can be used successfully when the varying
7369 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)7370 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
7371 {
7372 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7373
7374 constexpr char kVS[] =
7375 R"(#version 310 es
7376 #extension GL_OES_shader_multisample_interpolation : require
7377
7378 precision highp float;
7379 in vec4 inputAttribute;
7380
7381 sample out highp float v;
7382 void main()
7383 {
7384 v = inputAttribute[0];
7385 gl_Position = inputAttribute;
7386 })";
7387
7388 constexpr char kFS[] =
7389 R"(#version 310 es
7390 #extension GL_OES_shader_multisample_interpolation : require
7391
7392 precision highp float;
7393 sample in mediump float v;
7394 layout(location = 0) out mediump vec4 color;
7395
7396 void main()
7397 {
7398 color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
7399 })";
7400
7401 ANGLE_GL_PROGRAM(program, kVS, kFS);
7402 drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7403 ASSERT_GL_NO_ERROR();
7404
7405 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
7406 }
7407
7408 // Test that a shader IO block varying whose block name is declared multiple(in/out) time links
7409 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockDeclaredAsInAndOut)7410 TEST_P(GLSLTest_ES31, VaryingIOBlockDeclaredAsInAndOut)
7411 {
7412 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7413 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7414
7415 constexpr char kVS[] = R"(#version 310 es
7416 #extension GL_EXT_shader_io_blocks : require
7417 precision highp float;
7418 in vec4 inputAttribute;
7419 out Vertex
7420 {
7421 vec4 fv;
7422 } outVertex;
7423 void main()
7424 {
7425 gl_Position = inputAttribute;
7426 outVertex.fv = gl_Position;
7427 })";
7428
7429 constexpr char kTCS[] = R"(#version 310 es
7430 #extension GL_EXT_tessellation_shader : require
7431 #extension GL_EXT_shader_io_blocks : require
7432 precision mediump float;
7433 in Vertex
7434 {
7435 vec4 fv;
7436 } inVertex[];
7437 layout(vertices = 2) out;
7438 out Vertex
7439 {
7440 vec4 fv;
7441 } outVertex[];
7442
7443 void main()
7444 {
7445 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7446 outVertex[gl_InvocationID].fv = inVertex[gl_InvocationID].fv;
7447 gl_TessLevelInner[0] = 1.0;
7448 gl_TessLevelInner[1] = 1.0;
7449 gl_TessLevelOuter[0] = 1.0;
7450 gl_TessLevelOuter[1] = 1.0;
7451 gl_TessLevelOuter[2] = 1.0;
7452 gl_TessLevelOuter[3] = 1.0;
7453 })";
7454
7455 constexpr char kTES[] = R"(#version 310 es
7456 #extension GL_EXT_tessellation_shader : require
7457 #extension GL_EXT_shader_io_blocks : require
7458 precision mediump float;
7459 layout (isolines, point_mode) in;
7460 in Vertex
7461 {
7462 vec4 fv;
7463 } inVertex[];
7464 out vec4 result_fv;
7465
7466 void main()
7467 {
7468 gl_Position = gl_in[0].gl_Position;
7469 result_fv = inVertex[0].fv;
7470 })";
7471
7472 constexpr char kFS[] = R"(#version 310 es
7473 precision mediump float;
7474
7475 layout(location = 0) out mediump vec4 color;
7476
7477 void main()
7478 {
7479 // Output solid green
7480 color = vec4(0, 1.0, 0, 1.0);
7481 })";
7482
7483 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7484 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7485 ASSERT_GL_NO_ERROR();
7486 }
7487
testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)7488 void GLSLTest_ES31::testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)
7489 {
7490 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
7491
7492 // Vertex shader
7493 constexpr char kVS[] = R"(#version 310 es
7494 precision highp float;
7495 in vec4 inputAttribute;
7496
7497 void main()
7498 {
7499 gl_Position = inputAttribute;
7500 })";
7501
7502 // Tessellation shaders
7503 constexpr char kGLSLVersion[] = R"(#version 310 es
7504 )";
7505 constexpr char kTessEXT[] = R"(#extension GL_EXT_tessellation_shader : require
7506 )";
7507 constexpr char kTessOES[] = R"(#extension GL_OES_tessellation_shader : require
7508 )";
7509 constexpr char kTexBufEXT[] = R"(#extension GL_EXT_texture_buffer : require
7510 )";
7511 constexpr char kTexBufOES[] = R"(#extension GL_OES_texture_buffer : require
7512 )";
7513
7514 std::string tcs;
7515 std::string tes;
7516
7517 tcs.append(kGLSLVersion);
7518 tes.append(kGLSLVersion);
7519
7520 if (usedExtension == APIExtensionVersion::EXT)
7521 {
7522 tcs.append(kTessEXT);
7523 tes.append(kTessEXT);
7524 tes.append(kTexBufEXT);
7525 }
7526 else
7527 {
7528 tcs.append(kTessOES);
7529 tes.append(kTessOES);
7530 tes.append(kTexBufOES);
7531 }
7532
7533 constexpr char kTCSBody[] = R"(precision mediump float;
7534 layout(vertices = 2) out;
7535
7536 void main()
7537 {
7538 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7539 gl_TessLevelInner[0] = 1.0;
7540 gl_TessLevelInner[1] = 1.0;
7541 gl_TessLevelOuter[0] = 1.0;
7542 gl_TessLevelOuter[1] = 1.0;
7543 gl_TessLevelOuter[2] = 1.0;
7544 gl_TessLevelOuter[3] = 1.0;
7545 })";
7546 tcs.append(kTCSBody);
7547
7548 constexpr char kTESBody[] = R"(precision mediump float;
7549 layout (isolines, point_mode) in;
7550
7551 uniform highp samplerBuffer tex;
7552
7553 out vec4 tex_color;
7554
7555 void main()
7556 {
7557 tex_color = texelFetch(tex, 0);
7558 gl_Position = gl_in[0].gl_Position;
7559 })";
7560 tes.append(kTESBody);
7561
7562 // Fragment shader
7563 constexpr char kFS[] = R"(#version 310 es
7564 precision mediump float;
7565 layout(location = 0) out mediump vec4 color;
7566
7567 in vec4 tex_color;
7568
7569 void main()
7570 {
7571 color = tex_color;
7572 })";
7573
7574 constexpr GLint kBufferSize = 4;
7575 GLubyte texData[] = {0u, 255u, 0u, 255u};
7576
7577 GLTexture texture;
7578 glBindTexture(GL_TEXTURE_BUFFER, texture);
7579
7580 GLBuffer buffer;
7581 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
7582 glBufferData(GL_TEXTURE_BUFFER, kBufferSize, texData, GL_STATIC_DRAW);
7583 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
7584 ASSERT_GL_NO_ERROR();
7585
7586 glClearColor(1.0, 0, 0, 1.0);
7587 glClear(GL_COLOR_BUFFER_BIT);
7588
7589 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, tcs.c_str(), tes.c_str(), kFS);
7590 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7591 ASSERT_GL_NO_ERROR();
7592 }
7593
7594 // Test that texture buffers can be accessed in a tessellation stage (using EXT)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessEXT)7595 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessEXT)
7596 {
7597 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7598 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
7599 testTessellationTextureBufferAccess(APIExtensionVersion::EXT);
7600 }
7601
7602 // Test that texture buffers can be accessed in a tessellation stage (using OES)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessOES)7603 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessOES)
7604 {
7605 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_tessellation_shader"));
7606 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
7607 testTessellationTextureBufferAccess(APIExtensionVersion::OES);
7608 }
7609
7610 // Test that a varying struct that's not declared in the fragment shader links successfully.
7611 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)7612 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
7613 {
7614 constexpr char kVS[] =
7615 "#version 300 es\n"
7616 "struct S {\n"
7617 " vec4 field;\n"
7618 "};\n"
7619 "out S varStruct;\n"
7620 "void main()\n"
7621 "{\n"
7622 " gl_Position = vec4(1.0);\n"
7623 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7624 "}\n";
7625
7626 constexpr char kFS[] =
7627 "#version 300 es\n"
7628 "precision mediump float;\n"
7629 "out vec4 col;\n"
7630 "void main()\n"
7631 "{\n"
7632 " col = vec4(1.0);\n"
7633 "}\n";
7634
7635 ANGLE_GL_PROGRAM(program, kVS, kFS);
7636 }
7637
7638 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
7639 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)7640 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
7641 {
7642 // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
7643 // going to use it. See section 9.1 in
7644 // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
7645 // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7646 //
7647 // However, nvidia OpenGL ES drivers fail to link this program.
7648 //
7649 // http://anglebug.com/42262078
7650 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
7651
7652 constexpr char kVS[] =
7653 "#version 300 es\n"
7654 "void main()\n"
7655 "{\n"
7656 " gl_Position = vec4(1.0);\n"
7657 "}\n";
7658
7659 constexpr char kFS[] =
7660 "#version 300 es\n"
7661 "precision mediump float;\n"
7662 "out vec4 col;\n"
7663 "struct S {\n"
7664 " vec4 field;\n"
7665 "};\n"
7666 "in S varStruct;\n"
7667 "void main()\n"
7668 "{\n"
7669 " col = vec4(1.0);\n"
7670 "}\n";
7671
7672 ANGLE_GL_PROGRAM(program, kVS, kFS);
7673 }
7674
7675 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)7676 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
7677 {
7678 // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
7679 // specification that the varying values are undefined in the fragment stage). See section 9.1
7680 // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
7681 // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7682 //
7683 // However, windows and mac OpenGL drivers fail to link this program. With a message like:
7684 //
7685 // > Input of fragment shader 'varStruct' not written by vertex shader
7686 //
7687 // http://anglebug.com/42262078
7688 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsMac() || (IsWindows() && !IsNVIDIA())));
7689
7690 constexpr char kVS[] =
7691 "#version 300 es\n"
7692 "struct S {\n"
7693 " vec4 field;\n"
7694 "};\n"
7695 "out S varStruct;\n"
7696 "void main()\n"
7697 "{\n"
7698 " gl_Position = vec4(1.0);\n"
7699 "}\n";
7700
7701 constexpr char kFS[] =
7702 "#version 300 es\n"
7703 "precision mediump float;\n"
7704 "out vec4 col;\n"
7705 "struct S {\n"
7706 " vec4 field;\n"
7707 "};\n"
7708 "in S varStruct;\n"
7709 "void main()\n"
7710 "{\n"
7711 " col = varStruct.field;\n"
7712 "}\n";
7713
7714 ANGLE_GL_PROGRAM(program, kVS, kFS);
7715 }
7716
7717 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)7718 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
7719 {
7720 constexpr char kVS[] =
7721 "#version 300 es\n"
7722 "in vec4 inputAttribute;\n"
7723 "struct S {\n"
7724 " vec4 field;\n"
7725 "};\n"
7726 "out S varStruct;\n"
7727 "out S varStruct2;\n"
7728 "void main()\n"
7729 "{\n"
7730 " gl_Position = inputAttribute;\n"
7731 " varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7732 " varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7733 "}\n";
7734
7735 constexpr char kFS[] =
7736 "#version 300 es\n"
7737 "precision mediump float;\n"
7738 "out vec4 col;\n"
7739 "struct S {\n"
7740 " vec4 field;\n"
7741 "};\n"
7742 "in S varStruct;\n"
7743 "in S varStruct2;\n"
7744 "void main()\n"
7745 "{\n"
7746 " col = varStruct.field + varStruct2.field;\n"
7747 "}\n";
7748
7749 ANGLE_GL_PROGRAM(program, kVS, kFS);
7750 drawQuad(program, "inputAttribute", 0.5f);
7751 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7752 }
7753
7754 // This is a regression test to make sure a red quad is rendered without issues
7755 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)7756 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
7757 {
7758 constexpr char kVS[] =
7759 "precision mediump float;\n"
7760 "attribute vec4 inputAttribute;\n"
7761 "varying mediump vec2 texCoord;\n"
7762 "void main() {\n"
7763 " texCoord = inputAttribute.xy;\n"
7764 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7765 "}\n";
7766
7767 constexpr char kFS[] =
7768 "precision mediump float;\n"
7769 "varying mediump vec2 texCoord;\n"
7770 "uniform sampler2D testSampler;\n"
7771 "vec3 passthrough(vec3 c) {\n"
7772 " return c;\n"
7773 "}\n"
7774 "void main() {\n"
7775 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
7776 "}\n";
7777 ANGLE_GL_PROGRAM(program, kVS, kFS);
7778
7779 // Initialize basic red texture.
7780 GLTexture texture;
7781 glBindTexture(GL_TEXTURE_2D, texture);
7782 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7783 GLColor::red.data());
7784 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7786 ASSERT_GL_NO_ERROR();
7787
7788 drawQuad(program, "inputAttribute", 0.5f);
7789 ASSERT_GL_NO_ERROR();
7790 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7791 }
7792
7793 // This is a regression test to make sure a red quad is rendered without issues
7794 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)7795 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
7796 {
7797 constexpr char kVS[] =
7798 "precision mediump float;\n"
7799 "attribute vec4 inputAttribute;\n"
7800 "varying mediump vec2 texCoord;\n"
7801 "void main() {\n"
7802 " texCoord = inputAttribute.xy;\n"
7803 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7804 "}\n";
7805
7806 constexpr char kFS[] =
7807 "precision mediump float;\n"
7808 "varying mediump vec2 texCoord;\n"
7809 "uniform sampler2D testSampler;\n"
7810 "vec4 passthrough(vec4 c) {\n"
7811 " return c;\n"
7812 "}\n"
7813 "void main() {\n"
7814 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
7815 "}\n";
7816 ANGLE_GL_PROGRAM(program, kVS, kFS);
7817
7818 // Initialize basic red texture.
7819 GLTexture texture;
7820 glBindTexture(GL_TEXTURE_2D, texture);
7821 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7822 GLColor::red.data());
7823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7824 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7825 ASSERT_GL_NO_ERROR();
7826
7827 drawQuad(program, "inputAttribute", 0.5f);
7828 ASSERT_GL_NO_ERROR();
7829 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7830 }
7831
7832 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)7833 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
7834 {
7835 // TODO(syoussefi): fails on android with:
7836 //
7837 // > Internal Vulkan error: A return array was too small for the result
7838 //
7839 // http://anglebug.com/42261898
7840 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
7841
7842 constexpr char kVS[] =
7843 "#version 300 es\n"
7844 "in vec4 inputAttribute;\n"
7845 "struct S {\n"
7846 " vec4 field1;\n"
7847 " vec4 field2;\n"
7848 "};\n"
7849 "out S varStruct;\n"
7850 "out S varStruct2;\n"
7851 "void main()\n"
7852 "{\n"
7853 " gl_Position = inputAttribute;\n"
7854 " varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7855 " varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7856 " varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7857 " varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7858 "}\n";
7859
7860 constexpr char kFS[] =
7861 "#version 300 es\n"
7862 "precision mediump float;\n"
7863 "out vec4 col;\n"
7864 "struct S {\n"
7865 " vec4 field1;\n"
7866 " vec4 field2;\n"
7867 "};\n"
7868 "in S varStruct;\n"
7869 "in S varStruct2;\n"
7870 "void main()\n"
7871 "{\n"
7872 " col = varStruct.field1 + varStruct2.field2;\n"
7873 "}\n";
7874
7875 ANGLE_GL_PROGRAM(program, kVS, kFS);
7876 drawQuad(program, "inputAttribute", 0.5f);
7877 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7878 }
7879
7880 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)7881 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
7882 {
7883 constexpr char kVS[] =
7884 "#version 300 es\n"
7885 "in vec4 inputAttribute;\n"
7886 "out vec4 varArray[4];\n"
7887 "void main()\n"
7888 "{\n"
7889 " gl_Position = inputAttribute;\n"
7890 " varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
7891 " varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
7892 " varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
7893 " varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
7894 "}\n";
7895
7896 constexpr char kFS[] =
7897 "#version 300 es\n"
7898 "precision mediump float;\n"
7899 "out vec4 col;\n"
7900 "void main()\n"
7901 "{\n"
7902 " col = vec4(0.0, 0.0, 0.0, 1.0);\n"
7903 "}\n";
7904
7905 ANGLE_GL_PROGRAM(program, kVS, kFS);
7906 drawQuad(program, "inputAttribute", 0.5f);
7907 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7908 }
7909
7910 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)7911 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
7912 {
7913 constexpr char kVS[] =
7914 "#version 300 es\n"
7915 "in vec4 inputAttribute;\n"
7916 "struct S {\n"
7917 " vec4 field;\n"
7918 "};\n"
7919 "out S varStruct;\n"
7920 "out S varStruct2;\n"
7921 "void main()\n"
7922 "{\n"
7923 " gl_Position = inputAttribute;\n"
7924 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7925 " varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7926 "}\n";
7927
7928 constexpr char kFS[] =
7929 "#version 300 es\n"
7930 "precision mediump float;\n"
7931 "out vec4 col;\n"
7932 "struct S {\n"
7933 " vec4 field;\n"
7934 "};\n"
7935 "in S varStruct;\n"
7936 "in S varStruct2;\n"
7937 "void main()\n"
7938 "{\n"
7939 " col = varStruct.field;\n"
7940 "}\n";
7941
7942 ANGLE_GL_PROGRAM(program, kVS, kFS);
7943 drawQuad(program, "inputAttribute", 0.5f);
7944 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7945 }
7946
7947 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)7948 TEST_P(GLSLTest_ES3, VaryingMatrices)
7949 {
7950 constexpr char kVS[] =
7951 "#version 300 es\n"
7952 "in vec4 inputAttribute;\n"
7953 "out mat2x2 varMat;\n"
7954 "out mat2x2 varMat2;\n"
7955 "out mat4x3 varMat3;\n"
7956 "void main()\n"
7957 "{\n"
7958 " gl_Position = inputAttribute;\n"
7959 " varMat[0] = vec2(1, 1);\n"
7960 " varMat[1] = vec2(1, 1);\n"
7961 " varMat2[0] = vec2(0.5, 0.5);\n"
7962 " varMat2[1] = vec2(0.5, 0.5);\n"
7963 " varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
7964 " varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
7965 " varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
7966 " varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
7967 "}\n";
7968
7969 constexpr char kFS[] =
7970 "#version 300 es\n"
7971 "precision mediump float;\n"
7972 "out vec4 col;\n"
7973 "in mat2x2 varMat;\n"
7974 "in mat2x2 varMat2;\n"
7975 "in mat4x3 varMat3;\n"
7976 "void main()\n"
7977 "{\n"
7978 " col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
7979 "}\n";
7980
7981 ANGLE_GL_PROGRAM(program, kVS, kFS);
7982 drawQuad(program, "inputAttribute", 0.5f);
7983 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
7984 }
7985
7986 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)7987 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
7988 {
7989 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
7990 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7991
7992 const char kFragmentShader[] = R"(precision mediump float;
7993 struct S { sampler2D samplerMember; };
7994 uniform S uStruct;
7995 uniform vec2 uTexCoord;
7996 vec4 foo(S structVar)
7997 {
7998 return texture2D(structVar.samplerMember, uTexCoord);
7999 }
8000 void main()
8001 {
8002 gl_FragColor = foo(uStruct);
8003 })";
8004
8005 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8006
8007 // Initialize the texture with green.
8008 GLTexture tex;
8009 glActiveTexture(GL_TEXTURE0);
8010 glBindTexture(GL_TEXTURE_2D, tex);
8011 GLubyte texData[] = {0u, 255u, 0u, 255u};
8012 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8013 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8015 ASSERT_GL_NO_ERROR();
8016
8017 // Draw
8018 glUseProgram(program);
8019 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8020 ASSERT_NE(-1, samplerMemberLoc);
8021 glUniform1i(samplerMemberLoc, 0);
8022 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8023 ASSERT_NE(-1, texCoordLoc);
8024 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8025
8026 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8027 ASSERT_GL_NO_ERROR();
8028
8029 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8030 }
8031
8032 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)8033 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
8034 {
8035 // Shader failed to compile on Android. http://anglebug.com/42260860
8036 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
8037
8038 const char kFragmentShader[] = R"(precision mediump float;
8039 struct S { sampler2D samplerMember; };
8040 uniform S uStruct;
8041 uniform vec2 uTexCoord;
8042 vec4 foo(S structVar);
8043 vec4 foo(S structVar)
8044 {
8045 return texture2D(structVar.samplerMember, uTexCoord);
8046 }
8047 void main()
8048 {
8049 gl_FragColor = foo(uStruct);
8050 })";
8051
8052 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8053
8054 // Initialize the texture with green.
8055 GLTexture tex;
8056 glActiveTexture(GL_TEXTURE0);
8057 glBindTexture(GL_TEXTURE_2D, tex);
8058 GLubyte texData[] = {0u, 255u, 0u, 255u};
8059 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8060 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8062 ASSERT_GL_NO_ERROR();
8063
8064 // Draw
8065 glUseProgram(program);
8066 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8067 ASSERT_NE(-1, samplerMemberLoc);
8068 glUniform1i(samplerMemberLoc, 0);
8069 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8070 ASSERT_NE(-1, texCoordLoc);
8071 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8072
8073 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8074 ASSERT_GL_NO_ERROR();
8075
8076 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8077 }
8078
8079 // This test covers passing a struct containing a sampler as a function argument, where the function
8080 // has non-return branch statements.
TEST_P(GLSLTest_ES3,StructsWithSamplersAsFunctionArgWithBranch)8081 TEST_P(GLSLTest_ES3, StructsWithSamplersAsFunctionArgWithBranch)
8082 {
8083 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8084 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8085
8086 const char kFragmentShader[] = R"(precision mediump float;
8087 struct S { sampler2D samplerMember; };
8088 uniform S uStruct;
8089 uniform vec2 uTexCoord;
8090 vec4 foo(S structVar)
8091 {
8092 vec4 result;
8093 while (true)
8094 {
8095 result = texture2D(structVar.samplerMember, uTexCoord);
8096 if (result.x == 12345.)
8097 {
8098 continue;
8099 }
8100 break;
8101 }
8102 return result;
8103 }
8104 void main()
8105 {
8106 gl_FragColor = foo(uStruct);
8107 })";
8108
8109 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8110
8111 // Initialize the texture with green.
8112 GLTexture tex;
8113 glActiveTexture(GL_TEXTURE0);
8114 glBindTexture(GL_TEXTURE_2D, tex);
8115 GLubyte texData[] = {0u, 255u, 0u, 255u};
8116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8119 ASSERT_GL_NO_ERROR();
8120
8121 // Draw
8122 glUseProgram(program);
8123 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8124 ASSERT_NE(-1, samplerMemberLoc);
8125 glUniform1i(samplerMemberLoc, 0);
8126 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8127 ASSERT_NE(-1, texCoordLoc);
8128 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8129
8130 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8131 ASSERT_GL_NO_ERROR();
8132
8133 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8134 }
8135
8136 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)8137 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
8138 {
8139 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8140 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8141
8142 constexpr char kFS[] =
8143 "precision mediump float;\n"
8144 "struct S\n"
8145 "{\n"
8146 " sampler2D samplerMember; \n"
8147 "};\n"
8148 "uniform S uStructs[2];\n"
8149 "uniform vec2 uTexCoord;\n"
8150 "\n"
8151 "vec4 foo(S[2] structs)\n"
8152 "{\n"
8153 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
8154 "}\n"
8155 "void main()\n"
8156 "{\n"
8157 " gl_FragColor = foo(uStructs);\n"
8158 "}\n";
8159
8160 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8161
8162 // Initialize the texture with green.
8163 GLTexture tex;
8164 glActiveTexture(GL_TEXTURE0);
8165 glBindTexture(GL_TEXTURE_2D, tex);
8166 GLubyte texData[] = {0u, 255u, 0u, 255u};
8167 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8170 ASSERT_GL_NO_ERROR();
8171
8172 // Draw
8173 glUseProgram(program);
8174 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
8175 ASSERT_NE(-1, samplerMemberLoc);
8176 glUniform1i(samplerMemberLoc, 0);
8177 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8178 ASSERT_NE(-1, texCoordLoc);
8179 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8180
8181 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8182 ASSERT_GL_NO_ERROR();
8183
8184 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8185 }
8186
8187 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)8188 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
8189 {
8190 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8191 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8192
8193 constexpr char kFS[] =
8194 "precision mediump float;\n"
8195 "struct S\n"
8196 "{\n"
8197 " sampler2D samplerMembers[2];\n"
8198 "};\n"
8199 "uniform S uStruct;\n"
8200 "uniform vec2 uTexCoord;\n"
8201 "\n"
8202 "vec4 foo(S str)\n"
8203 "{\n"
8204 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
8205 "}\n"
8206 "void main()\n"
8207 "{\n"
8208 " gl_FragColor = foo(uStruct);\n"
8209 "}\n";
8210
8211 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8212
8213 // Initialize the texture with green.
8214 GLTexture tex;
8215 glActiveTexture(GL_TEXTURE0);
8216 glBindTexture(GL_TEXTURE_2D, tex);
8217 GLubyte texData[] = {0u, 255u, 0u, 255u};
8218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8221 ASSERT_GL_NO_ERROR();
8222
8223 // Draw
8224 glUseProgram(program);
8225 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
8226 ASSERT_NE(-1, samplerMemberLoc);
8227 glUniform1i(samplerMemberLoc, 0);
8228 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8229 ASSERT_NE(-1, texCoordLoc);
8230 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8231
8232 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8233 ASSERT_GL_NO_ERROR();
8234
8235 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8236 }
8237
8238 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)8239 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
8240 {
8241 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8242 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8243
8244 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8245 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8246
8247 const char kFragmentShader[] = R"(precision mediump float;
8248 struct S { sampler2D samplerMember; };
8249 struct T { S nest; };
8250 uniform T uStruct;
8251 uniform vec2 uTexCoord;
8252 vec4 foo2(S structVar)
8253 {
8254 return texture2D(structVar.samplerMember, uTexCoord);
8255 }
8256 vec4 foo(T structVar)
8257 {
8258 return foo2(structVar.nest);
8259 }
8260 void main()
8261 {
8262 gl_FragColor = foo(uStruct);
8263 })";
8264
8265 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8266
8267 // Initialize the texture with green.
8268 GLTexture tex;
8269 glActiveTexture(GL_TEXTURE0);
8270 glBindTexture(GL_TEXTURE_2D, tex);
8271 GLubyte texData[] = {0u, 255u, 0u, 255u};
8272 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8275 ASSERT_GL_NO_ERROR();
8276
8277 // Draw
8278 glUseProgram(program);
8279 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8280 ASSERT_NE(-1, samplerMemberLoc);
8281 glUniform1i(samplerMemberLoc, 0);
8282 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8283 ASSERT_NE(-1, texCoordLoc);
8284 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8285
8286 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8287 ASSERT_GL_NO_ERROR();
8288
8289 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8290 }
8291
8292 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)8293 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
8294 {
8295 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8296 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8297
8298 const char kFragmentShader[] = R"(precision mediump float;
8299 struct S { sampler2D samplerMember; bool b; };
8300 uniform S uStruct;
8301 uniform vec2 uTexCoord;
8302 vec4 foo(S structVar)
8303 {
8304 if (structVar.b)
8305 return texture2D(structVar.samplerMember, uTexCoord);
8306 else
8307 return vec4(1, 0, 0, 1);
8308 }
8309 void main()
8310 {
8311 gl_FragColor = foo(uStruct);
8312 })";
8313
8314 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8315
8316 // Initialize the texture with green.
8317 GLTexture tex;
8318 glActiveTexture(GL_TEXTURE0);
8319 glBindTexture(GL_TEXTURE_2D, tex);
8320 GLubyte texData[] = {0u, 255u, 0u, 255u};
8321 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8324 ASSERT_GL_NO_ERROR();
8325
8326 // Draw
8327 glUseProgram(program);
8328 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8329 ASSERT_NE(-1, samplerMemberLoc);
8330 glUniform1i(samplerMemberLoc, 0);
8331 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8332 ASSERT_NE(-1, texCoordLoc);
8333 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8334 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8335 ASSERT_NE(-1, bLoc);
8336 glUniform1i(bLoc, 1);
8337
8338 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8339 ASSERT_GL_NO_ERROR();
8340
8341 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8342 }
8343
8344 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)8345 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
8346 {
8347 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8348 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8349
8350 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8351 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8352
8353 const char kFragmentShader[] = R"(precision mediump float;
8354 struct S { sampler2D samplerMember; bool b; };
8355 struct T { S nest; bool b; };
8356 uniform T uStruct;
8357 uniform vec2 uTexCoord;
8358 vec4 foo2(S structVar)
8359 {
8360 if (structVar.b)
8361 return texture2D(structVar.samplerMember, uTexCoord);
8362 else
8363 return vec4(1, 0, 0, 1);
8364 }
8365 vec4 foo(T structVar)
8366 {
8367 if (structVar.b)
8368 return foo2(structVar.nest);
8369 else
8370 return vec4(1, 0, 0, 1);
8371 }
8372 void main()
8373 {
8374 gl_FragColor = foo(uStruct);
8375 })";
8376
8377 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8378
8379 // Initialize the texture with green.
8380 GLTexture tex;
8381 glActiveTexture(GL_TEXTURE0);
8382 glBindTexture(GL_TEXTURE_2D, tex);
8383 GLubyte texData[] = {0u, 255u, 0u, 255u};
8384 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8387 ASSERT_GL_NO_ERROR();
8388
8389 // Draw
8390 glUseProgram(program);
8391 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8392 ASSERT_NE(-1, samplerMemberLoc);
8393 glUniform1i(samplerMemberLoc, 0);
8394 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8395 ASSERT_NE(-1, texCoordLoc);
8396 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8397
8398 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8399 ASSERT_NE(-1, bLoc);
8400 glUniform1i(bLoc, 1);
8401
8402 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8403 ASSERT_NE(-1, nestbLoc);
8404 glUniform1i(nestbLoc, 1);
8405
8406 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8407 ASSERT_GL_NO_ERROR();
8408
8409 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8410 }
8411
8412 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)8413 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
8414 {
8415 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8416 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8417
8418 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8419 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8420
8421 const char kFragmentShader[] = R"(precision mediump float;
8422 struct S { bool b; sampler2D samplerMember; };
8423 struct T { bool b; S nest; };
8424 uniform T uStruct;
8425 uniform vec2 uTexCoord;
8426 vec4 foo2(S structVar)
8427 {
8428 if (structVar.b)
8429 return texture2D(structVar.samplerMember, uTexCoord);
8430 else
8431 return vec4(1, 0, 0, 1);
8432 }
8433 vec4 foo(T structVar)
8434 {
8435 if (structVar.b)
8436 return foo2(structVar.nest);
8437 else
8438 return vec4(1, 0, 0, 1);
8439 }
8440 void main()
8441 {
8442 gl_FragColor = foo(uStruct);
8443 })";
8444
8445 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8446
8447 // Initialize the texture with green.
8448 GLTexture tex;
8449 glActiveTexture(GL_TEXTURE0);
8450 glBindTexture(GL_TEXTURE_2D, tex);
8451 GLubyte texData[] = {0u, 255u, 0u, 255u};
8452 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8454 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8455 ASSERT_GL_NO_ERROR();
8456
8457 // Draw
8458 glUseProgram(program);
8459 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8460 ASSERT_NE(-1, samplerMemberLoc);
8461 glUniform1i(samplerMemberLoc, 0);
8462 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8463 ASSERT_NE(-1, texCoordLoc);
8464 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8465
8466 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8467 ASSERT_NE(-1, bLoc);
8468 glUniform1i(bLoc, 1);
8469
8470 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8471 ASSERT_NE(-1, nestbLoc);
8472 glUniform1i(nestbLoc, 1);
8473
8474 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8475 ASSERT_GL_NO_ERROR();
8476
8477 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8478 }
8479 // Test that a global variable declared after main() works. This is a regression test for an issue
8480 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)8481 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
8482 {
8483 constexpr char kFS[] =
8484 "precision mediump float;\n"
8485 "int getFoo();\n"
8486 "uniform int u_zero;\n"
8487 "void main()\n"
8488 "{\n"
8489 " gl_FragColor = vec4(1, 0, 0, 1);\n"
8490 " if (getFoo() == 0)\n"
8491 " {\n"
8492 " gl_FragColor = vec4(0, 1, 0, 1);\n"
8493 " }\n"
8494 "}\n"
8495 "int foo;\n"
8496 "int getFoo()\n"
8497 "{\n"
8498 " foo = u_zero;\n"
8499 " return foo;\n"
8500 "}\n";
8501
8502 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8503 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8504 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8505 }
8506
8507 // Test calling array length() with a "this" expression having side effects inside a loop condition.
8508 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)8509 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
8510 {
8511 // "a" gets doubled three times in the below program.
8512 constexpr char kFS[] = R"(#version 300 es
8513 precision highp float;
8514 out vec4 my_FragColor;
8515 uniform int u_zero;
8516 int a;
8517 int[2] doubleA()
8518 {
8519 a *= 2;
8520 return int[2](a, a);
8521 }
8522 void main()
8523 {
8524 a = u_zero + 1;
8525 for (int i = 0; i < doubleA().length(); ++i)
8526 {}
8527 if (a == 8)
8528 {
8529 my_FragColor = vec4(0, 1, 0, 1);
8530 }
8531 else
8532 {
8533 my_FragColor = vec4(1, 0, 0, 1);
8534 }
8535 })";
8536
8537 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8538 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8539 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8540 }
8541
8542 // Test calling array length() with a "this" expression having side effects that interact with side
8543 // effects of another operand of the same sequence operator. The spec says that sequence operator
8544 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)8545 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
8546 {
8547 constexpr char kFS[] = R"(#version 300 es
8548 precision highp float;
8549 out vec4 my_FragColor;
8550 uniform int u_zero;
8551 int a;
8552 int[3] doubleA()
8553 {
8554 a *= 2;
8555 return int[3](a, a, a);
8556 }
8557 void main()
8558 {
8559 a = u_zero;
8560 int b = (a++, doubleA().length());
8561 if (b == 3 && a == 2)
8562 {
8563 my_FragColor = vec4(0, 1, 0, 1);
8564 }
8565 else
8566 {
8567 my_FragColor = vec4(1, 0, 0, 1);
8568 }
8569 })";
8570
8571 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8572 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8573 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8574 }
8575
8576 // Test calling array length() with a "this" expression that also contains a call of array length().
8577 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)8578 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
8579 {
8580 constexpr char kFS[] = R"(#version 300 es
8581 precision highp float;
8582 out vec4 my_FragColor;
8583 uniform int u_zero;
8584 int a;
8585 int[3] multiplyA(int multiplier)
8586 {
8587 a *= multiplier;
8588 return int[3](a, a, a);
8589 }
8590 void main()
8591 {
8592 a = u_zero + 1;
8593 int b = multiplyA(multiplyA(2).length()).length();
8594 if (b == 3 && a == 6)
8595 {
8596 my_FragColor = vec4(0, 1, 0, 1);
8597 }
8598 else
8599 {
8600 my_FragColor = vec4(1, 0, 0, 1);
8601 }
8602 })";
8603
8604 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8605 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8606 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8607 }
8608
8609 // Test calling array length() with a "this" expression having side effects inside an if condition.
8610 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)8611 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
8612 {
8613 // Bug in the shader translator. http://anglebug.com/42262472
8614 ANGLE_SKIP_TEST_IF(true);
8615
8616 // "a" shouldn't get modified by this shader.
8617 constexpr char kFS[] = R"(#version 300 es
8618 precision highp float;
8619 out vec4 my_FragColor;
8620 uniform int u_zero;
8621 int a;
8622 int[2] doubleA()
8623 {
8624 a *= 2;
8625 return int[2](a, a);
8626 }
8627 void main()
8628 {
8629 a = u_zero + 1;
8630 if (u_zero != 0 && doubleA().length() == 2)
8631 {
8632 ++a;
8633 }
8634 if (a == 1)
8635 {
8636 my_FragColor = vec4(0, 1, 0, 1);
8637 }
8638 else
8639 {
8640 my_FragColor = vec4(1, 0, 0, 1);
8641 }
8642 })";
8643
8644 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8645 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8646 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8647 }
8648
8649 // Test calling array length() with a "this" expression having side effects in a statement where the
8650 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)8651 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
8652 {
8653 // Bug in the shader translator. http://anglebug.com/42262472
8654 ANGLE_SKIP_TEST_IF(true);
8655
8656 // "a" shouldn't get modified by this shader.
8657 constexpr char kFS[] = R"(#version 300 es
8658 precision highp float;
8659 out vec4 my_FragColor;
8660 uniform int u_zero;
8661 int a;
8662 int[2] doubleA()
8663 {
8664 a *= 2;
8665 return int[2](a, a);
8666 }
8667 void main()
8668 {
8669 a = u_zero + 1;
8670 bool test = u_zero != 0 && doubleA().length() == 2;
8671 if (a == 1)
8672 {
8673 my_FragColor = vec4(0, 1, 0, 1);
8674 }
8675 else
8676 {
8677 my_FragColor = vec4(1, 0, 0, 1);
8678 }
8679 })";
8680
8681 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8682 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8683 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8684 }
8685
8686 // Test that array length inside vector constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructor)8687 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructor)
8688 {
8689 const char kVS[] = R"(#version 300 es
8690 precision highp float;
8691 flat out uvec4 v;
8692
8693 int[1] f0()
8694 {
8695 return int[1](1);
8696 }
8697 void main()
8698 {
8699 v = uvec4(vec4(f0().length()));
8700
8701 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8702 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8703 gl_Position.zw = vec2(0, 1);
8704 })";
8705
8706 const char kFS[] = R"(#version 300 es
8707 precision highp float;
8708 flat in uvec4 v;
8709 out vec4 color;
8710
8711 bool isEq(uint a, float b) { return abs(float(a) - b) < 0.01; }
8712
8713 void main()
8714 {
8715 if (isEq(v[0], 1.) &&
8716 isEq(v[1], 1.) &&
8717 isEq(v[2], 1.) &&
8718 isEq(v[3], 1.))
8719 {
8720 color = vec4(0, 1, 0, 1);
8721 }
8722 else
8723 {
8724 color = vec4(1, 0, 0, 1);
8725 }
8726 })";
8727
8728 ANGLE_GL_PROGRAM(program, kVS, kFS);
8729 glUseProgram(program);
8730 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8731 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8732 }
8733
8734 // Test that array length inside vector constructor works in complex expression.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructorComplex)8735 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructorComplex)
8736 {
8737 const char kVS[] = R"(#version 300 es
8738 precision highp float;
8739 out vec4 v;
8740
8741 int[1] f0()
8742 {
8743 return int[1](1);
8744 }
8745 void main()
8746 {
8747 v = vec4(float(uint(f0().length()) + 1u) / 4.);
8748
8749 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8750 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8751 gl_Position.zw = vec2(0, 1);
8752 })";
8753
8754 const char kFS[] = R"(#version 300 es
8755 precision highp float;
8756 in vec4 v;
8757 out vec4 color;
8758
8759 bool isEq(float a, float b) { return abs(float(a) - b) < 0.01; }
8760
8761 void main()
8762 {
8763 if (isEq(v[0], 0.5) &&
8764 isEq(v[1], 0.5) &&
8765 isEq(v[2], 0.5) &&
8766 isEq(v[3], 0.5))
8767 {
8768 color = vec4(0, 1, 0, 1);
8769 }
8770 else
8771 {
8772 color = vec4(1, 0, 0, 1);
8773 }
8774 })";
8775
8776 ANGLE_GL_PROGRAM(program, kVS, kFS);
8777 glUseProgram(program);
8778 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8779 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8780 }
8781
8782 // Test that array length inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInMatrixConstructor)8783 TEST_P(GLSLTest_ES3, ArrayLengthInMatrixConstructor)
8784 {
8785 const char kVS[] = R"(#version 300 es
8786 precision highp float;
8787 out mat2x2 v;
8788
8789 int[1] f0()
8790 {
8791 return int[1](1);
8792 }
8793 void main()
8794 {
8795 v = mat2x2(f0().length());
8796
8797 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8798 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8799 gl_Position.zw = vec2(0, 1);
8800 })";
8801
8802 const char kFS[] = R"(#version 300 es
8803 precision highp float;
8804 in mat2x2 v;
8805 out vec4 color;
8806
8807 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8808
8809 void main()
8810 {
8811 if (isEq(v[0][0], 1.) &&
8812 isEq(v[0][1], 0.) &&
8813 isEq(v[1][0], 0.) &&
8814 isEq(v[1][1], 1.))
8815 {
8816 color = vec4(0, 1, 0, 1);
8817 }
8818 else
8819 {
8820 color = vec4(1, 0, 0, 1);
8821 }
8822 })";
8823
8824 ANGLE_GL_PROGRAM(program, kVS, kFS);
8825 glUseProgram(program);
8826 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8827 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8828 }
8829
8830 // Test that array length inside vector constructor inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorInMatrixConstructor)8831 TEST_P(GLSLTest_ES3, ArrayLengthInVectorInMatrixConstructor)
8832 {
8833 const char kVS[] = R"(#version 300 es
8834 precision highp float;
8835 out mat2x2 v;
8836
8837 int[1] f0()
8838 {
8839 return int[1](1);
8840 }
8841 void main()
8842 {
8843 v = mat2x2(vec2(f0().length()), f0().length(), 0);
8844
8845 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8846 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8847 gl_Position.zw = vec2(0, 1);
8848 })";
8849
8850 const char kFS[] = R"(#version 300 es
8851 precision highp float;
8852 in mat2x2 v;
8853 out vec4 color;
8854
8855 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8856
8857 void main()
8858 {
8859 if (isEq(v[0][0], 1.) &&
8860 isEq(v[0][1], 1.) &&
8861 isEq(v[1][0], 1.) &&
8862 isEq(v[1][1], 0.))
8863 {
8864 color = vec4(0, 1, 0, 1);
8865 }
8866 else
8867 {
8868 color = vec4(1, 0, 0, 1);
8869 }
8870 })";
8871
8872 ANGLE_GL_PROGRAM(program, kVS, kFS);
8873 glUseProgram(program);
8874 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8875 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8876 }
8877
8878 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)8879 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
8880 {
8881 constexpr char kFS[] = R"(#version 300 es
8882 precision highp float;
8883 uniform int u;
8884 void main()
8885 {
8886 switch (u)
8887 {
8888 case 0:
8889 ivec2 i;
8890 i.yx;
8891 }
8892 })";
8893
8894 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8895 }
8896
8897 // Test that switch fall-through works correctly.
8898 // This is a regression test for http://anglebug.com/40644631
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)8899 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
8900 {
8901 constexpr char kFS[] = R"(#version 300 es
8902 precision highp float;
8903 out vec4 my_FragColor;
8904 uniform int u_zero;
8905
8906 void main()
8907 {
8908 int i = 0;
8909 // switch should fall through both cases.
8910 switch(u_zero)
8911 {
8912 case 0:
8913 i += 1;
8914 case 1:
8915 i += 2;
8916 }
8917 if (i == 3)
8918 {
8919 my_FragColor = vec4(0, 1, 0, 1);
8920 }
8921 else
8922 {
8923 my_FragColor = vec4(1, 0, 0, 1);
8924 }
8925 })";
8926
8927 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8928 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8929 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8930 }
8931
8932 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)8933 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
8934 {
8935 constexpr char kFS[] = R"(#version 300 es
8936
8937 precision highp float;
8938 out vec4 my_FragColor;
8939
8940 uniform int u_zero;
8941
8942 void main()
8943 {
8944 switch (u_zero)
8945 {
8946 case 1:
8947 my_FragColor = vec4(1, 0, 0, 1);
8948 break;
8949 default:
8950 my_FragColor = vec4(0, 1, 0, 1);
8951 }
8952 })";
8953
8954 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8955 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8956 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8957 }
8958
8959 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)8960 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
8961 {
8962 constexpr char kFS[] = R"(#version 300 es
8963
8964 precision mediump float;
8965 uniform int i;
8966 void main()
8967 {
8968 switch (i)
8969 {
8970 case 0:
8971 break;
8972 default:
8973 {}
8974 }
8975 })";
8976 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8977 }
8978
8979 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)8980 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
8981 {
8982 constexpr char kFS[] = R"(#version 300 es
8983
8984 precision mediump float;
8985 uniform int i;
8986 void main()
8987 {
8988 switch (i)
8989 {
8990 case 0:
8991 break;
8992 default:
8993 float;
8994 }
8995 })";
8996 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8997 }
8998
8999 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)9000 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
9001 {
9002 constexpr char kFS[] = R"(#version 300 es
9003
9004 precision highp float;
9005
9006 uniform int u_zero;
9007 out vec4 my_FragColor;
9008
9009 bool test(int n)
9010 {
9011 switch(n) {
9012 case 0:
9013 {
9014 {
9015 break;
9016 }
9017 }
9018 case 1:
9019 {
9020 return true;
9021 }
9022 case 2:
9023 {
9024 n++;
9025 }
9026 }
9027 return false;
9028 }
9029
9030 void main()
9031 {
9032 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9033 })";
9034
9035 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9036 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9037 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9038 }
9039
9040 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
9041 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)9042 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
9043 {
9044 constexpr char kFS[] = R"(#version 300 es
9045
9046 precision highp float;
9047 out vec4 my_FragColor;
9048
9049 uniform int u_zero;
9050
9051 void main()
9052 {
9053 my_FragColor = vec4(1, 0, 0, 1);
9054 switch (u_zero)
9055 {
9056 case 0:
9057 ivec2 i;
9058 i = ivec2(1, 0);
9059 default:
9060 my_FragColor = vec4(0, i[0], 0, 1);
9061 }
9062 })";
9063
9064 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9065 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9066 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9067 }
9068
9069 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
9070 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)9071 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
9072 {
9073 constexpr char kFS[] = R"(#version 300 es
9074
9075 precision highp float;
9076 out vec4 my_FragColor;
9077
9078 uniform int u_zero;
9079 uniform int u_zero2;
9080
9081 void main()
9082 {
9083 my_FragColor = vec4(1, 0, 0, 1);
9084 switch (u_zero)
9085 {
9086 case 0:
9087 ivec2 i;
9088 i = ivec2(1, 0);
9089 switch (u_zero2)
9090 {
9091 case 0:
9092 int j;
9093 default:
9094 j = 1;
9095 i *= j;
9096 }
9097 default:
9098 my_FragColor = vec4(0, i[0], 0, 1);
9099 }
9100 })";
9101
9102 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9103 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9104 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9105 }
9106
9107 // Test that an empty switch/case statement is translated in a way that compiles and executes the
9108 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)9109 TEST_P(GLSLTest_ES3, EmptySwitch)
9110 {
9111 constexpr char kFS[] = R"(#version 300 es
9112
9113 precision highp float;
9114
9115 uniform int u_zero;
9116 out vec4 my_FragColor;
9117
9118 void main()
9119 {
9120 int i = u_zero;
9121 switch(++i) {}
9122 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9123 })";
9124
9125 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9126 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9127 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9128 }
9129
9130 // Test that an switch over a constant with mismatching cases works.
TEST_P(GLSLTest_ES3,SwitchWithConstantExpr)9131 TEST_P(GLSLTest_ES3, SwitchWithConstantExpr)
9132 {
9133 constexpr char kFS[] = R"(#version 300 es
9134 precision highp float;
9135 out vec4 color;
9136
9137 void main()
9138 {
9139 float r = 0.;
9140 float g = 1.;
9141 float b = 0.;
9142
9143 switch(10)
9144 {
9145 case 44:
9146 r = 0.5;
9147 case 50:
9148 break;
9149 }
9150
9151 switch(20)
9152 {
9153 case 198:
9154 g = 0.5;
9155 default:
9156 g -= 1.;
9157 break;
9158 }
9159
9160 switch(30)
9161 {
9162 default:
9163 b = 0.5;
9164 case 4:
9165 b += 0.5;
9166 break;
9167 }
9168
9169 color = vec4(r, g, b, 1);
9170 })";
9171
9172 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9173 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9174 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
9175 }
9176
9177 // Test that basic infinite loops are either rejected or are pruned in WebGL
TEST_P(WebGL2GLSLTest,BasicInfiniteLoop)9178 TEST_P(WebGL2GLSLTest, BasicInfiniteLoop)
9179 {
9180 constexpr char kFS[] = R"(#version 300 es
9181 precision highp float;
9182 uniform uint zero;
9183 out vec4 color;
9184
9185 bool globalConstantVariable = true;
9186
9187 float f()
9188 {
9189 // Should not be pruned
9190 while (true)
9191 {
9192 // Should not be pruned
9193 for (int i = 0; true; ++i)
9194 {
9195 if (zero < 10u)
9196 {
9197 switch (zero)
9198 {
9199 case 0u:
9200 // Loops should be pruned because of this `return`.
9201 return 0.7;
9202 default:
9203 break;
9204 }
9205 }
9206 }
9207 }
9208 }
9209
9210 void main()
9211 {
9212 float r = 0.;
9213 float g = 1.;
9214 float b = 0.;
9215
9216 bool localConstantVariable = true;
9217 bool localVariable = true;
9218
9219 // Should be pruned
9220 while (true)
9221 {
9222 r += 0.1;
9223 if (r > 0.)
9224 {
9225 continue;
9226 }
9227 }
9228
9229 if (zero != 0u)
9230 {
9231 localVariable = false;
9232 }
9233
9234 // Should be pruned
9235 while (localConstantVariable)
9236 {
9237 g -= 0.1;
9238 }
9239
9240 // Should not be pruned
9241 while (localConstantVariable)
9242 {
9243 b += 0.3;
9244
9245 if (g > 0.4) { break; }
9246 }
9247
9248 // Should be pruned
9249 for (; globalConstantVariable; )
9250 {
9251 g -= 0.1;
9252
9253 switch (zero)
9254 {
9255 case 0u:
9256 r = 0.4;
9257 break;
9258 default:
9259 r = 0.2;
9260 break;
9261 }
9262 }
9263
9264 // Should not be pruned
9265 while (localVariable)
9266 {
9267 b += 0.2;
9268 localVariable = !localVariable;
9269 }
9270
9271 r = f();
9272
9273 color = vec4(r, g, b, 1);
9274 })";
9275
9276 if (getEGLWindow()->isFeatureEnabled(Feature::RejectWebglShadersWithUndefinedBehavior))
9277 {
9278 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
9279 EXPECT_EQ(0u, shader);
9280 }
9281 else
9282 {
9283 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9284 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9285 EXPECT_PIXEL_NEAR(0, 0, 178, 255, 127, 255, 1);
9286 }
9287 }
9288
9289 // Test that while(true) loops with break/return are not rejected
TEST_P(WebGL2GLSLTest,NotInfiniteLoop)9290 TEST_P(WebGL2GLSLTest, NotInfiniteLoop)
9291 {
9292 constexpr char kFS[] = R"(#version 300 es
9293 precision highp float;
9294 uniform uint zero;
9295 out vec4 color;
9296
9297 void main()
9298 {
9299 float r = 0.;
9300 float g = 1.;
9301 float b = 0.;
9302
9303 while (true)
9304 {
9305 r += 0.1;
9306 if (r > 0.4)
9307 {
9308 break;
9309 }
9310 }
9311
9312 for (;;)
9313 {
9314 g -= 0.1;
9315
9316 switch (zero)
9317 {
9318 case 0u:
9319 g -= 0.6;
9320 color = vec4(r, g, b, 1);
9321 return;
9322 default:
9323 r = 0.2;
9324 break;
9325 }
9326 }
9327 })";
9328
9329 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9330 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9331 EXPECT_PIXEL_NEAR(0, 0, 127, 76, 0, 255, 1);
9332 }
9333
9334 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)9335 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
9336 {
9337 // Incorrect output color was seen on Android. http://anglebug.com/42260946
9338 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
9339
9340 constexpr char kFS[] = R"(#version 300 es
9341
9342 precision highp float;
9343 out vec4 my_FragColor;
9344
9345 uniform float u_zero;
9346
9347 struct S
9348 {
9349 float field;
9350 };
9351
9352 void main()
9353 {
9354 const S constS = S(1.0);
9355 S nonConstS = constS;
9356 nonConstS.field = u_zero;
9357 bool fail = (constS == nonConstS);
9358 my_FragColor = vec4(0, 1, 0, 1);
9359 if (fail)
9360 {
9361 my_FragColor = vec4(1, 0, 0, 1);
9362 }
9363 })";
9364
9365 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9366 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9367 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9368 }
9369
9370 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)9371 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
9372 {
9373 constexpr char kVS[] = R"(#version 300 es
9374 in vec4 inputAttribute;
9375
9376 flat out struct S
9377 {
9378 int field;
9379 } v_s;
9380
9381 void main()
9382 {
9383 v_s.field = 1;
9384 gl_Position = inputAttribute;
9385 })";
9386
9387 constexpr char kFS[] = R"(#version 300 es
9388
9389 precision highp float;
9390 out vec4 my_FragColor;
9391
9392 flat in struct S
9393 {
9394 int field;
9395 } v_s;
9396
9397 void main()
9398 {
9399 bool success = (v_s.field == 1);
9400 my_FragColor = vec4(1, 0, 0, 1);
9401 if (success)
9402 {
9403 my_FragColor = vec4(0, 1, 0, 1);
9404 }
9405 })";
9406
9407 ANGLE_GL_PROGRAM(program, kVS, kFS);
9408 drawQuad(program, "inputAttribute", 0.5f);
9409 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9410 }
9411
9412 // Test that multi variables struct should not crash in separated struct expressions.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition2)9413 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition2)
9414 {
9415 constexpr char kVS[] = R"(#version 300 es
9416 in vec4 inputAttribute;
9417 flat out struct A
9418 {
9419 int a;
9420 } z1, z2;
9421 void main()
9422 {
9423 z1.a = 1;
9424 z2.a = 2;
9425 gl_Position = inputAttribute;
9426 })";
9427 constexpr char kFS[] = R"(#version 300 es
9428 precision highp float;
9429 out vec4 my_FragColor;
9430 flat in struct A
9431 {
9432 int a;
9433 } z1, z2;
9434 void main()
9435 {
9436 bool success = (z1.a == 1 && z2.a == 2);
9437 my_FragColor = vec4(1, 0, 0, 1);
9438 if (success)
9439 {
9440 my_FragColor = vec4(0, 1, 0, 1);
9441 }
9442 })";
9443
9444 ANGLE_GL_PROGRAM(program, kVS, kFS);
9445 drawQuad(program.get(), "inputAttribute", 0.5f);
9446 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9447 }
9448
9449 // Test that a varying anonymous struct that is defined as a part of the declaration is handled
9450 // correctly.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition)9451 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition)
9452 {
9453 constexpr char kVS[] = R"(#version 300 es
9454 in vec4 inputAttribute;
9455 flat out struct
9456 {
9457 int field;
9458 } v_s;
9459
9460 void main()
9461 {
9462 v_s.field = 1;
9463 gl_Position = inputAttribute;
9464 })";
9465
9466 constexpr char kFS[] = R"(#version 300 es
9467 precision highp float;
9468 out vec4 my_FragColor;
9469 flat in struct
9470 {
9471 int field;
9472 } v_s;
9473 void main()
9474 {
9475 bool success = (v_s.field == 1);
9476 my_FragColor = vec4(1, 0, 0, 1);
9477 if (success)
9478 {
9479 my_FragColor = vec4(0, 1, 0, 1);
9480 }
9481 })";
9482 ANGLE_GL_PROGRAM(program, kVS, kFS);
9483 drawQuad(program.get(), "inputAttribute", 0.5f);
9484 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9485 }
9486
9487 // Test that a varying anonymous structs that are defined as a part of the declaration is handled
9488 // correctly.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition2)9489 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition2)
9490 {
9491 constexpr char kVS[] = R"(#version 300 es
9492 in vec4 inputAttribute;
9493 flat out struct
9494 {
9495 int field;
9496 } v_s0, v_s1;
9497 void main()
9498 {
9499 v_s0.field = 1;
9500 v_s1.field = 2;
9501 gl_Position = inputAttribute;
9502 })";
9503 constexpr char kFS[] = R"(#version 300 es
9504 precision highp float;
9505 out vec4 my_FragColor;
9506 flat in struct
9507 {
9508 int field;
9509 } v_s0, v_s1;
9510 void main()
9511 {
9512 bool success = (v_s0.field == 1 && v_s1.field == 2);
9513 my_FragColor = vec4(1, 0, 0, 1);
9514 if (success)
9515 {
9516 my_FragColor = vec4(0, 1, 0, 1);
9517 }
9518 })";
9519 ANGLE_GL_PROGRAM(program, kVS, kFS);
9520 drawQuad(program.get(), "inputAttribute", 0.5f);
9521 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9522 }
9523
9524 // Test that a varying anonymous structs that are defined as a part of the declaration is handled
9525 // in a specific way. Highlights ambiguity of ES "Chapter 9. Shader Interface Matching":
9526 // "When linking shaders, the type of declared vertex outputs and fragment inputs with the same
9527 // name must match"
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition3)9528 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition3)
9529 {
9530 constexpr char kVS[] = R"(#version 300 es
9531 in vec4 inputAttribute;
9532 flat out struct
9533 {
9534 int field;
9535 } v_s0;
9536 flat out struct
9537 {
9538 int field;
9539 } v_s1;
9540 flat out struct
9541 {
9542 int field;
9543 } v_s2, v_s3;
9544 void main()
9545 {
9546 v_s0.field = 1;
9547 v_s1.field = 2;
9548 v_s2.field = 3;
9549 v_s3.field = 4;
9550 gl_Position = inputAttribute;
9551 })";
9552
9553 constexpr char kFS[] = R"(#version 300 es
9554 precision highp float;
9555 out vec4 my_FragColor;
9556 flat in struct
9557 {
9558 int field;
9559 } v_s0, v_s1, v_s2, v_s3;
9560 void main()
9561 {
9562 bool success = v_s0.field == 1 && v_s1.field == 2 && v_s2.field == 3 && v_s3.field == 4;
9563 my_FragColor = vec4(1, 0, 0, 1);
9564 if (success)
9565 {
9566 my_FragColor = vec4(0, 1, 0, 1);
9567 }
9568 })";
9569
9570 ANGLE_GL_PROGRAM(program, kVS, kFS);
9571 drawQuad(program.get(), "inputAttribute", 0.5f);
9572 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9573 }
9574
9575 // Test that a varying anonymous structs can be compared for equality.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructEquality)9576 TEST_P(GLSLTest_ES3, VaryingAnonymousStructEquality)
9577 {
9578 constexpr char kVS[] = R"(#version 300 es
9579 in vec4 inputAttribute;
9580 flat out struct
9581 {
9582 int field;
9583 } v_s0;
9584 flat out struct
9585 {
9586 int field;
9587 } v_s1;
9588 flat out struct
9589 {
9590 int field;
9591 } v_s2, v_s3;
9592
9593 void main()
9594 {
9595 v_s0.field = 1;
9596 v_s1.field = 2;
9597 v_s2.field = 3;
9598 v_s3.field = 4;
9599 gl_Position = inputAttribute;
9600 })";
9601
9602 constexpr char kFS[] = R"(#version 300 es
9603 precision highp float;
9604 out vec4 my_FragColor;
9605 flat in struct
9606 {
9607 int field;
9608 } v_s0, v_s1, v_s2, v_s3;
9609 void main()
9610 {
9611 bool success = v_s0 != v_s1 && v_s0 != v_s2 && v_s0 != v_s3 && v_s1 != v_s2 && v_s1 != v_s3 && v_s2 != v_s3;
9612 success = success && v_s0.field == 1 && v_s1.field == 2 && v_s2.field == 3 && v_s3.field == 4;
9613 my_FragColor = vec4(1, 0, 0, 1);
9614 if (success)
9615 {
9616 my_FragColor = vec4(0, 1, 0, 1);
9617 }
9618 })";
9619
9620 ANGLE_GL_PROGRAM(program, kVS, kFS);
9621 drawQuad(program.get(), "inputAttribute", 0.5f);
9622 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9623 }
9624
9625 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)9626 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
9627 {
9628 constexpr char kVS[] = R"(#version 300 es
9629 in vec4 position;
9630 uniform highp float inVal;
9631 out highp float myVarying;
9632
9633 void main()
9634 {
9635 myVarying = inVal;
9636 gl_Position = position;
9637 })";
9638
9639 constexpr char kFS[] = R"(#version 300 es
9640 precision highp float;
9641 out vec4 my_FragColor;
9642 in mediump float myVarying;
9643
9644 void main()
9645 {
9646 my_FragColor = vec4(1, 0, 0, 1);
9647 if (myVarying > 1.0)
9648 {
9649 my_FragColor = vec4(0, 1, 0, 1);
9650 }
9651 })";
9652
9653 ANGLE_GL_PROGRAM(program, kVS, kFS);
9654
9655 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9656 glClear(GL_COLOR_BUFFER_BIT);
9657 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9658
9659 glUseProgram(program);
9660 GLint positionLocation = glGetAttribLocation(program, "position");
9661 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9662 for (Vector3 &vertex : quadVertices)
9663 {
9664 vertex.z() = 0.5f;
9665 }
9666 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9667 glEnableVertexAttribArray(positionLocation);
9668
9669 GLint inValLoc = glGetUniformLocation(program, "inVal");
9670 ASSERT_NE(-1, inValLoc);
9671 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9672
9673 glDrawArrays(GL_TRIANGLES, 0, 6);
9674 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9675 }
9676
9677 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)9678 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
9679 {
9680 // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
9681 // precision", thus this is the same test as MismatchPrecisionFloat but including it for
9682 // completeness in case something changes.
9683 constexpr char kVS[] = R"(#version 300 es
9684 in vec4 position;
9685 uniform highp float inVal;
9686 out highp float myVarying;
9687
9688 void main()
9689 {
9690 myVarying = inVal;
9691 gl_Position = position;
9692 })";
9693
9694 constexpr char kFS[] = R"(#version 300 es
9695 precision highp float;
9696 out vec4 my_FragColor;
9697 in lowp float myVarying;
9698
9699 void main()
9700 {
9701 my_FragColor = vec4(1, 0, 0, 1);
9702 if (myVarying > 1.0)
9703 {
9704 my_FragColor = vec4(0, 1, 0, 1);
9705 }
9706 })";
9707
9708 ANGLE_GL_PROGRAM(program, kVS, kFS);
9709
9710 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9711 glClear(GL_COLOR_BUFFER_BIT);
9712 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9713
9714 glUseProgram(program);
9715 GLint positionLocation = glGetAttribLocation(program, "position");
9716 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9717 for (Vector3 &vertex : quadVertices)
9718 {
9719 vertex.z() = 0.5f;
9720 }
9721 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9722 glEnableVertexAttribArray(positionLocation);
9723
9724 GLint inValLoc = glGetUniformLocation(program, "inVal");
9725 ASSERT_NE(-1, inValLoc);
9726 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9727
9728 glDrawArrays(GL_TRIANGLES, 0, 6);
9729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9730 }
9731
9732 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)9733 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
9734 {
9735 constexpr char kVS[] = R"(#version 300 es
9736 in vec2 position;
9737 uniform highp float inVal;
9738 out highp float myVarying;
9739 out highp vec2 texCoord;
9740
9741 void main()
9742 {
9743 myVarying = inVal;
9744 gl_Position = vec4(position, 0, 1);
9745 texCoord = position * 0.5 + vec2(0.5);
9746 })";
9747
9748 constexpr char kFS[] = R"(#version 300 es
9749 precision highp float;
9750 out vec4 my_FragColor;
9751 in mediump float myVarying;
9752 in mediump vec2 texCoord;
9753
9754 void main()
9755 {
9756 my_FragColor = vec4(1, 0, 0, 1);
9757 if (myVarying > 1.0)
9758 {
9759 my_FragColor = vec4(0, 1, 0, 1);
9760 }
9761 })";
9762
9763 ANGLE_GL_PROGRAM(program, kVS, kFS);
9764
9765 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9766 glClear(GL_COLOR_BUFFER_BIT);
9767 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9768
9769 glUseProgram(program);
9770 GLint positionLocation = glGetAttribLocation(program, "position");
9771 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9772 for (Vector3 &vertex : quadVertices)
9773 {
9774 vertex.z() = 0.5f;
9775 }
9776 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9777 glEnableVertexAttribArray(positionLocation);
9778
9779 GLint inValLoc = glGetUniformLocation(program, "inVal");
9780 ASSERT_NE(-1, inValLoc);
9781 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9782
9783 glDrawArrays(GL_TRIANGLES, 0, 6);
9784 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9785 }
9786
9787 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)9788 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
9789 {
9790 constexpr char kVS[] = R"(#version 300 es
9791 in vec2 position;
9792 uniform highp float inVal;
9793 out mediump float myVarying;
9794
9795 void main()
9796 {
9797 myVarying = inVal;
9798 gl_Position = vec4(position, 0, 1);
9799 })";
9800
9801 constexpr char kFS[] = R"(#version 300 es
9802 precision highp float;
9803 out vec4 my_FragColor;
9804 in highp float myVarying;
9805
9806 void main()
9807 {
9808 my_FragColor = vec4(1, 0, 0, 1);
9809 if (myVarying > 1.0)
9810 {
9811 my_FragColor = vec4(0, 1, 0, 1);
9812 }
9813 })";
9814
9815 ANGLE_GL_PROGRAM(program, kVS, kFS);
9816
9817 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9818 glClear(GL_COLOR_BUFFER_BIT);
9819 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9820
9821 glUseProgram(program);
9822 GLint positionLocation = glGetAttribLocation(program, "position");
9823 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9824 for (Vector3 &vertex : quadVertices)
9825 {
9826 vertex.z() = 0.5f;
9827 }
9828 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9829 glEnableVertexAttribArray(positionLocation);
9830
9831 GLint inValLoc = glGetUniformLocation(program, "inVal");
9832 ASSERT_NE(-1, inValLoc);
9833 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9834
9835 glDrawArrays(GL_TRIANGLES, 0, 6);
9836 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9837 }
9838
9839 // Test that *= on boolean vectors fails compilation
TEST_P(GLSLTest,BVecMultiplyAssign)9840 TEST_P(GLSLTest, BVecMultiplyAssign)
9841 {
9842 constexpr char kFS[] = R"(bvec4 c,s;void main(){s*=c;})";
9843
9844 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
9845 EXPECT_EQ(fs, 0u);
9846 }
9847
9848 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)9849 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
9850 {
9851 constexpr char kFS[] = R"(precision mediump float;
9852
9853 void main() {
9854 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9855 for (int i = 0; i < 2; i++)
9856 {
9857 gl_FragColor += (2.0 * gl_FragCoord.x);
9858 }
9859 if (gl_FragColor.g == gl_FragColor.r &&
9860 gl_FragColor.b == gl_FragColor.r &&
9861 gl_FragColor.a == gl_FragColor.r)
9862 {
9863 gl_FragColor = vec4(0, 1, 0, 1);
9864 }
9865 })";
9866
9867 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9868 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9869 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9870 }
9871
9872 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)9873 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
9874 {
9875 constexpr char kFS[] = R"(precision mediump float;
9876
9877 void main() {
9878 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9879 for (int i = 0; i < 2; i++)
9880 {
9881 float x = gl_FragCoord.x;
9882 gl_FragColor = gl_FragColor + (x /= 2.0);
9883 }
9884 if (gl_FragColor.g == gl_FragColor.r &&
9885 gl_FragColor.b == gl_FragColor.r &&
9886 gl_FragColor.a == gl_FragColor.r)
9887 {
9888 gl_FragColor = vec4(0, 1, 0, 1);
9889 }
9890 })";
9891
9892 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9893 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9894 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9895 }
9896
9897 // Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation.
TEST_P(GLSLTest,VectorScalarArithmeticWithSideEffectInLoop)9898 TEST_P(GLSLTest, VectorScalarArithmeticWithSideEffectInLoop)
9899 {
9900 // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past
9901 // (notice how sbcd references i outside the for loop. The loop condition doesn't look right
9902 // either):
9903 //
9904 // #version 450
9905 // void main(){
9906 // (gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
9907 // mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
9908 // vec3 _ures = vec3(0.0, 0.0, 0.0);
9909 // vec3 sbcd = vec3(_ures[_ui]);
9910 // for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)),
9911 // sbcd)), _ui)], (_ui < 7)); )
9912 // {
9913 // }
9914 // }
9915
9916 constexpr char kVS[] = R"(
9917 void main()
9918 {
9919 mat3 tmp;
9920 vec3 res;
9921 for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;);
9922 })";
9923
9924 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9925
9926 const char *sourceArray[1] = {kVS};
9927 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
9928 glShaderSource(shader, 1, sourceArray, lengths);
9929 glCompileShader(shader);
9930
9931 GLint compileResult;
9932 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9933 EXPECT_NE(compileResult, 0);
9934 }
9935
9936 // Test that packing of excessive 3-column variables does not overflow the count of 3-column
9937 // variables in VariablePacker
TEST_P(WebGL2GLSLTest,ExcessiveMat3UniformPacking)9938 TEST_P(WebGL2GLSLTest, ExcessiveMat3UniformPacking)
9939 {
9940 std::ostringstream srcStream;
9941
9942 srcStream << "#version 300 es\n";
9943 srcStream << "precision mediump float;\n";
9944 srcStream << "out vec4 finalColor;\n";
9945 srcStream << "in vec4 color;\n";
9946 srcStream << "uniform mat4 r[254];\n";
9947
9948 srcStream << "uniform mat3 ";
9949 constexpr size_t kNumUniforms = 10000;
9950 for (size_t i = 0; i < kNumUniforms; ++i)
9951 {
9952 if (i > 0)
9953 {
9954 srcStream << ", ";
9955 }
9956 srcStream << "m3a_" << i << "[256]";
9957 }
9958 srcStream << ";\n";
9959
9960 srcStream << "void main(void) { finalColor = color; }\n";
9961 std::string src = std::move(srcStream).str();
9962
9963 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9964
9965 const char *sourceArray[1] = {src.c_str()};
9966 GLint lengths[1] = {static_cast<GLint>(src.length())};
9967 glShaderSource(shader, 1, sourceArray, lengths);
9968 glCompileShader(shader);
9969
9970 GLint compileResult;
9971 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9972 EXPECT_EQ(compileResult, 0);
9973 }
9974
9975 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
9976 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)9977 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
9978 {
9979 constexpr char kVS[] = R"(#version 300 es
9980
9981 in vec4 inputAttribute;
9982
9983 flat out int v;
9984
9985 void main()
9986 {
9987 v = 1;
9988 gl_Position = inputAttribute;
9989 })";
9990
9991 constexpr char kFS[] = R"(#version 300 es
9992
9993 precision highp float;
9994 out vec4 my_FragColor;
9995
9996 flat in int v;
9997
9998 void main()
9999 {
10000 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
10001 })";
10002
10003 ANGLE_GL_PROGRAM(program, kVS, kFS);
10004 drawQuad(program, "inputAttribute", 0.5f);
10005 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10006 }
10007
10008 // Verify that the link error message from last link failure is cleared when the new link is
10009 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)10010 TEST_P(GLSLTest, ClearLinkErrorLog)
10011 {
10012 constexpr char kVS[] = R"(attribute vec4 vert_in;
10013 varying vec4 vert_out;
10014 void main()
10015 {
10016 gl_Position = vert_in;
10017 vert_out = vert_in;
10018 })";
10019
10020 constexpr char kFS[] = R"(precision mediump float;
10021 varying vec4 frag_in;
10022 void main()
10023 {
10024 gl_FragColor = frag_in;
10025 })";
10026
10027 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
10028 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
10029
10030 GLuint program = glCreateProgram();
10031
10032 // The first time the program link fails because of lack of fragment shader.
10033 glAttachShader(program, vs);
10034 glLinkProgram(program);
10035 GLint linkStatus = GL_TRUE;
10036 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10037 ASSERT_FALSE(linkStatus);
10038
10039 const std::string lackOfFragmentShader = QueryErrorMessage(program);
10040 EXPECT_TRUE(lackOfFragmentShader != "");
10041
10042 // The second time the program link fails because of the mismatch of the varying types.
10043 glAttachShader(program, fs);
10044 glLinkProgram(program);
10045 linkStatus = GL_TRUE;
10046 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10047 ASSERT_FALSE(linkStatus);
10048
10049 const std::string varyingTypeMismatch = QueryErrorMessage(program);
10050 EXPECT_TRUE(varyingTypeMismatch != "");
10051
10052 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
10053
10054 glDetachShader(program, vs);
10055 glDetachShader(program, fs);
10056 glDeleteShader(vs);
10057 glDeleteShader(fs);
10058 glDeleteProgram(program);
10059
10060 ASSERT_GL_NO_ERROR();
10061 }
10062
10063 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)10064 TEST_P(GLSLTest, DrawAfterShaderLinkError)
10065 {
10066 constexpr char kVS[] = R"(attribute vec4 position;
10067 varying vec4 vColor;
10068 void main()
10069 {
10070 vColor = vec4(0.0, 1.0, 0.0, 1.0);
10071 gl_Position = position;
10072 })";
10073 constexpr char kFS[] = R"(precision mediump float;
10074 varying vec4 vColor;
10075 void main()
10076 {
10077 gl_FragColor = vColor;
10078 })";
10079 constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
10080
10081 GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
10082
10083 // Create bad fragment shader
10084 {
10085 const char *sourceArray[1] = {kBadFS};
10086 glShaderSource(fsBad, 1, sourceArray, nullptr);
10087 glCompileShader(fsBad);
10088
10089 GLint compileResult;
10090 glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
10091 ASSERT_FALSE(compileResult);
10092 }
10093
10094 ANGLE_GL_PROGRAM(program, kVS, kFS);
10095 GLuint fs = GetProgramShader(program, GL_FRAGMENT_SHADER);
10096
10097 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10098 glClear(GL_COLOR_BUFFER_BIT);
10099 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10100
10101 glUseProgram(program);
10102 GLint positionLocation = glGetAttribLocation(program, "position");
10103 std::array<Vector3, 6> quadVertices = GetQuadVertices();
10104 for (Vector3 &vertex : quadVertices)
10105 {
10106 vertex.z() = 0.5f;
10107 }
10108 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
10109 glEnableVertexAttribArray(positionLocation);
10110 glDrawArrays(GL_TRIANGLES, 0, 6);
10111 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10112
10113 glDetachShader(program, fs);
10114 glAttachShader(program, fsBad);
10115 glLinkProgram(program);
10116 GLint linkStatus = GL_TRUE;
10117 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10118 ASSERT_FALSE(linkStatus);
10119
10120 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10121 glClear(GL_COLOR_BUFFER_BIT);
10122 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10123
10124 glDrawArrays(GL_TRIANGLES, 0, 6);
10125 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10126 }
10127
10128 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)10129 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
10130 {
10131 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
10132 varying vec4 vertex_out;
10133 void main()
10134 {
10135 vertex_out = inputAttribute;
10136 gl_Position = inputAttribute;
10137 })";
10138
10139 constexpr char kFS[] = R"(precision mediump float;
10140 varying float vertex_out;
10141 void main()
10142 {
10143 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
10144 })";
10145
10146 validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
10147 }
10148
10149 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)10150 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
10151 {
10152 constexpr char kVS[] = R"(#version 300 es
10153 in vec4 inputAttribute;
10154 struct S {
10155 float val1;
10156 vec4 val2;
10157 };
10158 out S vertex_out;
10159 void main()
10160 {
10161 vertex_out.val2 = inputAttribute;
10162 vertex_out.val1 = inputAttribute[0];
10163 gl_Position = inputAttribute;
10164 })";
10165
10166 constexpr char kFS[] = R"(#version 300 es
10167 precision mediump float;
10168 struct S {
10169 float val1;
10170 vec4 val3;
10171 };
10172 in S vertex_out;
10173 layout (location = 0) out vec4 frag_out;
10174 void main()
10175 {
10176 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
10177 })";
10178
10179 validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
10180 }
10181
10182 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)10183 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
10184 {
10185 constexpr char kVS[] = R"(#version 300 es
10186 in vec4 inputAttribute;
10187 struct S {
10188 float val1;
10189 vec4 val2;
10190 };
10191 out S vertex_out;
10192 void main()
10193 {
10194 vertex_out.val2 = inputAttribute;
10195 vertex_out.val1 = inputAttribute[0];
10196 gl_Position = inputAttribute;
10197 })";
10198
10199 constexpr char kFS[] = R"(#version 300 es
10200 precision mediump float;
10201 struct S {
10202 float val1;
10203 vec2 val2;
10204 };
10205 in S vertex_out;
10206 layout (location = 0) out vec4 frag_out;
10207 void main()
10208 {
10209 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
10210 })";
10211
10212 validateComponentsInErrorMessage(kVS, kFS, "Types",
10213 "varying 'vertex_out' member 'vertex_out.val2'");
10214 }
10215
10216 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
10217 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)10218 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
10219 {
10220 constexpr char kVS[] = R"(
10221 struct T
10222 {
10223 vec2 t1;
10224 vec3 t2;
10225 };
10226 struct S {
10227 T val1;
10228 vec4 val2;
10229 };
10230 uniform S uni;
10231
10232 attribute vec4 inputAttribute;
10233 varying vec4 vertex_out;
10234 void main()
10235 {
10236 vertex_out = uni.val2;
10237 gl_Position = inputAttribute;
10238 })";
10239
10240 constexpr char kFS[] = R"(precision highp float;
10241 struct T
10242 {
10243 vec2 t1;
10244 vec3 t3;
10245 };
10246 struct S {
10247 T val1;
10248 vec4 val2;
10249 };
10250 uniform S uni;
10251
10252 varying vec4 vertex_out;
10253 void main()
10254 {
10255 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
10256 })";
10257
10258 validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
10259 }
10260
10261 // Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
10262 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)10263 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
10264 {
10265 constexpr char kVS[] = R"(#version 300 es
10266 uniform S {
10267 vec2 val1;
10268 vec4 val2;
10269 } uni;
10270
10271 in vec4 inputAttribute;
10272 out vec4 vertex_out;
10273 void main()
10274 {
10275 vertex_out = uni.val2;
10276 gl_Position = inputAttribute;
10277 })";
10278
10279 constexpr char kFS[] = R"(#version 300 es
10280 precision highp float;
10281 uniform S {
10282 vec2 val1;
10283 vec3 val2;
10284 } uni;
10285
10286 in vec4 vertex_out;
10287 layout (location = 0) out vec4 frag_out;
10288 void main()
10289 {
10290 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
10291 })";
10292
10293 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
10294 }
10295
10296 // Validate error messages when the link mismatch occurs on the type of a member of a uniform block
10297 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)10298 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
10299 {
10300 constexpr char kVS[] = R"(#version 300 es
10301 struct T
10302 {
10303 vec2 t1;
10304 vec3 t2;
10305 };
10306 uniform S {
10307 T val1;
10308 vec4 val2;
10309 } uni;
10310
10311 in vec4 inputAttribute;
10312 out vec4 vertex_out;
10313 void main()
10314 {
10315 vertex_out = uni.val2;
10316 gl_Position = inputAttribute;
10317 })";
10318
10319 constexpr char kFS[] = R"(#version 300 es
10320 precision highp float;
10321 struct T
10322 {
10323 vec2 t1;
10324 vec4 t2;
10325 };
10326 uniform S {
10327 T val1;
10328 vec4 val2;
10329 } uni;
10330
10331 in vec4 vertex_out;
10332 layout (location = 0) out vec4 frag_out;
10333 void main()
10334 {
10335 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
10336 })";
10337
10338 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
10339 }
10340
10341 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
10342 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)10343 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
10344 {
10345 constexpr char kVS[] = R"(#version 300 es
10346 precision mediump float;
10347
10348 void main()
10349 {
10350 gl_Position = vec4(0, 1, 0, 1);
10351 })";
10352
10353 constexpr char kFS[] = R"(#version 300 es
10354 precision mediump float;
10355 in float foo;
10356 out vec4 my_FragColor;
10357
10358 void main()
10359 {
10360 if (false)
10361 {
10362 float unreferenced = foo;
10363 }
10364 my_FragColor = vec4(0, 1, 0, 1);
10365 })";
10366
10367 validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
10368 }
10369
10370 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)10371 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
10372 {
10373 constexpr char kVS[] = R"(#version 300 es
10374 precision mediump float;
10375 in vec4 iv;
10376 out vec4 v;
10377 void main()
10378 {
10379 gl_Position = iv;
10380 v = iv;
10381 })";
10382
10383 constexpr char kFS[] = R"(#version 300 es
10384 precision mediump float;
10385 in vec4 v;
10386 out vec4 color;
10387 void main()
10388 {
10389 color = true ? vec4(0.0) : v;
10390 })";
10391
10392 ANGLE_GL_PROGRAM(program, kVS, kFS);
10393 }
10394
10395 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)10396 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
10397 {
10398 constexpr char kVS[] = R"(#version 310 es
10399 precision highp float;
10400 in vec4 position;
10401 layout(location = 1) out vec4 shaderOutput;
10402 void main() {
10403 gl_Position = position;
10404 shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
10405 })";
10406
10407 constexpr char kFS[] = R"(#version 310 es
10408 precision highp float;
10409 layout(location = 1) in vec4 shaderInput;
10410 out vec4 outColor;
10411 void main() {
10412 outColor = shaderInput;
10413 })";
10414
10415 ANGLE_GL_PROGRAM(program, kVS, kFS);
10416 drawQuad(program, "position", 0.5f);
10417 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10418 }
10419
10420 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)10421 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
10422 {
10423 // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
10424 // up red. http://crbug.com/838885
10425 ANGLE_SKIP_TEST_IF(IsD3D11());
10426
10427 constexpr char kFS[] = R"(#version 300 es
10428 precision highp float;
10429 out vec4 my_FragColor;
10430 void main()
10431 {
10432 vec2 coord = gl_FragCoord.xy / 500.0;
10433 my_FragColor = vec4(1, 0, 0, 1);
10434 if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
10435 {
10436 my_FragColor = vec4(0, 1, 0, 1);
10437 }
10438 })";
10439
10440 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10441 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10442 // Verify that all the corners of the rendered result are green.
10443 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10444 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
10445 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
10446 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
10447 }
10448
10449 // Verify that a link error is generated when the sum of the number of active image uniforms and
10450 // active shader storage blocks in a rendering pipeline exceeds
10451 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)10452 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
10453 {
10454 // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
10455 // D3D11 back-ends.
10456 ANGLE_SKIP_TEST_IF(IsD3D11());
10457
10458 GLint maxVertexShaderStorageBlocks;
10459 GLint maxVertexImageUniforms;
10460 GLint maxFragmentShaderStorageBlocks;
10461 GLint maxFragmentImageUniforms;
10462 GLint maxCombinedShaderStorageBlocks;
10463 GLint maxCombinedImageUniforms;
10464 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
10465 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
10466 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
10467 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
10468 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
10469 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
10470
10471 ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
10472 ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
10473 ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
10474 ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
10475
10476 GLint vertexSSBOs = maxVertexShaderStorageBlocks;
10477 GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
10478 // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
10479 if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
10480 {
10481 fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
10482 }
10483
10484 GLint vertexImages = maxVertexImageUniforms;
10485 GLint fragmentImages = maxFragmentImageUniforms;
10486 // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
10487 if (vertexImages + fragmentImages > maxCombinedImageUniforms)
10488 {
10489 vertexImages = maxCombinedImageUniforms - fragmentImages;
10490 }
10491
10492 GLint maxDrawBuffers;
10493 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
10494
10495 GLint maxCombinedShaderOutputResources;
10496 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
10497 ASSERT_GL_NO_ERROR();
10498
10499 ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
10500 maxDrawBuffers <=
10501 maxCombinedShaderOutputResources);
10502
10503 std::ostringstream vertexStream;
10504 vertexStream << "#version 310 es\n";
10505 for (int i = 0; i < vertexSSBOs; ++i)
10506 {
10507 vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10508 << "{\n"
10509 " float data;\n"
10510 "} ssbo"
10511 << i << ";\n";
10512 }
10513 vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
10514 << "];\n";
10515 vertexStream << "void main()\n"
10516 "{\n"
10517 " float val = 0.1;\n"
10518 " vec4 val2 = vec4(0.0);\n";
10519 for (int i = 0; i < vertexSSBOs; ++i)
10520 {
10521 vertexStream << " val += ssbo" << i << ".data; \n";
10522 }
10523 for (int i = 0; i < vertexImages; ++i)
10524 {
10525 vertexStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10526 }
10527 vertexStream << " gl_Position = vec4(val, val2);\n"
10528 "}\n";
10529
10530 std::ostringstream fragmentStream;
10531 fragmentStream << "#version 310 es\n" << "precision highp float;\n";
10532 for (int i = 0; i < fragmentSSBOs; ++i)
10533 {
10534 fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10535 << "{\n"
10536 " float data;\n"
10537 "} ssbo"
10538 << i << ";\n";
10539 }
10540 fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
10541 << fragmentImages << "];\n";
10542 fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
10543
10544 fragmentStream << "void main()\n"
10545 "{\n"
10546 " float val = 0.1;\n"
10547 " vec4 val2 = vec4(0.0);\n";
10548 for (int i = 0; i < fragmentSSBOs; ++i)
10549 {
10550 fragmentStream << " val += ssbo" << i << ".data; \n";
10551 }
10552 for (int i = 0; i < fragmentImages; ++i)
10553 {
10554 fragmentStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10555 }
10556 for (int i = 0; i < maxDrawBuffers; ++i)
10557 {
10558 fragmentStream << " foutput[" << i << "] = vec4(val, val2);\n";
10559 }
10560 fragmentStream << "}\n";
10561
10562 GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
10563 EXPECT_EQ(0u, program);
10564
10565 ASSERT_GL_NO_ERROR();
10566 }
10567
10568 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
10569 // function works correctly.
TEST_P(GLSLTest_ES3,AssignToSwizzled)10570 TEST_P(GLSLTest_ES3, AssignToSwizzled)
10571 {
10572 constexpr char kFS[] = R"(#version 300 es
10573 precision highp float;
10574 out vec4 my_FragColor;
10575
10576 uniform float uzero;
10577
10578 vec3 fun(float s, float v)
10579 {
10580 vec3 r = vec3(0);
10581 if (s < 1.0) {
10582 r.x = r.y = r.z = v;
10583 return r;
10584 }
10585 return r;
10586 }
10587
10588 void main()
10589 {
10590 my_FragColor.a = 1.0;
10591 my_FragColor.rgb = fun(uzero, 1.0);
10592 })";
10593
10594 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10595 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10596 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10597 }
10598
10599 // Similar to AssignToSwizzled, but uses other assignment operators than `=`.
TEST_P(GLSLTest_ES3,AssignToSwizzled2)10600 TEST_P(GLSLTest_ES3, AssignToSwizzled2)
10601 {
10602 constexpr char kFS[] = R"(#version 300 es
10603 precision highp float;
10604 out vec4 my_FragColor;
10605
10606 uniform float uzero;
10607
10608 vec3 fun(float s, float v)
10609 {
10610 vec3 r = vec3(0.125, 0.5, 0.);
10611 if (s < 1.0) {
10612 r.x /= r.y *= r.z += v;
10613 return r;
10614 }
10615 return r;
10616 }
10617
10618 void main()
10619 {
10620 my_FragColor.a = 1.0;
10621 my_FragColor.rgb = fun(uzero, 1.0);
10622 })";
10623
10624 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10625 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10626 EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 255, 1);
10627 }
10628
10629 // Test that swizzled vector to bool cast works correctly.
TEST_P(GLSLTest_ES3,SwizzledToBoolCoercion)10630 TEST_P(GLSLTest_ES3, SwizzledToBoolCoercion)
10631 {
10632 constexpr char kFS[] = R"(#version 300 es
10633 precision highp float;
10634 out vec4 o;
10635 uniform vec2 u;
10636 void main()
10637 {
10638 bvec2 b = bvec2(u.yx);
10639 if (b.x&&!b.y)
10640 o = vec4(1.0);
10641 })";
10642 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10643 glUseProgram(program);
10644 GLint uloc = glGetUniformLocation(program, "u");
10645 ASSERT_NE(uloc, -1);
10646 glUniform2f(uloc, 0, 1);
10647 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10648 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10649 }
10650
10651 // Test a fragment shader that returns inside if (that being the only branch that actually gets
10652 // executed). Regression test for http://anglebug.com/42261034
TEST_P(GLSLTest,IfElseIfAndReturn)10653 TEST_P(GLSLTest, IfElseIfAndReturn)
10654 {
10655 constexpr char kVS[] = R"(attribute vec4 a_position;
10656 varying vec2 vPos;
10657 void main()
10658 {
10659 gl_Position = a_position;
10660 vPos = a_position.xy;
10661 })";
10662
10663 constexpr char kFS[] = R"(precision mediump float;
10664 varying vec2 vPos;
10665 void main()
10666 {
10667 if (vPos.x < 1.0) // This colors the whole canvas green
10668 {
10669 gl_FragColor = vec4(0, 1, 0, 1);
10670 return;
10671 }
10672 else if (vPos.x < 1.1) // This should have no effect
10673 {
10674 gl_FragColor = vec4(1, 0, 0, 1);
10675 }
10676 })";
10677
10678 ANGLE_GL_PROGRAM(program, kVS, kFS);
10679 drawQuad(program, "a_position", 0.5f);
10680 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10681 }
10682
10683 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)10684 TEST_P(GLSLTest, IfElsePrunedBlocks)
10685 {
10686 constexpr char kFS[] = R"(precision mediump float;
10687 uniform float u;
10688 void main()
10689 {
10690 // if with only a pruned true block
10691 if (u > 0.0)
10692 if (false) discard;
10693
10694 // if with a pruned true block and a false block
10695 if (u > 0.0)
10696 {
10697 if (false) discard;
10698 }
10699 else
10700 ;
10701
10702 // if with a true block and a pruned false block
10703 if (u > 0.0)
10704 ;
10705 else
10706 if (false) discard;
10707
10708 // if with a pruned true block and a pruned false block
10709 if (u > 0.0)
10710 {
10711 if (false) discard;
10712 }
10713 else
10714 if (false) discard;
10715
10716 gl_FragColor = vec4(0, 1, 0, 1);
10717 })";
10718
10719 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10720 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10721 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10722 }
10723
10724 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)10725 TEST_P(GLSLTest, PointCoordConsistency)
10726 {
10727 constexpr char kPointCoordVS[] = R"(attribute vec2 position;
10728 uniform vec2 viewportSize;
10729 void main()
10730 {
10731 gl_Position = vec4(position, 0, 1);
10732 gl_PointSize = viewportSize.x;
10733 })";
10734
10735 constexpr char kPointCoordFS[] = R"(void main()
10736 {
10737 gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
10738 })";
10739
10740 ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
10741 glUseProgram(program);
10742
10743 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10744 ASSERT_NE(-1, uniLoc);
10745 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10746 static_cast<GLfloat>(getWindowHeight()));
10747
10748 // Draw to backbuffer.
10749 glClear(GL_COLOR_BUFFER_BIT);
10750 glDrawArrays(GL_POINTS, 0, 1);
10751 ASSERT_GL_NO_ERROR();
10752
10753 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10754 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10755 backbufferData.data());
10756
10757 GLTexture tex;
10758 glBindTexture(GL_TEXTURE_2D, tex);
10759 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10760 GL_UNSIGNED_BYTE, nullptr);
10761
10762 GLFramebuffer fbo;
10763 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10764 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10765 ASSERT_GL_NO_ERROR();
10766 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10767
10768 // Draw to user FBO.
10769 glClear(GL_COLOR_BUFFER_BIT);
10770 glDrawArrays(GL_POINTS, 0, 1);
10771 ASSERT_GL_NO_ERROR();
10772
10773 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10774 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10775 userFBOData.data());
10776
10777 ASSERT_GL_NO_ERROR();
10778 ASSERT_EQ(userFBOData.size(), backbufferData.size());
10779 EXPECT_EQ(userFBOData, backbufferData);
10780 }
10781
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)10782 bool SubrectEquals(const std::vector<GLColor> &bigArray,
10783 const std::vector<GLColor> &smallArray,
10784 int bigSize,
10785 int offset,
10786 int smallSize)
10787 {
10788 int badPixels = 0;
10789 for (int y = 0; y < smallSize; y++)
10790 {
10791 for (int x = 0; x < smallSize; x++)
10792 {
10793 int bigOffset = (y + offset) * bigSize + x + offset;
10794 int smallOffset = y * smallSize + x;
10795 if (bigArray[bigOffset] != smallArray[smallOffset])
10796 badPixels++;
10797 }
10798 }
10799 return badPixels == 0;
10800 }
10801
10802 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)10803 TEST_P(GLSLTest, FragCoordConsistency)
10804 {
10805 constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
10806 void main()
10807 {
10808 gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
10809 })";
10810
10811 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
10812 glUseProgram(program);
10813
10814 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10815 ASSERT_NE(-1, uniLoc);
10816 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10817 static_cast<GLfloat>(getWindowHeight()));
10818
10819 // Draw to backbuffer.
10820 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10821 ASSERT_GL_NO_ERROR();
10822
10823 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10824 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10825 backbufferData.data());
10826
10827 GLTexture tex;
10828 glBindTexture(GL_TEXTURE_2D, tex);
10829 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10830 GL_UNSIGNED_BYTE, nullptr);
10831
10832 GLFramebuffer fbo;
10833 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10834 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10835 ASSERT_GL_NO_ERROR();
10836 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10837
10838 // Draw to user FBO.
10839 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10840 ASSERT_GL_NO_ERROR();
10841
10842 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10843 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10844 userFBOData.data());
10845
10846 ASSERT_GL_NO_ERROR();
10847 ASSERT_EQ(userFBOData.size(), backbufferData.size());
10848 EXPECT_EQ(userFBOData, backbufferData)
10849 << "FragCoord should be the same to default and user FBO";
10850
10851 // Repeat the same test but with a smaller viewport.
10852 ASSERT_EQ(getWindowHeight(), getWindowWidth());
10853 const int kQuarterSize = getWindowWidth() >> 2;
10854 glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
10855
10856 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10857 glClear(GL_COLOR_BUFFER_BIT);
10858 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10859
10860 std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
10861 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10862 GL_UNSIGNED_BYTE, userFBOViewportData.data());
10863
10864 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10865 glClear(GL_COLOR_BUFFER_BIT);
10866 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10867
10868 std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
10869 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10870 GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
10871 ASSERT_GL_NO_ERROR();
10872 EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
10873 << "FragCoord should be the same to default and user FBO even with a custom viewport";
10874
10875 // Check that the subrectangles are the same between the viewport and non-viewport modes.
10876 EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
10877 kQuarterSize * 2));
10878 EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
10879 kQuarterSize, kQuarterSize * 2));
10880 }
10881
10882 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)10883 TEST_P(GLSLTest, DefinedInMacroSucceeds)
10884 {
10885 constexpr char kVS[] = R"(precision mediump float;
10886 attribute highp vec4 position;
10887 varying vec2 out0;
10888
10889 void main()
10890 {
10891 #define AAA defined(BBB)
10892
10893 #if !AAA
10894 out0 = vec2(0.0, 1.0);
10895 #else
10896 out0 = vec2(1.0, 0.0);
10897 #endif
10898 gl_Position = position;
10899 })";
10900
10901 constexpr char kFS[] = R"(precision mediump float;
10902 varying vec2 out0;
10903 void main()
10904 {
10905 gl_FragColor = vec4(out0, 0, 1);
10906 })";
10907
10908 ANGLE_GL_PROGRAM(program, kVS, kFS);
10909 drawQuad(program, "position", 0.5f);
10910 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10911 }
10912
10913 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)10914 TEST_P(GLSLTest, DefinedInMacroWithUndef)
10915 {
10916 constexpr char kVS[] = R"(precision mediump float;
10917 attribute highp vec4 position;
10918 varying vec2 out0;
10919
10920 void main()
10921 {
10922 #define BBB 1
10923 #define AAA defined(BBB)
10924 #undef BBB
10925
10926 #if AAA
10927 out0 = vec2(1.0, 0.0);
10928 #else
10929 out0 = vec2(0.0, 1.0);
10930 #endif
10931 gl_Position = position;
10932 })";
10933
10934 constexpr char kFS[] = R"(precision mediump float;
10935 varying vec2 out0;
10936 void main()
10937 {
10938 gl_FragColor = vec4(out0, 0, 1);
10939 })";
10940
10941 ANGLE_GL_PROGRAM(program, kVS, kFS);
10942 drawQuad(program, "position", 0.5f);
10943 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10944 }
10945
10946 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)10947 TEST_P(GLSLTest, DefinedAfterMacroUsage)
10948 {
10949 constexpr char kVS[] = R"(precision mediump float;
10950 attribute highp vec4 position;
10951 varying vec2 out0;
10952
10953 void main()
10954 {
10955 #define AAA defined(BBB)
10956 #define BBB 1
10957
10958 #if AAA
10959 out0 = vec2(0.0, 1.0);
10960 #else
10961 out0 = vec2(1.0, 0.0);
10962 #endif
10963 gl_Position = position;
10964 })";
10965
10966 constexpr char kFS[] = R"(precision mediump float;
10967 varying vec2 out0;
10968 void main()
10969 {
10970 gl_FragColor = vec4(out0, 0, 1);
10971 })";
10972
10973 ANGLE_GL_PROGRAM(program, kVS, kFS);
10974 drawQuad(program, "position", 0.5f);
10975 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10976 }
10977
10978 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)10979 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
10980 {
10981 constexpr char kVS[] = R"(precision mediump float;
10982 attribute highp vec4 position;
10983 varying vec2 out0;
10984
10985 void main()
10986 {
10987 #define BBB 1
10988 #define AAA(defi, ned) defi ## ned(BBB)
10989
10990 #if AAA(defi, ned)
10991 out0 = vec2(0.0, 1.0);
10992 #else
10993 out0 = vec2(1.0, 0.0);
10994 #endif
10995 gl_Position = position;
10996 })";
10997
10998 constexpr char kFS[] = R"(precision mediump float;
10999 varying vec2 out0;
11000 void main()
11001 {
11002 gl_FragColor = vec4(out0, 0, 1);
11003 })";
11004
11005 GLuint program = CompileProgram(kVS, kFS);
11006 EXPECT_EQ(0u, program);
11007 glDeleteProgram(program);
11008 }
11009
11010 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)11011 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
11012 {
11013 constexpr char kVS[] = R"(precision mediump float;
11014 attribute highp vec4 position;
11015 varying vec2 out0;
11016
11017 void main()
11018 {
11019 #define BBB 1
11020 #define AAA(defined) defined(BBB)
11021
11022 #if AAA(defined)
11023 out0 = vec2(0.0, 1.0);
11024 #else
11025 out0 = vec2(1.0, 0.0);
11026 #endif
11027 gl_Position = position;
11028 })";
11029
11030 constexpr char kFS[] = R"(precision mediump float;
11031 varying vec2 out0;
11032 void main()
11033 {
11034 gl_FragColor = vec4(out0, 0, 1);
11035 })";
11036
11037 GLuint program = CompileProgram(kVS, kFS);
11038 EXPECT_EQ(0u, program);
11039 glDeleteProgram(program);
11040 }
11041
11042 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)11043 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
11044 {
11045 constexpr char kVS[] = R"(precision mediump float;
11046 attribute highp vec4 position;
11047 varying float out0;
11048
11049 void main()
11050 {
11051 #define AAA defined(BBB)
11052
11053 #if !AAA
11054 out0 = 1.0;
11055 #else
11056 out0 = 0.0;
11057 #endif
11058 gl_Position = dEQP_Position;
11059 })";
11060
11061 constexpr char kFS[] = R"(precision mediump float;
11062 varying float out0;
11063 void main()
11064 {
11065 gl_FragColor = vec4(out0, 0, 0, 1);
11066 })";
11067
11068 GLuint program = CompileProgram(kVS, kFS);
11069 EXPECT_EQ(0u, program);
11070 glDeleteProgram(program);
11071 }
11072
11073 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)11074 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
11075 {
11076 constexpr char kVS[] = R"(void main()
11077 {
11078 gl_Position = vec4(1, 0, 0, 1);
11079 })";
11080
11081 constexpr char kFS[] = R"(#if defined(GL_ES)
11082 precision mediump float;
11083 void main()
11084 {
11085 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
11086 }
11087 #else
11088 foo
11089 #endif
11090 )";
11091
11092 ANGLE_GL_PROGRAM(program, kVS, kFS);
11093 }
11094
11095 // Test that inactive output variables compile ok in combination with initOutputVariables
11096 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)11097 TEST_P(WebGL2GLSLTest, InactiveOutput)
11098 {
11099 constexpr char kFS[] = R"(#version 300 es
11100 precision highp float;
11101 out vec4 _cassgl_2_;
11102 void main()
11103 {
11104 })";
11105
11106 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
11107 EXPECT_NE(shader, 0u);
11108 }
11109
11110 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)11111 TEST_P(GLSLTest, ValidIndexClampES100)
11112 {
11113 // http://anglebug.com/42264558
11114 ANGLE_SKIP_TEST_IF(IsD3D9());
11115
11116 constexpr char kFS[] = R"(
11117 precision mediump float;
11118 uniform int u;
11119 uniform mat4 m[2];
11120 void main()
11121 {
11122 gl_FragColor = vec4(m[u][1].xyz, 1);
11123 }
11124 )";
11125
11126 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11127 glUseProgram(program);
11128
11129 GLint uniformLocation = glGetUniformLocation(program, "u");
11130 ASSERT_NE(-1, uniformLocation);
11131
11132 GLint matrixLocation = glGetUniformLocation(program, "m");
11133 ASSERT_NE(matrixLocation, -1);
11134 const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
11135 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
11136 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
11137 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
11138 glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
11139
11140 glUniform1i(uniformLocation, 1);
11141 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11142 EXPECT_GL_NO_ERROR();
11143
11144 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11145 }
11146
11147 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)11148 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
11149 {
11150 constexpr char kFS[] = R"(#version 300 es
11151 precision mediump float;
11152 out vec4 color;
11153 uniform int u;
11154 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
11155 void main()
11156 {
11157 color = vec4(m[u][2].xyz, 1);
11158 }
11159 )";
11160
11161 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11162 glUseProgram(program);
11163
11164 GLint uniformLocation = glGetUniformLocation(program, "u");
11165 ASSERT_NE(-1, uniformLocation);
11166
11167 glUniform1i(uniformLocation, 2);
11168 EXPECT_GL_NO_ERROR();
11169 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11170 EXPECT_GL_NO_ERROR();
11171
11172 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11173 }
11174
11175 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)11176 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
11177 {
11178 constexpr char kFS[] = R"(#version 300 es
11179 precision mediump float;
11180
11181 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
11182 const mat4x2 matB = mat4x2(1.0/2.0, 1.0/4.0, 1.0/8.0, 1.0/16.0, 1.0/32.0, 1.0/64.0, 1.0/128.0, 1.0/256.0);
11183
11184 out vec4 color;
11185
11186 void main()
11187 {
11188 mat4x2 result = matrixCompMult(matA, matB);
11189 vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
11190 if (vresult == vec2(4.0, 4.0))
11191 {
11192 color = vec4(0.0, 1.0, 0.0, 1.0);
11193 }
11194 else
11195 {
11196 color = vec4(1.0, 0.0, 0.0, 1.0);
11197 }
11198 })";
11199
11200 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11201 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11202 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11203 }
11204
11205 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)11206 TEST_P(GLSLTest_ES3, InitSameNameArray)
11207 {
11208 constexpr char kFS[] = R"(#version 300 es
11209 precision highp float;
11210 out vec4 my_FragColor;
11211
11212 void main()
11213 {
11214 float arr[2] = float[2](1.0, 1.0);
11215 {
11216 float arr[2] = arr;
11217 my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
11218 }
11219 })";
11220
11221 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11222 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11223 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11224 }
11225
11226 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)11227 TEST_P(GLSLTest, FragData)
11228 {
11229 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
11230 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11231 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11232 EXPECT_GL_NO_ERROR();
11233 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11234 }
11235
11236 // Tests using gl_FragData[0] instead of gl_FragColor with GL_SAMPLE_ALPHA_TO_COVERAGE
11237 // Regression test for https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5520
TEST_P(GLSLTest,FragData_AlphaToCoverage)11238 TEST_P(GLSLTest, FragData_AlphaToCoverage)
11239 {
11240 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
11241 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11242 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
11243 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11244 EXPECT_GL_NO_ERROR();
11245 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11246 }
11247
11248 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)11249 TEST_P(GLSLTest, MemoryExhaustedTest)
11250 {
11251 GLuint program =
11252 CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
11253 EXPECT_NE(0u, program);
11254 }
11255
11256 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)11257 TEST_P(GLSLTest, InactiveSamplersInStruct)
11258 {
11259 constexpr char kVS[] = R"(attribute vec4 a_position;
11260 void main() {
11261 gl_Position = a_position;
11262 })";
11263
11264 constexpr char kFS[] = R"(precision highp float;
11265 struct S
11266 {
11267 vec4 v;
11268 sampler2D t[10];
11269 };
11270 uniform S s;
11271 void main() {
11272 gl_FragColor = s.v;
11273 })";
11274
11275 ANGLE_GL_PROGRAM(program, kVS, kFS);
11276
11277 drawQuad(program, "a_position", 0.5f);
11278 }
11279
11280 // Helper functions for MixedRowAndColumnMajorMatrices* tests
11281
11282 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)11283 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
11284 {
11285 return (value + alignment - 1) & ~(alignment - 1);
11286 }
11287
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)11288 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
11289 {
11290 unsigned int outputInitData = 0;
11291 glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
11292 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11293 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
11294 EXPECT_GL_NO_ERROR();
11295 }
11296
11297 // Fill provided buffer with matrices based on the given dimensions. The buffer should be large
11298 // enough to accomodate the data.
FillBuffer(const std::pair<uint32_t,uint32_t> matrixDims[],const bool matrixIsColMajor[],size_t matrixCount,float data[],bool isStd430,bool isTransposed)11299 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
11300 const bool matrixIsColMajor[],
11301 size_t matrixCount,
11302 float data[],
11303 bool isStd430,
11304 bool isTransposed)
11305 {
11306 size_t offset = 0;
11307 for (size_t m = 0; m < matrixCount; ++m)
11308 {
11309 uint32_t cols = matrixDims[m].first;
11310 uint32_t rows = matrixDims[m].second;
11311 bool isColMajor = matrixIsColMajor[m] != isTransposed;
11312
11313 uint32_t arraySize = isColMajor ? cols : rows;
11314 uint32_t arrayElementComponents = isColMajor ? rows : cols;
11315 // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
11316 // MixedRowAndColumnMajorMatrices* tests don't use). With std430, small matrices can have
11317 // a stride of 2 between rows/columns.
11318 uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
11319
11320 offset = RoundUpPow2(offset, stride);
11321
11322 for (uint32_t i = 0; i < arraySize; ++i)
11323 {
11324 for (uint32_t c = 0; c < arrayElementComponents; ++c)
11325 {
11326 uint32_t row = isColMajor ? c : i;
11327 uint32_t col = isColMajor ? i : c;
11328
11329 data[offset + i * stride + c] = col * 4 + row;
11330 }
11331 }
11332
11333 offset += arraySize * stride;
11334 }
11335 return offset;
11336 }
11337
11338 // Initialize and bind the buffer.
11339 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)11340 void InitBuffer(GLuint program,
11341 const char *name,
11342 GLuint buffer,
11343 uint32_t bindingIndex,
11344 const T data[],
11345 uint32_t dataSize,
11346 bool isUniform)
11347 {
11348 GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
11349
11350 glBindBufferBase(bindPoint, bindingIndex, buffer);
11351 glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
11352
11353 if (isUniform)
11354 {
11355 GLint blockIndex = glGetUniformBlockIndex(program, name);
11356 glUniformBlockBinding(program, blockIndex, bindingIndex);
11357 }
11358 }
11359
11360 // Verify that buffer data is written by the shader as expected.
11361 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)11362 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
11363 {
11364 uint32_t sizeInBytes = dataSize * sizeof(*data);
11365
11366 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11367
11368 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
11369
11370 const T *ptr = reinterpret_cast<const T *>(
11371 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeInBytes, GL_MAP_READ_BIT));
11372
11373 bool isCorrect = memcmp(ptr, data, sizeInBytes) == 0;
11374 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11375
11376 return isCorrect;
11377 }
11378
11379 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)11380 bool VerifySuccess(GLuint buffer)
11381 {
11382 uint32_t success = 1;
11383 return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
11384 }
11385
11386 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
11387 // both std140 and std430 layouts. Tests many combinations of std140 vs std430, struct being used
11388 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
11389 // nested structs, matrix arrays, inout parameters etc.
11390 //
11391 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)11392 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
11393 {
11394 GLint maxComputeShaderStorageBlocks;
11395 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
11396
11397 // The test uses 9 SSBOs. Skip if not that many are supported.
11398 ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
11399
11400 // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
11401 // UBO also see it as row-major despite explicit column-major qualifier.
11402 // http://anglebug.com/42262474
11403 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
11404
11405 // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
11406 // read column-major despite explicit row-major qualifier. http://anglebug.com/42262481
11407 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11408
11409 // Fails on windows AMD on GL: http://anglebug.com/42262482
11410 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11411
11412 // Fails to compile the shader on Android. http://anglebug.com/42262483
11413 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11414
11415 // Fails on assertion in translation to D3D. http://anglebug.com/42262486
11416 ANGLE_SKIP_TEST_IF(IsD3D11());
11417
11418 // Fails on SSBO validation on Android/Vulkan. http://anglebug.com/42262485
11419 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
11420
11421 // Fails input verification as well as std140 SSBO validation. http://anglebug.com/42262489
11422 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
11423
11424 // Fails on ARM on Vulkan. http://anglebug.com/42263107
11425 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
11426
11427 constexpr char kCS[] = R"(#version 310 es
11428 precision highp float;
11429 layout(local_size_x=1) in;
11430
11431 struct Inner
11432 {
11433 mat3x4 m3c4r;
11434 mat4x3 m4c3r;
11435 };
11436
11437 struct Matrices
11438 {
11439 mat2 m2c2r;
11440 mat2x3 m2c3r[2];
11441 mat3x2 m3c2r;
11442 Inner inner;
11443 };
11444
11445 // For simplicity, the layouts are either of:
11446 // - col-major mat4, row-major rest
11447 // - row-major mat4, col-major rest
11448 //
11449 // The former is tagged with c, the latter with r.
11450 layout(std140, column_major) uniform Ubo140c
11451 {
11452 mat4 m4c4r;
11453 layout(row_major) Matrices m;
11454 } ubo140cIn;
11455
11456 layout(std140, row_major) uniform Ubo140r
11457 {
11458 mat4 m4c4r;
11459 layout(column_major) Matrices m;
11460 } ubo140rIn;
11461
11462 layout(std140, row_major, binding = 0) buffer Ssbo140c
11463 {
11464 layout(column_major) mat4 m4c4r;
11465 Matrices m;
11466 } ssbo140cIn;
11467
11468 layout(std140, column_major, binding = 1) buffer Ssbo140r
11469 {
11470 layout(row_major) mat4 m4c4r;
11471 Matrices m;
11472 } ssbo140rIn;
11473
11474 layout(std430, column_major, binding = 2) buffer Ssbo430c
11475 {
11476 mat4 m4c4r;
11477 layout(row_major) Matrices m;
11478 } ssbo430cIn;
11479
11480 layout(std430, row_major, binding = 3) buffer Ssbo430r
11481 {
11482 mat4 m4c4r;
11483 layout(column_major) Matrices m;
11484 } ssbo430rIn;
11485
11486 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
11487 {
11488 layout(column_major) mat4 m4c4r;
11489 Matrices m;
11490 } ssbo140cOut;
11491
11492 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
11493 {
11494 layout(row_major) mat4 m4c4r;
11495 Matrices m;
11496 } ssbo140rOut;
11497
11498 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
11499 {
11500 mat4 m4c4r;
11501 layout(row_major) Matrices m;
11502 } ssbo430cOut;
11503
11504 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
11505 {
11506 mat4 m4c4r;
11507 layout(column_major) Matrices m;
11508 } ssbo430rOut;
11509
11510 layout(std140, binding = 8) buffer Result
11511 {
11512 uint success;
11513 } resultOut;
11514
11515 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11516 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
11517
11518 #define VERIFY_IN(result, mat, cols, rows) \
11519 EXPECT(result, mat[0].x, 0.0); \
11520 EXPECT(result, mat[0][1], 1.0); \
11521 EXPECTV(result, mat[0].xy, vec2(0, 1)); \
11522 EXPECTV(result, mat[1].xy, vec2(4, 5)); \
11523 for (int c = 0; c < cols; ++c) \
11524 { \
11525 for (int r = 0; r < rows; ++r) \
11526 { \
11527 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11528 } \
11529 }
11530
11531 #define COPY(matIn, matOut, cols, rows) \
11532 matOut = matOut + matIn; \
11533 /* random operations for testing */ \
11534 matOut[0].x += matIn[0].x + matIn[1].x; \
11535 matOut[0].x -= matIn[1].x; \
11536 matOut[0][1] += matIn[0][1]; \
11537 matOut[1] += matIn[1]; \
11538 matOut[1].xy -= matIn[1].xy; \
11539 /* undo the above to get back matIn */ \
11540 matOut[0].x -= matIn[0].x; \
11541 matOut[0][1] -= matIn[0][1]; \
11542 matOut[1] -= matIn[1]; \
11543 matOut[1].xy += matIn[1].xy;
11544
11545 bool verifyMatrices(in Matrices m)
11546 {
11547 bool result = true;
11548 VERIFY_IN(result, m.m2c2r, 2, 2);
11549 VERIFY_IN(result, m.m2c3r[0], 2, 3);
11550 VERIFY_IN(result, m.m2c3r[1], 2, 3);
11551 VERIFY_IN(result, m.m3c2r, 3, 2);
11552 VERIFY_IN(result, m.inner.m3c4r, 3, 4);
11553 VERIFY_IN(result, m.inner.m4c3r, 4, 3);
11554 return result;
11555 }
11556
11557 mat4 copyMat4(in mat4 m)
11558 {
11559 return m;
11560 }
11561
11562 void copyMatrices(in Matrices mIn, inout Matrices mOut)
11563 {
11564 COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
11565 COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
11566 COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
11567 COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
11568 COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
11569 COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
11570 }
11571
11572 void main()
11573 {
11574 bool result = true;
11575
11576 VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
11577 VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
11578 EXPECT(result, verifyMatrices(ubo140cIn.m), true);
11579
11580 VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
11581 VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
11582 EXPECT(result, verifyMatrices(ubo140rIn.m), true);
11583
11584 VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
11585 VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
11586 EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
11587
11588 VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
11589 VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
11590 EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
11591
11592 VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
11593 VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
11594 EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
11595
11596 VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
11597 VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
11598 EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
11599
11600 // Only assign to SSBO from a single invocation.
11601 if (gl_GlobalInvocationID.x == 0u)
11602 {
11603 ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
11604 copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
11605 ssbo140cOut.m.m2c3r[1] = mat2x3(0);
11606 COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
11607
11608 ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
11609 copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
11610 ssbo140rOut.m.inner.m3c4r = mat3x4(0);
11611 COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
11612
11613 ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
11614 copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
11615 ssbo430cOut.m.m3c2r = mat3x2(0);
11616 COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
11617
11618 ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
11619 copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
11620 ssbo430rOut.m.inner.m4c3r = mat4x3(0);
11621 COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
11622
11623 resultOut.success = uint(result);
11624 }
11625 })";
11626
11627 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11628 EXPECT_GL_NO_ERROR();
11629
11630 constexpr size_t kMatrixCount = 7;
11631 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11632 {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
11633 };
11634 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11635 true, false, false, false, false, false, false,
11636 };
11637
11638 float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
11639 float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
11640 float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
11641 float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
11642 float dataZeros[kMatrixCount * 4 * 4] = {};
11643
11644 const uint32_t sizeStd140ColMajor =
11645 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
11646 const uint32_t sizeStd140RowMajor =
11647 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
11648 const uint32_t sizeStd430ColMajor =
11649 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
11650 const uint32_t sizeStd430RowMajor =
11651 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
11652
11653 GLBuffer uboStd140ColMajor, uboStd140RowMajor;
11654 GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
11655 GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
11656 GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
11657 GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
11658
11659 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11660 true);
11661 InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11662 true);
11663 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11664 false);
11665 InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11666 false);
11667 InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
11668 false);
11669 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
11670 false);
11671 InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
11672 false);
11673 InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
11674 false);
11675 InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
11676 false);
11677 InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
11678 false);
11679 EXPECT_GL_NO_ERROR();
11680
11681 GLBuffer outputBuffer;
11682 CreateOutputBuffer(&outputBuffer, 8);
11683
11684 glUseProgram(program);
11685 glDispatchCompute(1, 1, 1);
11686 EXPECT_GL_NO_ERROR();
11687 EXPECT_TRUE(VerifySuccess(outputBuffer));
11688
11689 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
11690 EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
11691 EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
11692 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
11693 }
11694
11695 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)11696 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
11697 {
11698 constexpr char kFS[] = R"(#version 300 es
11699 precision highp float;
11700 out vec4 outColor;
11701
11702 layout(std140, row_major) uniform Ubo
11703 {
11704 mat4 m1;
11705 };
11706
11707 void main()
11708 {
11709 outColor = m1[3] / 255.0;
11710 })";
11711
11712 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11713 EXPECT_GL_NO_ERROR();
11714
11715 constexpr size_t kMatrixCount = 1;
11716 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11717 {4, 4},
11718 };
11719 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11720 false,
11721 };
11722
11723 float data[kMatrixCount * 4 * 4] = {};
11724
11725 const uint32_t size =
11726 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11727
11728 GLBuffer ubos;
11729
11730 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11731
11732 EXPECT_GL_NO_ERROR();
11733
11734 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11735 EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
11736 }
11737
11738 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)11739 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
11740 {
11741 constexpr char kFS[] = R"(#version 300 es
11742 precision highp float;
11743 out vec4 outColor;
11744
11745 layout(std140, row_major) uniform Ubo
11746 {
11747 mat2x3 m1;
11748 };
11749
11750 void main()
11751 {
11752 outColor = vec4(m1[1], 0) / 255.0;
11753 })";
11754
11755 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11756 EXPECT_GL_NO_ERROR();
11757
11758 constexpr size_t kMatrixCount = 1;
11759 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11760 {2, 3},
11761 };
11762 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11763 false,
11764 };
11765
11766 float data[kMatrixCount * 3 * 4] = {};
11767
11768 const uint32_t size =
11769 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11770
11771 GLBuffer ubos;
11772
11773 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11774
11775 EXPECT_GL_NO_ERROR();
11776
11777 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11778 EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
11779 }
11780
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)11781 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
11782 {
11783 constexpr char kFS[] = R"(#version 300 es
11784 precision highp float;
11785 out vec4 outColor;
11786
11787 layout(std140, row_major) uniform Ubo
11788 {
11789 mat3x2 m1;
11790 };
11791
11792 void main()
11793 {
11794 outColor = vec4(m1[2], 0, 0) / 255.0;
11795 })";
11796
11797 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11798 EXPECT_GL_NO_ERROR();
11799
11800 constexpr size_t kMatrixCount = 1;
11801 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11802 {3, 2},
11803 };
11804 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11805 false,
11806 };
11807
11808 float data[kMatrixCount * 2 * 4] = {};
11809
11810 const uint32_t size =
11811 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11812
11813 GLBuffer ubos;
11814
11815 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11816
11817 EXPECT_GL_NO_ERROR();
11818
11819 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11820 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
11821 }
11822
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)11823 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
11824 {
11825 // Many OpenGL drivers seem to fail this
11826 ANGLE_SKIP_TEST_IF((IsLinux() || IsMac()) && IsOpenGL());
11827
11828 constexpr char kFS[] = R"(#version 300 es
11829 precision mediump float;
11830
11831 uniform Ubo {
11832 layout(row_major) mat4 u_mat[3];
11833 layout(row_major) mat4 u_ndx[3];
11834 } stuff;
11835
11836 precision highp float;
11837 out vec4 outColor;
11838
11839 void main() {
11840 outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
11841 }
11842 )";
11843
11844 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11845 EXPECT_GL_NO_ERROR();
11846
11847 typedef float vec4[4];
11848 typedef vec4 mat4[4];
11849
11850 constexpr size_t kMatrixCount = 6;
11851 mat4 data[] = {
11852 {
11853 {0, 1, 2, 3}, //
11854 {4, 5, 6, 7}, //
11855 {8, 9, 10, 11}, //
11856 {12, 13, 14, 15}, //
11857 },
11858 {
11859 // +-- we should be looking up this column
11860 // V
11861 {0, 4, 8, 12}, //
11862 {1, 5, 9, 13}, //
11863 {2, 6, 10, 14}, //
11864 {3, 7, 11, 15}, //
11865 },
11866 {
11867 {0, 2, 4, 6}, //
11868 {8, 10, 12, 14}, //
11869 {16, 18, 20, 22}, //
11870 {24, 26, 28, 30}, //
11871 },
11872 {
11873 {0, 0, 0, 0}, //
11874 {0, 0, 0, 0}, //
11875 {0, 0, 0, 0}, //
11876 {0, 0, 0, 0}, //
11877 },
11878 {
11879 {0, 0, 0, 0}, //
11880 {0, 0, 0, 2}, //
11881 {0, 0, 0, 0}, //
11882 {0, 1, 0, 0},
11883 // ^
11884 // +-- we should be using this element
11885 },
11886 {
11887 {0, 0, 0, 0}, //
11888 {0, 0, 0, 0}, //
11889 {0, 0, 0, 0}, //
11890 {0, 0, 0, 0}, //
11891 },
11892 };
11893
11894 GLBuffer ubos;
11895 InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
11896 EXPECT_GL_NO_ERROR();
11897
11898 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11899 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
11900 }
11901
11902 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)11903 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
11904 {
11905 // Fails to compile the shader on Android: http://anglebug.com/42262483
11906 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11907
11908 // http://anglebug.com/42262481
11909 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11910
11911 // Fails on Mac on Intel and AMD: http://anglebug.com/42262487
11912 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11913
11914 // Fails on windows AMD on GL: http://anglebug.com/42262482
11915 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11916
11917 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
11918 ANGLE_SKIP_TEST_IF(IsD3D11());
11919
11920 constexpr char kFS[] = R"(#version 300 es
11921 precision highp float;
11922 out vec4 outColor;
11923
11924 layout(std140, column_major) uniform Ubo
11925 {
11926 mat4 m1;
11927 layout(row_major) mat4 m2;
11928 } ubo[3];
11929
11930 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11931
11932 #define VERIFY_IN(result, mat, cols, rows) \
11933 for (int c = 0; c < cols; ++c) \
11934 { \
11935 for (int r = 0; r < rows; ++r) \
11936 { \
11937 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11938 } \
11939 }
11940
11941 void main()
11942 {
11943 bool result = true;
11944
11945 VERIFY_IN(result, ubo[0].m1, 4, 4);
11946 VERIFY_IN(result, ubo[0].m2, 4, 4);
11947
11948 VERIFY_IN(result, ubo[1].m1, 4, 4);
11949 VERIFY_IN(result, ubo[1].m2, 4, 4);
11950
11951 VERIFY_IN(result, ubo[2].m1, 4, 4);
11952 VERIFY_IN(result, ubo[2].m2, 4, 4);
11953
11954 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11955 })";
11956
11957 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11958 EXPECT_GL_NO_ERROR();
11959
11960 constexpr size_t kMatrixCount = 2;
11961 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11962 {4, 4},
11963 {4, 4},
11964 };
11965 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11966 true,
11967 false,
11968 };
11969
11970 float data[kMatrixCount * 4 * 4] = {};
11971
11972 const uint32_t size =
11973 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11974
11975 GLBuffer ubos[3];
11976
11977 InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
11978 InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
11979 InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
11980
11981 EXPECT_GL_NO_ERROR();
11982
11983 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11984 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11985 }
11986
11987 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)11988 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
11989 {
11990 // Fails on Mac on Intel and AMD: http://anglebug.com/42262487
11991 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11992
11993 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
11994 ANGLE_SKIP_TEST_IF(IsD3D11());
11995
11996 constexpr char kFS[] = R"(#version 300 es
11997 precision highp float;
11998 out vec4 outColor;
11999
12000 struct S
12001 {
12002 mat2x3 m2[3];
12003 };
12004
12005 layout(std140, column_major) uniform Ubo
12006 {
12007 mat4 m1;
12008 layout(row_major) S s[2];
12009 } ubo;
12010
12011 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
12012
12013 #define VERIFY_IN(result, mat, cols, rows) \
12014 for (int c = 0; c < cols; ++c) \
12015 { \
12016 for (int r = 0; r < rows; ++r) \
12017 { \
12018 EXPECT(result, mat[c][r], float(c * 4 + r)); \
12019 } \
12020 }
12021
12022 bool verify2x3(mat2x3 mat)
12023 {
12024 bool result = true;
12025
12026 for (int c = 0; c < 2; ++c)
12027 {
12028 for (int r = 0; r < 3; ++r)
12029 {
12030 EXPECT(result, mat[c][r], float(c * 4 + r));
12031 }
12032 }
12033
12034 return result;
12035 }
12036
12037 void main()
12038 {
12039 bool result = true;
12040
12041 int sideEffect = 0;
12042 VERIFY_IN(result, ubo.m1, 4, 4);
12043 EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
12044 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
12045 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
12046
12047 EXPECT(result, sideEffect, 2);
12048
12049 EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
12050 EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
12051 EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
12052
12053 EXPECT(result, sideEffect, 4);
12054
12055 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12056 })";
12057
12058 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12059 EXPECT_GL_NO_ERROR();
12060
12061 constexpr size_t kMatrixCount = 7;
12062 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12063 {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
12064 };
12065 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12066 true, false, false, false, false, false, false,
12067 };
12068
12069 float data[kMatrixCount * 4 * 4] = {};
12070
12071 const uint32_t size =
12072 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12073
12074 GLBuffer ubo;
12075 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12076
12077 EXPECT_GL_NO_ERROR();
12078
12079 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12080 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12081 }
12082
12083 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)12084 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
12085 {
12086 // http://anglebug.com/42262481
12087 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12088
12089 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12090 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12091 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12092
12093 constexpr char kFS[] = R"(#version 300 es
12094 precision highp float;
12095 out vec4 outColor;
12096
12097 layout(std140, column_major) uniform Ubo
12098 {
12099 mat4 m1;
12100 layout(row_major) mat4 m2[2];
12101 } ubo;
12102
12103 void main()
12104 {
12105 bool result = true;
12106
12107 int x = 0;
12108 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
12109 {
12110 result = true;
12111 }
12112 else
12113 {
12114 result = false;
12115 }
12116
12117 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12118 })";
12119
12120 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12121 EXPECT_GL_NO_ERROR();
12122
12123 constexpr size_t kMatrixCount = 3;
12124 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12125 {4, 4},
12126 {4, 4},
12127 {4, 4},
12128 };
12129 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12130
12131 float data[kMatrixCount * 4 * 4] = {};
12132
12133 const uint32_t size =
12134 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12135
12136 GLBuffer ubo;
12137 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12138
12139 EXPECT_GL_NO_ERROR();
12140
12141 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12142 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12143 }
12144
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)12145 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
12146 {
12147 // http://anglebug.com/42262481
12148 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12149
12150 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12151 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12152 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12153
12154 constexpr char kFS[] = R"(#version 300 es
12155 precision highp float;
12156 out vec4 outColor;
12157
12158 layout(std140, column_major) uniform Ubo
12159 {
12160 mat4 m1;
12161 layout(row_major) mat4 m2[2];
12162 } ubo;
12163
12164 void main()
12165 {
12166 bool result = false;
12167
12168 for(int x = 0; x < 1; ++x)
12169 {
12170 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
12171 result = true;
12172 }
12173 }
12174 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12175 })";
12176
12177 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12178 EXPECT_GL_NO_ERROR();
12179
12180 constexpr size_t kMatrixCount = 3;
12181 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12182 {4, 4},
12183 {4, 4},
12184 {4, 4},
12185 };
12186 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12187
12188 float data[kMatrixCount * 4 * 4] = {};
12189
12190 const uint32_t size =
12191 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12192
12193 GLBuffer ubo;
12194 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12195
12196 EXPECT_GL_NO_ERROR();
12197
12198 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12199 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12200 }
12201
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)12202 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
12203 {
12204 // http://anglebug.com/42262481
12205 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12206
12207 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12208 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12209 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12210
12211 constexpr char kFS[] = R"(#version 300 es
12212 precision highp float;
12213 out vec4 outColor;
12214
12215 layout(std140, column_major) uniform Ubo
12216 {
12217 mat4 m1;
12218 layout(row_major) mat4 m2[2];
12219 } ubo;
12220
12221 void main()
12222 {
12223 bool result = false;
12224
12225 for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
12226 {
12227 result = true;
12228 }
12229 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12230 })";
12231
12232 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12233 EXPECT_GL_NO_ERROR();
12234
12235 constexpr size_t kMatrixCount = 3;
12236 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12237 {4, 4},
12238 {4, 4},
12239 {4, 4},
12240 };
12241 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12242
12243 float data[kMatrixCount * 4 * 4] = {};
12244
12245 const uint32_t size =
12246 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12247
12248 GLBuffer ubo;
12249 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12250
12251 EXPECT_GL_NO_ERROR();
12252
12253 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12254 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12255 }
12256
12257 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)12258 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
12259 {
12260 // Fails on Android: http://anglebug.com/42262483
12261 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
12262
12263 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12264 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12265 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12266
12267 constexpr char kFS[] = R"(#version 300 es
12268 precision highp float;
12269 out vec4 outColor;
12270
12271 layout(std140, column_major) uniform Ubo
12272 {
12273 mat4 m1;
12274 layout(row_major) mat4 m2[2];
12275 } ubo;
12276
12277 void main()
12278 {
12279 bool result = true;
12280
12281 int x = 0;
12282 if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
12283 {
12284 // First x == 1 should prevent the side effect of the second expression (x = 1) from
12285 // being executed. If x = 1 is run before the if, the condition of the if would be true,
12286 // which is a failure.
12287 result = false;
12288 }
12289 if (x == 1)
12290 {
12291 result = false;
12292 }
12293
12294 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12295 })";
12296
12297 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12298 EXPECT_GL_NO_ERROR();
12299
12300 constexpr size_t kMatrixCount = 3;
12301 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12302 {4, 4},
12303 {4, 4},
12304 {4, 4},
12305 };
12306 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12307
12308 float data[kMatrixCount * 4 * 4] = {};
12309
12310 const uint32_t size =
12311 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12312
12313 GLBuffer ubo;
12314 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12315
12316 EXPECT_GL_NO_ERROR();
12317
12318 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12319 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12320 }
12321
12322 // Test that indexing swizzles out of bounds fails
TEST_P(GLSLTest_ES3,OutOfBoundsIndexingOfSwizzle)12323 TEST_P(GLSLTest_ES3, OutOfBoundsIndexingOfSwizzle)
12324 {
12325 constexpr char kFS[] = R"(#version 300 es
12326 precision mediump float;
12327 out vec4 colorOut;
12328 uniform vec3 colorIn;
12329
12330 void main()
12331 {
12332 colorOut = vec4(colorIn.yx[2], 0, 0, 1);
12333 })";
12334
12335 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
12336 EXPECT_EQ(0u, shader);
12337 }
12338
12339 // Test that indexing l-value swizzles work
TEST_P(GLSLTest_ES3,IndexingOfSwizzledLValuesShouldWork)12340 TEST_P(GLSLTest_ES3, IndexingOfSwizzledLValuesShouldWork)
12341 {
12342 constexpr char kFS[] = R"(#version 300 es
12343 precision mediump float;
12344 out vec4 oColor;
12345
12346 bool do_test() {
12347 highp vec3 expected = vec3(3.0, 2.0, 1.0);
12348 highp vec3 vec;
12349
12350 vec.yzx[2] = 3.0;
12351 vec.yzx[1] = 1.0;
12352 vec.yzx[0] = 2.0;
12353
12354 return vec == expected;
12355 }
12356
12357 void main()
12358 {
12359 oColor = vec4(do_test(), 0, 0, 1);
12360 })";
12361
12362 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12363 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12364 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12365 ASSERT_GL_NO_ERROR();
12366 }
12367
12368 // Test that indexing r-value swizzles work
TEST_P(GLSLTest_ES3,IndexingOfSwizzledRValuesShouldWork)12369 TEST_P(GLSLTest_ES3, IndexingOfSwizzledRValuesShouldWork)
12370 {
12371 constexpr char kFS[] = R"(#version 300 es
12372 precision mediump float;
12373 out vec4 oColor;
12374
12375 bool do_test() {
12376 highp vec3 expected = vec3(3.0, 2.0, 1.0);
12377 highp vec3 vecA = vec3(1.0, 3.0, 2.0);
12378 highp vec3 vecB;
12379
12380 vecB.x = vecA.zxy[2];
12381 vecB.y = vecA.zxy[0];
12382 vecB.z = vecA.zxy[1];
12383
12384 return vecB == expected;
12385 }
12386
12387 void main()
12388 {
12389 oColor = vec4(do_test(), 0, 0, 1);
12390 })";
12391
12392 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12393 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12394 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12395 ASSERT_GL_NO_ERROR();
12396 }
12397
12398 // Test that dynamic indexing of swizzled l-values should work.
12399 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)12400 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
12401 {
12402 // The shader first assigns v.x to v.z (1.0)
12403 // Then v.y to v.y (2.0)
12404 // Then v.z to v.x (1.0)
12405 constexpr char kFS[] = R"(#version 300 es
12406 precision highp float;
12407 out vec4 my_FragColor;
12408 void main() {
12409 vec3 v = vec3(1.0, 2.0, 3.0);
12410 for (int i = 0; i < 3; i++) {
12411 v.zyx[i] = v[i];
12412 }
12413 my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12414 })";
12415
12416 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12417 EXPECT_GL_NO_ERROR();
12418 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12419 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12420 }
12421
12422 // Another test for dynamic indexing of swizzled l-values.
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork2)12423 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork2)
12424 {
12425 constexpr char kFS[] = R"(#version 300 es
12426 precision mediump float;
12427 out vec4 oColor;
12428
12429 bool do_test() {
12430 highp vec3 expected = vec3(3.0, 2.0, 1.0);
12431 highp vec3 vec;
12432
12433 for (int i = 0; i < 3; ++i)
12434 {
12435 vec.zyx[i] = float(1 + i);
12436 }
12437
12438 return vec == expected;
12439 }
12440
12441 void main()
12442 {
12443 oColor = vec4(do_test(), 0, 0, 1);
12444 })";
12445
12446 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12447 EXPECT_GL_NO_ERROR();
12448 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12449 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12450 }
12451
12452 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)12453 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
12454 {
12455 constexpr char kFS[] = R"(#version 300 es
12456 precision mediump float;
12457 out vec4 color;
12458
12459 vec4 f(vec4 c)
12460 {
12461 return c;
12462 // dead code
12463 c = vec4(0, 0, 1, 1);
12464 return c;
12465 }
12466
12467 void main()
12468 {
12469 vec4 result = vec4(0, 0.5, 0, 1);
12470 int var = int(result.y * 2.2);
12471
12472 {
12473 if (result.x > 1.0)
12474 {
12475 discard;
12476 // dead code
12477 result = vec4(1, 0, 0, 1);
12478 }
12479 for (int i = 0; i < 3; ++i)
12480 {
12481 if (i < 2)
12482 {
12483 result = f(result);
12484 continue;
12485 // dead code
12486 result = vec4(1, 0, 1, 1);
12487 }
12488 result = f(result);
12489 break;
12490 // dead code
12491 result = vec4(1, 0, 1, 0);
12492 }
12493 while (true)
12494 {
12495 if (result.x > -1.0)
12496 {
12497 {
12498 result = f(result);
12499 {
12500 break;
12501 // dead code
12502 result = vec4(1, 0, 0, 0);
12503 }
12504 // dead code
12505 for (int j = 0; j < 3; ++j)
12506 {
12507 if (j > 1) continue;
12508 result = vec4(0, 0, 1, 0);
12509 color = vec4(0.5, 0, 0.5, 0.5);
12510 return;
12511 }
12512 }
12513 // dead code
12514 result = vec4(0.5, 0, 0, 0);
12515 }
12516 }
12517 switch (var)
12518 {
12519 case 2:
12520 return;
12521 // dead code
12522 color = vec4(0.25, 0, 0.25, 0.25);
12523 case 1:
12524 {
12525 // Make sure this path is not pruned due to the return in the previous case.
12526 result.y += 0.5;
12527 break;
12528 // dead code
12529 color = vec4(0.25, 0, 0, 0);
12530 }
12531 // dead code
12532 color = vec4(0, 0, 0.25, 0);
12533 break;
12534 default:
12535 break;
12536 }
12537
12538 color = result;
12539 return;
12540 // dead code
12541 color = vec4(0, 0, 0.5, 0);
12542 }
12543 // dead code
12544 color = vec4(0, 0, 0, 0.5);
12545 })";
12546
12547 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12548
12549 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12550 EXPECT_GL_NO_ERROR();
12551
12552 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12553 }
12554
12555 // Regression test based on fuzzer issue. If a case has statements that are pruned, and those
12556 // pruned statements in turn have branches, and another case follows, a prior implementation of
12557 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)12558 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
12559 {
12560 constexpr char kFS[] = R"(#version 300 es
12561 precision mediump float;
12562 out vec4 color;
12563 void main()
12564 {
12565 color = vec4(0, 1, 0, 1);
12566 switch(0)
12567 {
12568 case 0:
12569 break;
12570 break;
12571 color = vec4(1, 0, 0, 1); // The bug was pruning this statement twice
12572 default:
12573 color = vec4(0, 0, 1, 1);
12574 break;
12575 }
12576 })";
12577
12578 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12579
12580 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12581 EXPECT_GL_NO_ERROR();
12582
12583 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12584 }
12585
12586 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
12587 // make sure they are all linked ok. The front-end sorts these resources and traverses the list of
12588 // "uniforms" to find the range for each resource. A bug there was causing some resource ranges to
12589 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)12590 TEST_P(GLSLTest_ES31, MixOfAllResources)
12591 {
12592 // http://anglebug.com/42263641
12593 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
12594
12595 constexpr char kComputeShader[] = R"(#version 310 es
12596 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12597 layout(binding = 1, std430) buffer Output {
12598 uint ubo_value;
12599 uint default_value;
12600 uint sampler_value;
12601 uint ac_value;
12602 uint image_value;
12603 } outbuf;
12604 uniform Input {
12605 uint input_value;
12606 } inbuf;
12607 uniform uint default_uniform;
12608 uniform sampler2D smplr;
12609 layout(binding=0) uniform atomic_uint ac;
12610 layout(r32ui) uniform highp readonly uimage2D image;
12611
12612 void main(void)
12613 {
12614 outbuf.ubo_value = inbuf.input_value;
12615 outbuf.default_value = default_uniform;
12616 outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
12617 outbuf.ac_value = atomicCounterIncrement(ac);
12618 outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
12619 }
12620 )";
12621 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12622 EXPECT_GL_NO_ERROR();
12623
12624 glUseProgram(program);
12625
12626 unsigned int inputData = 89u;
12627 GLBuffer inputBuffer;
12628 glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
12629 glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
12630 GLuint inputBufferIndex = glGetUniformBlockIndex(program, "Input");
12631 ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
12632 glUniformBlockBinding(program, inputBufferIndex, 0);
12633 glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
12634
12635 unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
12636 0x13579BDFu};
12637 GLBuffer outputBuffer;
12638 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12639 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
12640 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12641 EXPECT_GL_NO_ERROR();
12642
12643 unsigned int uniformData = 456u;
12644 GLint uniformLocation = glGetUniformLocation(program, "default_uniform");
12645 ASSERT_NE(uniformLocation, -1);
12646 glUniform1ui(uniformLocation, uniformData);
12647
12648 unsigned int acData = 2u;
12649 GLBuffer atomicCounterBuffer;
12650 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12651 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12652 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12653 EXPECT_GL_NO_ERROR();
12654
12655 unsigned int imageData = 33u;
12656 GLTexture image;
12657 glBindTexture(GL_TEXTURE_2D, image);
12658 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
12659 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
12660 glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
12661 EXPECT_GL_NO_ERROR();
12662
12663 GLColor textureData(127, 18, 189, 211);
12664 GLTexture texture;
12665 glBindTexture(GL_TEXTURE_2D, texture);
12666 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
12667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12669 ASSERT_GL_NO_ERROR();
12670
12671 glDispatchCompute(1, 1, 1);
12672 EXPECT_GL_NO_ERROR();
12673
12674 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12675
12676 // read back
12677 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12678 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12679 EXPECT_EQ(ptr[0], inputData);
12680 EXPECT_EQ(ptr[1], uniformData);
12681 EXPECT_NEAR(ptr[2], textureData.R, 1.0);
12682 EXPECT_EQ(ptr[3], acData);
12683 EXPECT_EQ(ptr[4], imageData);
12684
12685 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12686 }
12687
12688 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)12689 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
12690 {
12691 // http://anglebug.com/42264082
12692 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12693
12694 // anglebug.com/42262476 - no sampler array params on Android
12695 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12696
12697 constexpr char kComputeShader[] = R"(#version 310 es
12698 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12699
12700 layout(binding = 1, std430) buffer Output {
12701 uint success;
12702 } outbuf;
12703
12704 uniform uint initialAcValue;
12705 uniform sampler2D smplr[2][3];
12706 layout(binding=0) uniform atomic_uint ac;
12707
12708 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12709 {
12710 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12711 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12712 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12713 uint aResult = atomicCounterIncrement(a);
12714
12715 return sExpect == sResult && aExpect == aResult;
12716 }
12717
12718 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12719 {
12720 bool success = true;
12721 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
12722 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
12723 return success;
12724 }
12725
12726 void main(void)
12727 {
12728 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
12729 }
12730 )";
12731 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12732 EXPECT_GL_NO_ERROR();
12733
12734 glUseProgram(program);
12735
12736 unsigned int outputInitData = 0x12345678u;
12737 GLBuffer outputBuffer;
12738 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12739 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12740 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12741 EXPECT_GL_NO_ERROR();
12742
12743 unsigned int acData = 2u;
12744 GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
12745 ASSERT_NE(uniformLocation, -1);
12746 glUniform1ui(uniformLocation, acData);
12747
12748 GLBuffer atomicCounterBuffer;
12749 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12750 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12751 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12752 EXPECT_GL_NO_ERROR();
12753
12754 const std::array<GLColor, 6> kTextureData = {
12755 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12756 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
12757 };
12758 GLTexture textures[2][3];
12759
12760 for (int dim1 = 0; dim1 < 2; ++dim1)
12761 {
12762 for (int dim2 = 0; dim2 < 3; ++dim2)
12763 {
12764 int textureUnit = dim1 * 3 + dim2;
12765 glActiveTexture(GL_TEXTURE0 + textureUnit);
12766 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12767 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12768 &kTextureData[textureUnit]);
12769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12771
12772 std::stringstream uniformName;
12773 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12774 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12775 EXPECT_NE(samplerLocation, -1);
12776 glUniform1i(samplerLocation, textureUnit);
12777 }
12778 }
12779 ASSERT_GL_NO_ERROR();
12780
12781 glDispatchCompute(1, 1, 1);
12782 EXPECT_GL_NO_ERROR();
12783
12784 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12785
12786 // read back
12787 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12788 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12789 EXPECT_EQ(ptr[0], 1u);
12790
12791 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12792 }
12793
12794 // Test that array of array of samplers used as function parameter with an index that has a
12795 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)12796 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
12797 {
12798 // http://anglebug.com/42264082
12799 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12800
12801 // anglebug.com/42262476 - no sampler array params on Android
12802 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12803
12804 // Skip if EXT_gpu_shader5 is not enabled.
12805 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12806
12807 constexpr char kComputeShader[] = R"(#version 310 es
12808 #extension GL_EXT_gpu_shader5 : require
12809
12810 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12811
12812 layout(binding = 1, std430) buffer Output {
12813 uint success;
12814 } outbuf;
12815
12816 uniform sampler2D smplr[2][3];
12817 layout(binding=0) uniform atomic_uint ac;
12818
12819 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12820 {
12821 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12822 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12823 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12824 uint aResult = atomicCounter(a);
12825
12826 return sExpect == sResult && aExpect == aResult;
12827 }
12828
12829 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12830 {
12831 bool success = true;
12832 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
12833 s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
12834 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
12835 s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
12836 return success;
12837 }
12838
12839 void main(void)
12840 {
12841 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
12842 }
12843 )";
12844 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12845 EXPECT_GL_NO_ERROR();
12846
12847 glUseProgram(program);
12848
12849 unsigned int outputInitData = 0x12345678u;
12850 GLBuffer outputBuffer;
12851 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12852 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12853 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12854 EXPECT_GL_NO_ERROR();
12855
12856 unsigned int acData = 0u;
12857 GLBuffer atomicCounterBuffer;
12858 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12859 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12860 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12861 EXPECT_GL_NO_ERROR();
12862
12863 const std::array<GLColor, 6> kTextureData = {
12864 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12865 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
12866 };
12867 GLTexture textures[2][3];
12868
12869 for (int dim1 = 0; dim1 < 2; ++dim1)
12870 {
12871 for (int dim2 = 0; dim2 < 3; ++dim2)
12872 {
12873 int textureUnit = dim1 * 3 + dim2;
12874 glActiveTexture(GL_TEXTURE0 + textureUnit);
12875 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12876 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12877 &kTextureData[textureUnit]);
12878 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12879 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12880
12881 std::stringstream uniformName;
12882 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12883 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12884 EXPECT_NE(samplerLocation, -1);
12885 glUniform1i(samplerLocation, textureUnit);
12886 }
12887 }
12888 ASSERT_GL_NO_ERROR();
12889
12890 glDispatchCompute(1, 1, 1);
12891 EXPECT_GL_NO_ERROR();
12892
12893 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12894
12895 // read back
12896 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12897 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12898 EXPECT_EQ(ptr[0], 1u);
12899
12900 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12901 }
12902
testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)12903 void GLSLTest_ES31::testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)
12904 {
12905 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
12906
12907 int maxTextureImageUnits = 0;
12908 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12909 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12910
12911 // anglebug.com/42262476 - no sampler array params on Android
12912 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12913
12914 // http://anglebug.com/42264082
12915 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12916
12917 std::string computeShader;
12918 constexpr char kGLSLVersion[] = R"(#version 310 es
12919 )";
12920 constexpr char kGPUShaderEXT[] = R"(#extension GL_EXT_gpu_shader5 : require
12921 )";
12922 constexpr char kGPUShaderOES[] = R"(#extension GL_OES_gpu_shader5 : require
12923 )";
12924
12925 computeShader.append(kGLSLVersion);
12926 if (usedExtension == APIExtensionVersion::EXT)
12927 {
12928 computeShader.append(kGPUShaderEXT);
12929 }
12930 else
12931 {
12932 computeShader.append(kGPUShaderOES);
12933 }
12934
12935 constexpr char kComputeShaderBody[] = R"(
12936 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12937
12938 layout(binding = 1, std430) buffer Output {
12939 uint success;
12940 } outbuf;
12941
12942 uniform sampler2D smplr[2][3][4];
12943 layout(binding=0) uniform atomic_uint ac;
12944
12945 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
12946 {
12947 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12948 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12949 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
12950 uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
12951 uint aResult = atomicCounter(a);
12952
12953 return sExpect == sResult && aExpect == aResult;
12954 }
12955
12956 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
12957 {
12958 bool success = true;
12959 // [0][0]
12960 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
12961 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
12962 // [1][0]
12963 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
12964 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
12965 // [0][1]
12966 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
12967 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
12968 // [0][2]
12969 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
12970 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
12971 // [1][1]
12972 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
12973 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
12974 // [1][2]
12975 uint acValue = atomicCounterIncrement(ac); // Returns 5
12976 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
12977 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
12978
12979 return success;
12980 }
12981
12982 void main(void)
12983 {
12984 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
12985 }
12986 )";
12987 computeShader.append(kComputeShaderBody);
12988
12989 ANGLE_GL_COMPUTE_PROGRAM(program, computeShader.c_str());
12990 EXPECT_GL_NO_ERROR();
12991
12992 glUseProgram(program);
12993
12994 unsigned int outputInitData = 0x12345678u;
12995 GLBuffer outputBuffer;
12996 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12997 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12998 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12999 EXPECT_GL_NO_ERROR();
13000
13001 unsigned int acData = 0u;
13002 GLBuffer atomicCounterBuffer;
13003 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
13004 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
13005 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
13006 EXPECT_GL_NO_ERROR();
13007
13008 const std::array<GLColor, 24> kTextureData = {
13009 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
13010 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
13011 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
13012 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
13013 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
13014 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
13015 };
13016 GLTexture textures[2][3][4];
13017
13018 for (int dim1 = 0; dim1 < 2; ++dim1)
13019 {
13020 for (int dim2 = 0; dim2 < 3; ++dim2)
13021 {
13022 for (int dim3 = 0; dim3 < 4; ++dim3)
13023 {
13024 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
13025 glActiveTexture(GL_TEXTURE0 + textureUnit);
13026 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
13027 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13028 &kTextureData[textureUnit]);
13029 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13031
13032 std::stringstream uniformName;
13033 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
13034 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13035 EXPECT_NE(samplerLocation, -1);
13036 glUniform1i(samplerLocation, textureUnit);
13037 }
13038 }
13039 }
13040 ASSERT_GL_NO_ERROR();
13041
13042 glDispatchCompute(1, 1, 1);
13043 EXPECT_GL_NO_ERROR();
13044
13045 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13046
13047 // read back
13048 const GLuint *ptr = reinterpret_cast<const GLuint *>(
13049 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13050 EXPECT_EQ(ptr[0], 1u);
13051
13052 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13053 }
13054
13055 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexEXT)13056 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexEXT)
13057 {
13058 // Skip if EXT_gpu_shader5 is not enabled.
13059 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13060 testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::EXT);
13061 }
13062
13063 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexOES)13064 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexOES)
13065 {
13066 // Skip if OES_gpu_shader5 is not enabled.
13067 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_gpu_shader5"));
13068 testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::OES);
13069 }
13070
13071 // Test that array of array of samplers is handled correctly with the comma operator.
TEST_P(GLSLTest,ArrayOfArrayOfSamplerVsComma)13072 TEST_P(GLSLTest, ArrayOfArrayOfSamplerVsComma)
13073 {
13074 int maxTextureImageUnits = 0;
13075 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
13076
13077 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 6);
13078
13079 constexpr char kVS[] = R"(uniform struct {
13080 sampler2D s1, s2[3];
13081 } s[2];
13082
13083 void main()
13084 {
13085 ++gl_Position, s[1].s1;
13086 })";
13087 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
13088 EXPECT_GL_NO_ERROR();
13089 }
13090
13091 // Test that array of array of samplers can be indexed correctly with dynamic indices. Uses
13092 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)13093 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
13094 {
13095 // Skip if EXT_gpu_shader5 is not enabled.
13096 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13097
13098 int maxTextureImageUnits = 0;
13099 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
13100 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
13101
13102 // http://anglebug.com/42263641
13103 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
13104
13105 // anglebug.com/42262476 - no sampler array params on Android
13106 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
13107
13108 // http://anglebug.com/42264082
13109 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
13110
13111 constexpr char kComputeShader[] = R"(#version 310 es
13112 #extension GL_EXT_gpu_shader5 : require
13113
13114 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
13115
13116 layout(binding = 1, std430) buffer Output {
13117 uint success;
13118 } outbuf;
13119
13120 struct I
13121 {
13122 uint index;
13123 };
13124
13125 struct S
13126 {
13127 sampler2D smplr[4];
13128 I nested;
13129 };
13130
13131 struct T
13132 {
13133 S nested[3];
13134 uint tIndex;
13135 };
13136
13137 uniform T u[2];
13138
13139 uint getValue(in sampler2D s)
13140 {
13141 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
13142 }
13143
13144 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
13145 {
13146 uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
13147 getValue(s[2]), getValue(s[3]));
13148
13149 return sExpect == sResult;
13150 }
13151
13152 bool samplerTest(T t, uint N)
13153 {
13154 // u[N].tIndex == 0 + N*4
13155 // u[N].nested[0].nested.index == 1 + N*4
13156 // u[N].nested[1].nested.index == 2 + N*4
13157 // u[N].nested[2].nested.index == 3 + N*4
13158
13159 uvec4 colorOffset = N * 3u * 4u * uvec4(8);
13160
13161 bool success = true;
13162 // [N][0]
13163 success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
13164 t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
13165 // [N][1]
13166 success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
13167 t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
13168 // [N][2]
13169 success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
13170 t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
13171
13172 return success;
13173 }
13174
13175 bool uniformTest(T t, uint N)
13176 {
13177 // Also verify that expressions that involve structs-with-samplers are correct when not
13178 // referecing the sampler.
13179
13180 bool success = true;
13181 success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
13182 success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
13183 success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
13184
13185 success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
13186 && success;
13187 success = (t.nested[t.nested[0].nested.index - t.tIndex ].nested.index - t.tIndex == 2u)
13188 && success;
13189 success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
13190 && success;
13191
13192 success = (t.nested[
13193 t.nested[
13194 t.nested[2].nested.index - t.tIndex - 1u // 2
13195 ].nested.index - t.tIndex - 2u // 1
13196 ].nested.index - t.tIndex // 2
13197 == 2u) && success;
13198
13199 return success;
13200 }
13201
13202 void main(void)
13203 {
13204 bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
13205 && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
13206 outbuf.success = uint(success);
13207 }
13208 )";
13209 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
13210 EXPECT_GL_NO_ERROR();
13211
13212 glUseProgram(program);
13213
13214 unsigned int outputInitData = 0x12345678u;
13215 GLBuffer outputBuffer;
13216 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
13217 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
13218 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
13219 EXPECT_GL_NO_ERROR();
13220
13221 const std::array<GLColor, 24> kTextureData = {
13222 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
13223 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
13224 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
13225 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
13226 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
13227 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
13228 };
13229 GLTexture textures[2][3][4];
13230
13231 for (int dim1 = 0; dim1 < 2; ++dim1)
13232 {
13233 for (int dim2 = 0; dim2 < 3; ++dim2)
13234 {
13235 for (int dim3 = 0; dim3 < 4; ++dim3)
13236 {
13237 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
13238 glActiveTexture(GL_TEXTURE0 + textureUnit);
13239 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
13240 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13241 &kTextureData[textureUnit]);
13242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13244
13245 std::stringstream uniformName;
13246 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
13247 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13248 EXPECT_NE(samplerLocation, -1);
13249 glUniform1i(samplerLocation, textureUnit);
13250 }
13251
13252 std::stringstream uniformName;
13253 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
13254 GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
13255 EXPECT_NE(nestedIndexLocation, -1);
13256 glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
13257 }
13258
13259 std::stringstream uniformName;
13260 uniformName << "u[" << dim1 << "].tIndex";
13261 GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
13262 EXPECT_NE(indexLocation, -1);
13263 glUniform1ui(indexLocation, dim1 * 4);
13264 }
13265 ASSERT_GL_NO_ERROR();
13266
13267 glDispatchCompute(1, 1, 1);
13268 EXPECT_GL_NO_ERROR();
13269
13270 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13271
13272 // read back
13273 const GLuint *ptr = reinterpret_cast<const GLuint *>(
13274 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13275 EXPECT_EQ(ptr[0], 1u);
13276
13277 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13278 }
13279
13280 // Test that array of array of samplers work when indexed with an expression that's derived from an
13281 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)13282 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
13283 {
13284 // Skip if EXT_gpu_shader5 is not enabled.
13285 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13286
13287 // anglebug.com/42262476 - no sampler array params on Android
13288 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
13289
13290 constexpr char kComputeShader[] = R"(#version 310 es
13291 #extension GL_EXT_gpu_shader5 : require
13292
13293 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
13294
13295 layout(binding = 1, std430) buffer Output {
13296 uint success;
13297 } outbuf;
13298
13299 uniform sampler2D smplr[2][3];
13300
13301 uint getValue(in sampler2D s)
13302 {
13303 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
13304 }
13305
13306 bool runTest(in sampler2D s[2][3])
13307 {
13308 // s[0][0] should contain 2
13309 // s[0][1] should contain 0
13310 // s[0][2] should contain 1
13311 // s[1][0] should contain 1
13312 // s[1][1] should contain 2
13313 // s[1][2] should contain 0
13314
13315 uint result = getValue(
13316 s[
13317 getValue(
13318 s[
13319 getValue(s[0][1]) // 0
13320 ][
13321 getValue(s[0][0]) // 2
13322 ]
13323 ) // s[0][2] -> 1
13324 ][
13325 getValue(
13326 s[
13327 getValue(s[1][0]) // 1
13328 ][
13329 getValue(s[1][1]) // 2
13330 ]
13331 ) // s[1][2] -> 0
13332 ]
13333 ); // s[1][0] -> 1
13334
13335 return result == 1u;
13336 }
13337
13338 void main(void)
13339 {
13340 outbuf.success = uint(runTest(smplr));
13341 }
13342 )";
13343 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
13344 EXPECT_GL_NO_ERROR();
13345
13346 glUseProgram(program);
13347
13348 unsigned int outputInitData = 0x12345678u;
13349 GLBuffer outputBuffer;
13350 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
13351 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
13352 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
13353 EXPECT_GL_NO_ERROR();
13354
13355 const std::array<GLColor, 6> kTextureData = {
13356 GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
13357 GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
13358 };
13359 GLTexture textures[2][3];
13360
13361 for (int dim1 = 0; dim1 < 2; ++dim1)
13362 {
13363 for (int dim2 = 0; dim2 < 3; ++dim2)
13364 {
13365 int textureUnit = dim1 * 3 + dim2;
13366 glActiveTexture(GL_TEXTURE0 + textureUnit);
13367 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
13368 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13369 &kTextureData[textureUnit]);
13370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13371 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13372
13373 std::stringstream uniformName;
13374 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
13375 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13376 EXPECT_NE(samplerLocation, -1);
13377 glUniform1i(samplerLocation, textureUnit);
13378 }
13379 }
13380 ASSERT_GL_NO_ERROR();
13381
13382 glDispatchCompute(1, 1, 1);
13383 EXPECT_GL_NO_ERROR();
13384
13385 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13386
13387 // read back
13388 const GLuint *ptr = reinterpret_cast<const GLuint *>(
13389 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13390 EXPECT_EQ(ptr[0], 1u);
13391
13392 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13393 }
13394
13395 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)13396 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
13397 {
13398 // http://anglebug.com/42262475
13399 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
13400
13401 // Fails on windows AMD on GL: http://anglebug.com/42262482
13402 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
13403 // http://anglebug.com/42263924
13404 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
13405
13406 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
13407 ANGLE_SKIP_TEST_IF(IsD3D11());
13408
13409 constexpr char kCS[] = R"(#version 310 es
13410 precision highp float;
13411 layout(local_size_x=1) in;
13412
13413 layout(std140, column_major) uniform Ubo
13414 {
13415 mat4 m1;
13416 layout(row_major) mat4 m2;
13417 } ubo;
13418
13419 layout(std140, row_major, binding = 0) buffer Ssbo
13420 {
13421 layout(column_major) mat4 m1;
13422 mat4 m2;
13423 } ssbo;
13424
13425 layout(std140, binding = 1) buffer Result
13426 {
13427 uint success;
13428 } resultOut;
13429
13430 void main()
13431 {
13432 bool result = true;
13433
13434 // Only assign to SSBO from a single invocation.
13435 if (gl_GlobalInvocationID.x == 0u)
13436 {
13437 if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
13438 {
13439 result = false;
13440 }
13441
13442 resultOut.success = uint(result);
13443 }
13444 })";
13445
13446 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13447 EXPECT_GL_NO_ERROR();
13448
13449 constexpr size_t kMatrixCount = 2;
13450 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
13451 {4, 4},
13452 {4, 4},
13453 };
13454 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
13455 true,
13456 false,
13457 };
13458
13459 float data[kMatrixCount * 4 * 4] = {};
13460 float zeros[kMatrixCount * 4 * 4] = {};
13461
13462 const uint32_t size =
13463 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
13464
13465 GLBuffer ubo, ssbo;
13466
13467 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
13468 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
13469 EXPECT_GL_NO_ERROR();
13470
13471 GLBuffer outputBuffer;
13472 CreateOutputBuffer(&outputBuffer, 1);
13473
13474 glUseProgram(program);
13475 glDispatchCompute(1, 1, 1);
13476 EXPECT_GL_NO_ERROR();
13477 EXPECT_TRUE(VerifySuccess(outputBuffer));
13478
13479 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
13480 }
13481
13482 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)13483 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
13484 {
13485 // Fails on windows AMD on GL: http://anglebug.com/42262482
13486 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
13487 // http://anglebug.com/42263924
13488 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
13489
13490 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
13491 ANGLE_SKIP_TEST_IF(IsD3D11());
13492
13493 // Fails compiling shader on Android/Vulkan. http://anglebug.com/42262919
13494 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
13495
13496 // Fails on ARM on Vulkan. http://anglebug.com/42263107
13497 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
13498
13499 constexpr char kCS[] = R"(#version 310 es
13500 precision highp float;
13501 layout(local_size_x=1) in;
13502
13503 layout(std140, column_major) uniform Ubo
13504 {
13505 mat4 m1;
13506 layout(row_major) mat4 m2[2][3];
13507 } ubo;
13508
13509 layout(std140, row_major, binding = 0) buffer Ssbo
13510 {
13511 layout(column_major) mat4 m1;
13512 mat4 m2[2][3];
13513 } ssbo;
13514
13515 layout(std140, binding = 1) buffer Result
13516 {
13517 uint success;
13518 } resultOut;
13519
13520 void main()
13521 {
13522 bool result = true;
13523
13524 // Only assign to SSBO from a single invocation.
13525 if (gl_GlobalInvocationID.x == 0u)
13526 {
13527 ssbo.m1 = ubo.m1;
13528 ssbo.m2 = ubo.m2;
13529
13530 resultOut.success = uint(result);
13531 }
13532 })";
13533
13534 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13535 EXPECT_GL_NO_ERROR();
13536
13537 constexpr size_t kMatrixCount = 7;
13538 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
13539 {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
13540 };
13541 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
13542 true, false, false, false, false, false, false,
13543 };
13544
13545 float data[kMatrixCount * 4 * 4] = {};
13546 float zeros[kMatrixCount * 4 * 4] = {};
13547
13548 const uint32_t size =
13549 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
13550
13551 GLBuffer ubo, ssbo;
13552
13553 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
13554 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
13555 EXPECT_GL_NO_ERROR();
13556
13557 GLBuffer outputBuffer;
13558 CreateOutputBuffer(&outputBuffer, 1);
13559
13560 glUseProgram(program);
13561 glDispatchCompute(1, 1, 1);
13562 EXPECT_GL_NO_ERROR();
13563 EXPECT_TRUE(VerifySuccess(outputBuffer));
13564
13565 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
13566 }
13567
13568 // Verify that types used differently (in different block storages, differently qualified etc) work
13569 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)13570 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
13571 {
13572 constexpr char kCS[] = R"(#version 310 es
13573 precision highp float;
13574 layout(local_size_x=1) in;
13575
13576 struct Inner
13577 {
13578 mat3x2 m;
13579 float f[3];
13580 uvec2 u[2][4];
13581 ivec3 i;
13582 mat2x3 m2[3][2];
13583 };
13584
13585 struct Outer
13586 {
13587 Inner i[2];
13588 };
13589
13590 layout(std140, column_major) uniform Ubo140c
13591 {
13592 mat2 m;
13593 layout(row_major) Outer o;
13594 } ubo140cIn;
13595
13596 layout(std430, row_major, binding = 0) buffer Ubo430r
13597 {
13598 mat2 m;
13599 layout(column_major) Outer o;
13600 } ubo430rIn;
13601
13602 layout(std140, column_major, binding = 1) buffer Ssbo140c
13603 {
13604 layout(row_major) mat2 m[2];
13605 Outer o;
13606 layout(row_major) Inner i;
13607 } ssbo140cOut;
13608
13609 layout(std430, row_major, binding = 2) buffer Ssbo430r
13610 {
13611 layout(column_major) mat2 m[2];
13612 Outer o;
13613 layout(column_major) Inner i;
13614 } ssbo430rOut;
13615
13616 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
13617 {
13618 ssbo140cOut.o.i[innerIndex].u = u;
13619 }
13620
13621 void writeBlockArgToStd140(Inner i, int innerIndex)
13622 {
13623 ssbo140cOut.o.i[innerIndex] = i;
13624 }
13625
13626 mat2x3[3][2] readFromStd140(int innerIndex)
13627 {
13628 return ubo140cIn.o.i[0].m2;
13629 }
13630
13631 Inner readBlockFromStd430(int innerIndex)
13632 {
13633 return ubo430rIn.o.i[innerIndex];
13634 }
13635
13636 void copyFromStd140(out Inner i)
13637 {
13638 i = ubo140cIn.o.i[1];
13639 }
13640
13641 void main(){
13642 // Directly copy from one layout to another.
13643 ssbo140cOut.m[0] = ubo140cIn.m;
13644 ssbo140cOut.m[1] = ubo430rIn.m;
13645 ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
13646 ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
13647 ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
13648
13649 // Read from block and pass to function.
13650 writeArgToStd140(ubo140cIn.o.i[0].u, 0);
13651 writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
13652
13653 // Have function return value read from block.
13654 ssbo140cOut.o.i[0].m2 = readFromStd140(0);
13655
13656 // Have function fill in value as out parameter.
13657 copyFromStd140(ssbo140cOut.i);
13658
13659 // Initialize local variable.
13660 mat2 mStd140 = ubo140cIn.m;
13661
13662 // Copy to variable, through multiple assignments.
13663 mat2 mStd430, temp;
13664 mStd430 = temp = ubo430rIn.m;
13665
13666 // Copy from local variable
13667 ssbo430rOut.m[0] = mStd140;
13668 ssbo430rOut.m[1] = mStd430;
13669
13670 // Construct from struct.
13671 Inner iStd140 = ubo140cIn.o.i[1];
13672 Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
13673
13674 // Copy struct from local variable.
13675 ssbo430rOut.o = oStd140;
13676
13677 // Construct from arrays
13678 Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
13679 ubo430rIn.o.i[1].f,
13680 ubo430rIn.o.i[1].u,
13681 ubo430rIn.o.i[1].i,
13682 ubo430rIn.o.i[1].m2);
13683 ssbo430rOut.i = iStd430;
13684 })";
13685
13686 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13687 EXPECT_GL_NO_ERROR();
13688
13689 // Test data, laid out with padding (0) based on std140/std430 rules.
13690 // clang-format off
13691 const std::vector<float> ubo140cData = {
13692 // m (mat2, column-major)
13693 1, 2, 0, 0, 3, 4, 0, 0,
13694
13695 // o.i[0].m (mat3x2, row-major)
13696 5, 7, 9, 0, 6, 8, 10, 0,
13697 // o.i[0].f (float[3])
13698 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
13699 // o.i[0].u (uvec2[2][4])
13700 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
13701 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
13702 // o.i[0].i (ivec3)
13703 31, 32, 33, 0,
13704 // o.i[0].m2 (mat2x3[3][2], row-major)
13705 34, 37, 0, 0, 35, 38, 0, 0, 36, 39, 0, 0,
13706 40, 43, 0, 0, 41, 44, 0, 0, 42, 45, 0, 0,
13707 46, 49, 0, 0, 47, 50, 0, 0, 48, 51, 0, 0,
13708 52, 55, 0, 0, 53, 56, 0, 0, 54, 57, 0, 0,
13709 58, 61, 0, 0, 59, 62, 0, 0, 60, 63, 0, 0,
13710 64, 67, 0, 0, 65, 68, 0, 0, 66, 69, 0, 0,
13711
13712 // o.i[1].m (mat3x2, row-major)
13713 70, 72, 74, 0, 71, 73, 75, 0,
13714 // o.i[1].f (float[3])
13715 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
13716 // o.i[1].u (uvec2[2][4])
13717 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
13718 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
13719 // o.i[1].i (ivec3)
13720 96, 97, 98, 0,
13721 // o.i[1].m2 (mat2x3[3][2], row-major)
13722 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
13723 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
13724 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
13725 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
13726 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
13727 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
13728 };
13729 const std::vector<float> ubo430rData = {
13730 // m (mat2, row-major)
13731 135, 137, 136, 138,
13732
13733 // o.i[0].m (mat3x2, column-major)
13734 139, 140, 141, 142, 143, 144,
13735 // o.i[0].f (float[3])
13736 146, 147, 148, 0,
13737 // o.i[0].u (uvec2[2][4])
13738 149, 150, 151, 152, 153, 154, 155, 156,
13739 157, 158, 159, 160, 161, 162, 163, 164, 0, 0,
13740 // o.i[0].i (ivec3)
13741 165, 166, 167, 0,
13742 // o.i[0].m2 (mat2x3[3][2], column-major)
13743 168, 169, 170, 0, 171, 172, 173, 0,
13744 174, 175, 176, 0, 177, 178, 179, 0,
13745 180, 181, 182, 0, 183, 184, 185, 0,
13746 186, 187, 188, 0, 189, 190, 191, 0,
13747 192, 193, 194, 0, 195, 196, 197, 0,
13748 198, 199, 200, 0, 201, 202, 203, 0,
13749
13750 // o.i[1].m (mat3x2, column-major)
13751 204, 205, 206, 207, 208, 209,
13752 // o.i[1].f (float[3])
13753 211, 212, 213, 0,
13754 // o.i[1].u (uvec2[2][4])
13755 214, 215, 216, 217, 218, 219, 220, 221,
13756 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
13757 // o.i[1].i (ivec3)
13758 230, 231, 232, 0,
13759 // o.i[1].m2 (mat2x3[3][2], column-major)
13760 233, 234, 235, 0, 236, 237, 238, 0,
13761 239, 240, 241, 0, 242, 243, 244, 0,
13762 245, 246, 247, 0, 248, 249, 250, 0,
13763 251, 252, 253, 0, 254, 255, 256, 0,
13764 257, 258, 259, 0, 260, 261, 262, 0,
13765 263, 264, 265, 0, 266, 267, 268, 0,
13766 };
13767 const std::vector<float> ssbo140cExpect = {
13768 // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13769 1, 3, 0, 0, 2, 4, 0, 0,
13770 135, 137, 0, 0, 136, 138, 0, 0,
13771
13772 // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
13773 5, 6, 0, 0, 7, 8, 0, 0, 9, 10, 0, 0,
13774 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
13775 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
13776 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
13777 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
13778 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
13779 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
13780 31, 32, 33, 0,
13781 // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
13782 34, 35, 36, 0, 37, 38, 39, 0,
13783 40, 41, 42, 0, 43, 44, 45, 0,
13784 46, 47, 48, 0, 49, 50, 51, 0,
13785 52, 53, 54, 0, 55, 56, 57, 0,
13786 58, 59, 60, 0, 61, 62, 63, 0,
13787 64, 65, 66, 0, 67, 68, 69, 0,
13788
13789 // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
13790 139, 140, 0, 0, 141, 142, 0, 0, 143, 144, 0, 0,
13791 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
13792 146, 0, 0, 0, 147, 0, 0, 0, 148, 0, 0, 0,
13793 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
13794 149, 150, 0, 0, 151, 152, 0, 0, 153, 154, 0, 0, 155, 156, 0, 0,
13795 157, 158, 0, 0, 159, 160, 0, 0, 161, 162, 0, 0, 163, 164, 0, 0,
13796 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
13797 165, 166, 167, 0,
13798 // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
13799 168, 169, 170, 0, 171, 172, 173, 0,
13800 174, 175, 176, 0, 177, 178, 179, 0,
13801 180, 181, 182, 0, 183, 184, 185, 0,
13802 186, 187, 188, 0, 189, 190, 191, 0,
13803 192, 193, 194, 0, 195, 196, 197, 0,
13804 198, 199, 200, 0, 201, 202, 203, 0,
13805
13806 // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13807 70, 72, 74, 0, 71, 73, 75, 0,
13808 // i.f (float[3]), copied from ubo140cIn.o.i[1].f
13809 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
13810 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13811 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
13812 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
13813 // i.i (ivec3), copied from ubo140cIn.o.i[1].i
13814 96, 97, 98, 0,
13815 // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13816 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
13817 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
13818 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
13819 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
13820 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
13821 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
13822 };
13823 const std::vector<float> ssbo430rExpect = {
13824 // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13825 1, 2, 3, 4,
13826 135, 136, 137, 138,
13827
13828 // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13829 70, 72, 74, 0, 71, 73, 75, 0,
13830 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
13831 77, 78, 79, 0,
13832 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
13833 80, 81, 82, 83, 84, 85, 86, 87,
13834 88, 89, 90, 91, 92, 93, 94, 95,
13835 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
13836 96, 97, 98, 0,
13837 // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13838 99, 102, 100, 103, 101, 104,
13839 105, 108, 106, 109, 107, 110,
13840 111, 114, 112, 115, 113, 116,
13841 117, 120, 118, 121, 119, 122,
13842 123, 126, 124, 127, 125, 128,
13843 129, 132, 130, 133, 131, 134,
13844
13845 // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
13846 204, 206, 208, 0, 205, 207, 209, 0,
13847 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
13848 211, 212, 213, 0,
13849 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13850 214, 215, 216, 217, 218, 219, 220, 221,
13851 222, 223, 224, 225, 226, 227, 228, 229,
13852 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
13853 230, 231, 232, 0,
13854 // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
13855 233, 236, 234, 237, 235, 238,
13856 239, 242, 240, 243, 241, 244,
13857 245, 248, 246, 249, 247, 250,
13858 251, 254, 252, 255, 253, 256,
13859 257, 260, 258, 261, 259, 262,
13860 263, 266, 264, 267, 265, 268,
13861
13862 // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
13863 204, 205, 206, 207, 208, 209,
13864 // i.f (float[3]), copied from ubo430rIn.o.i[1].f
13865 211, 212, 213, 0,
13866 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13867 214, 215, 216, 217, 218, 219, 220, 221,
13868 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
13869 // i.i (ivec3), copied from ubo430rIn.o.i[1].i
13870 230, 231, 232, 0,
13871 // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
13872 233, 234, 235, 0, 236, 237, 238, 0,
13873 239, 240, 241, 0, 242, 243, 244, 0,
13874 245, 246, 247, 0, 248, 249, 250, 0,
13875 251, 252, 253, 0, 254, 255, 256, 0,
13876 257, 258, 259, 0, 260, 261, 262, 0,
13877 263, 264, 265, 0, 266, 267, 268, 0,
13878 };
13879 const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
13880 // clang-format on
13881
13882 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13883 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13884
13885 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13886 static_cast<uint32_t>(ubo140cData.size()), true);
13887 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13888 static_cast<uint32_t>(ubo430rData.size()), false);
13889 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
13890 static_cast<uint32_t>(ssbo140cExpect.size()), false);
13891 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13892 static_cast<uint32_t>(ssbo430rExpect.size()), false);
13893 EXPECT_GL_NO_ERROR();
13894
13895 glUseProgram(program);
13896 glDispatchCompute(1, 1, 1);
13897 EXPECT_GL_NO_ERROR();
13898
13899 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
13900 static_cast<uint32_t>(ssbo140cExpect.size())));
13901 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13902 static_cast<uint32_t>(ssbo430rExpect.size())));
13903 }
13904
13905 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)13906 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
13907 {
13908 constexpr char kCS[] = R"(#version 310 es
13909 precision highp float;
13910 layout(local_size_x=1) in;
13911
13912 struct Inner
13913 {
13914 bool b;
13915 bvec2 b2;
13916 bvec3 b3;
13917 bvec4 b4;
13918 bool ba[5];
13919 bvec2 b2a[2][3];
13920 };
13921
13922 struct Outer
13923 {
13924 Inner i[2];
13925 };
13926
13927 layout(std140) uniform Ubo140
13928 {
13929 Outer o;
13930 };
13931
13932 layout(std430, binding = 0) buffer Ubo430
13933 {
13934 Outer o;
13935 } ubo430In;
13936
13937 layout(std140, binding = 1) buffer Ssbo140
13938 {
13939 bool valid;
13940 Inner i;
13941 } ssbo140Out;
13942
13943 layout(std430, binding = 2) buffer Ssbo430
13944 {
13945 bool valid;
13946 Inner i;
13947 };
13948
13949 void writeArgToStd430(bool ba[5])
13950 {
13951 i.ba = ba;
13952 }
13953
13954 bool[5] readFromStd430(uint innerIndex)
13955 {
13956 return ubo430In.o.i[innerIndex].ba;
13957 }
13958
13959 void copyFromStd430(out bvec2 b2a[2][3])
13960 {
13961 b2a = ubo430In.o.i[0].b2a;
13962 }
13963
13964 bool destroyContent(inout Inner iOut)
13965 {
13966 iOut.b = true;
13967 iOut.b2 = bvec2(true);
13968 iOut.b3 = bvec3(true);
13969 iOut.b4 = bvec4(true);
13970 iOut.ba = bool[5](true, true, true, true, true);
13971 bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
13972 iOut.b2a = bvec2[2][3](true3, true3);
13973 return true;
13974 }
13975
13976 void main(){
13977 // Directly copy from one layout to another.
13978 i.b = o.i[0].b;
13979 i.b2 = o.i[0].b2;
13980 i.b2a = o.i[0].b2a;
13981
13982 // Copy to temp with swizzle.
13983 bvec4 t1 = o.i[0].b3.yxzy;
13984 bvec4 t2 = o.i[0].b4.xxyy;
13985 bvec4 t3 = o.i[0].b4.zzww;
13986
13987 // Copy from temp with swizzle.
13988 i.b3 = t1.ywz;
13989 i.b4.yz = bvec2(t2.z, t3.y);
13990 i.b4.wx = bvec2(t3.w, t2.x);
13991
13992 // Copy by passing argument to function.
13993 writeArgToStd430(o.i[0].ba);
13994
13995 // Copy by return value.
13996 ssbo140Out.i.ba = readFromStd430(0u);
13997
13998 // Copy by out parameter.
13999 copyFromStd430(ssbo140Out.i.b2a);
14000
14001 // Logical operations
14002 uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
14003 ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
14004 ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
14005 ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
14006 ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
14007
14008 ssbo140Out.valid = true;
14009 ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
14010 ssbo140Out.valid = ssbo140Out.valid &&
14011 all(notEqual(o.i[1].b4, bvec4(o.i[1].ba[0], o.i[1].ba[1], o.i[1].ba[2], o.i[1].ba[3])));
14012 ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
14013 for (int x = 0; x < o.i[1].b2a.length(); ++x)
14014 {
14015 for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
14016 {
14017 ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
14018 }
14019 }
14020
14021 valid = o.i[1] == ubo430In.o.i[1];
14022
14023 // Make sure short-circuiting behavior is correct.
14024 bool falseVar = !valid && destroyContent(i);
14025 if (falseVar && destroyContent(ssbo140Out.i))
14026 {
14027 valid = false;
14028 }
14029
14030 if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
14031 {
14032 }
14033 else
14034 {
14035 ssbo140Out.valid = false;
14036 }
14037 })";
14038
14039 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14040 EXPECT_GL_NO_ERROR();
14041
14042 // Test data, laid out with padding (0) based on std140/std430 rules.
14043 // clang-format off
14044 const std::vector<uint32_t> ubo140Data = {
14045 // o.i[0].b (bool)
14046 true, 0,
14047 // o.i[0].b2 (bvec2)
14048 true, false,
14049 // o.i[0].b3 (bvec3)
14050 true, true, false, 0,
14051 // o.i[0].b4 (bvec4)
14052 false, true, false, true,
14053 // o.i[0].ba (bool[5])
14054 true, 0, 0, 0,
14055 false, 0, 0, 0,
14056 false, 0, 0, 0,
14057 true, 0, 0, 0,
14058 true, 0, 0, 0,
14059 // o.i[0].b2a (bool[2][3])
14060 false, true, 0, 0, true, true, 0, 0, true, false, 0, 0,
14061 true, false, 0, 0, false, false, 0, 0, true, true, 0, 0,
14062
14063 // o.i[1].b (bool)
14064 false, 0,
14065 // o.i[1].b2 (bvec2)
14066 true, true,
14067 // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
14068 false, true, true, 0,
14069 // o.i[1].b4 (bvec4)
14070 true, false, true, true,
14071 // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
14072 false, 0, 0, 0,
14073 true, 0, 0, 0,
14074 false, 0, 0, 0,
14075 false, 0, 0, 0,
14076 true, 0, 0, 0,
14077 // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
14078 false, false, 0, 0, false, true, 0, 0, false, false, 0, 0,
14079 true, false, 0, 0, true, true, 0, 0, true, false, 0, 0,
14080 };
14081 const std::vector<uint32_t> ubo430Data = {
14082 // o.i[0].b (bool)
14083 false, 0,
14084 // o.i[0].b2 (bvec2)
14085 true, true,
14086 // o.i[0].b3 (bvec3)
14087 false, false, true, 0,
14088 // o.i[0].b4 (bvec4)
14089 true, false, true, true,
14090 // o.i[0].ba (bool[5])
14091 false, false, false, true, false, 0,
14092 // o.i[0].b2a (bool[2][3])
14093 true, false, true, false, true, true,
14094 false, true, true, true, false, false, 0, 0,
14095
14096 // o.i[1] expected to be equal to ubo140In.o.i[1]
14097 // o.i[1].b (bool)
14098 false, 0,
14099 // o.i[1].b2 (bvec2)
14100 true, true,
14101 // o.i[1].b3 (bvec3)
14102 false, true, true, 0,
14103 // o.i[1].b4 (bvec4)
14104 true, false, true, true,
14105 // o.i[1].ba (bool[5])
14106 false, true, false, false, true, 0,
14107 // o.i[1].b2a (bvec2[2][3])
14108 false, false, false, true, false, false,
14109 true, false, true, true, true, false,
14110 };
14111 const std::vector<uint32_t> ssbo140Expect = {
14112 // valid, expected to be true
14113 true, 0, 0, 0,
14114
14115 // i.b (bool), ubo430In.o.i[0].b ? false : true
14116 true, 0,
14117 // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
14118 false, false,
14119 // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
14120 false, true, false, 0,
14121 // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
14122 true, true, true, false,
14123 // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
14124 false, 0, 0, 0,
14125 false, 0, 0, 0,
14126 false, 0, 0, 0,
14127 true, 0, 0, 0,
14128 false, 0, 0, 0,
14129 // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
14130 true, false, 0, 0, true, false, 0, 0, true, true, 0, 0,
14131 false, true, 0, 0, true, true, 0, 0, false, false, 0, 0,
14132 };
14133 const std::vector<uint32_t> ssbo430Expect = {
14134 // valid, expected to be true
14135 true, 0, 0, 0,
14136
14137 // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
14138 true, 0,
14139 // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
14140 true, false,
14141 // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
14142 true, true, false, 0,
14143 // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
14144 false, true, false, true,
14145 // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
14146 true, false, false, true, true, 0,
14147 // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
14148 false, true, true, true, true, false,
14149 true, false, false, false, true, true, 0, 0,
14150 };
14151 const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
14152 // clang-format on
14153
14154 GLBuffer uboStd140, uboStd430;
14155 GLBuffer ssboStd140, ssboStd430;
14156
14157 InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
14158 static_cast<uint32_t>(ubo140Data.size()), true);
14159 InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
14160 static_cast<uint32_t>(ubo430Data.size()), false);
14161 InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
14162 static_cast<uint32_t>(ssbo140Expect.size()), false);
14163 InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
14164 static_cast<uint32_t>(ssbo430Expect.size()), false);
14165 EXPECT_GL_NO_ERROR();
14166
14167 glUseProgram(program);
14168 glDispatchCompute(1, 1, 1);
14169 EXPECT_GL_NO_ERROR();
14170
14171 EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
14172 static_cast<uint32_t>(ssbo140Expect.size())));
14173 EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
14174 static_cast<uint32_t>(ssbo430Expect.size())));
14175 }
14176
14177 // Verify that ternary operator works when the operands are matrices used in different block
14178 // storage.
TEST_P(GLSLTest_ES31,TernaryOnMatricesInDifferentBlockStorages)14179 TEST_P(GLSLTest_ES31, TernaryOnMatricesInDifferentBlockStorages)
14180 {
14181 constexpr char kCS[] = R"(#version 310 es
14182 precision highp float;
14183 layout(local_size_x=1) in;
14184
14185 layout(std140, column_major) uniform Ubo140c
14186 {
14187 uint u;
14188 layout(row_major) mat3x2 m;
14189 } ubo140cIn;
14190
14191 layout(std430, row_major, binding = 0) buffer Ubo430r
14192 {
14193 uint u;
14194 layout(column_major) mat3x2 m;
14195 } ubo430rIn;
14196
14197 layout(std140, column_major, binding = 1) buffer Ssbo140c
14198 {
14199 uint u;
14200 mat3x2 m;
14201 } ssbo140cIn;
14202
14203 layout(std430, row_major, binding = 2) buffer Ssbo430r
14204 {
14205 mat3x2 m1;
14206 mat3x2 m2;
14207 } ssbo430rOut;
14208
14209 void main(){
14210 ssbo430rOut.m1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.m : ubo430rIn.m;
14211 ssbo430rOut.m2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.m : ubo140cIn.m;
14212
14213 mat3x2 m = mat3x2(0);
14214
14215 ssbo430rOut.m1 = ubo140cIn.u == 0u ? m : ssbo430rOut.m1;
14216 })";
14217
14218 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14219 EXPECT_GL_NO_ERROR();
14220
14221 // Test data, laid out with padding (0) based on std140/std430 rules.
14222 // clang-format off
14223 const std::vector<float> ubo140cData = {
14224 // u (uint)
14225 1, 0, 0, 0,
14226
14227 // m (mat3x2, row-major)
14228 5, 7, 9, 0, 6, 8, 10, 0,
14229 };
14230 const std::vector<float> ubo430rData = {
14231 // u (uint)
14232 135, 0,
14233
14234 // m (mat3x2, column-major)
14235 139, 140, 141, 142, 143, 144,
14236 };
14237 const std::vector<float> ssbo140cData = {
14238 // u (uint)
14239 204, 0, 0, 0,
14240
14241 // m (mat3x2, column-major)
14242 205, 206, 0, 0, 207, 208, 0, 0, 209, 210, 0, 0,
14243 };
14244 const std::vector<float> ssbo430rExpect = {
14245 // m1 (mat3x2, row-major), copied from ubo430rIn.m
14246 139, 141, 143, 0, 140, 142, 144, 0,
14247
14248 // m2 (mat3x2, row-major), copied from ssbo140cIn.m
14249 205, 207, 209, 0, 206, 208, 210, 0,
14250 };
14251 const std::vector<float> zeros(ssbo430rExpect.size(), 0);
14252 // clang-format on
14253
14254 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
14255 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
14256
14257 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
14258 static_cast<uint32_t>(ubo140cData.size()), true);
14259 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
14260 static_cast<uint32_t>(ubo430rData.size()), false);
14261 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
14262 static_cast<uint32_t>(ssbo140cData.size()), false);
14263 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
14264 static_cast<uint32_t>(ssbo430rExpect.size()), false);
14265 EXPECT_GL_NO_ERROR();
14266
14267 glUseProgram(program);
14268 glDispatchCompute(1, 1, 1);
14269 EXPECT_GL_NO_ERROR();
14270
14271 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
14272 static_cast<uint32_t>(ssbo430rExpect.size())));
14273 }
14274
14275 // Verify that ternary operator works when the operands are structs used in different block
14276 // storage.
TEST_P(GLSLTest_ES31,TernaryOnStructsInDifferentBlockStorages)14277 TEST_P(GLSLTest_ES31, TernaryOnStructsInDifferentBlockStorages)
14278 {
14279 constexpr char kCS[] = R"(#version 310 es
14280 precision highp float;
14281 layout(local_size_x=1) in;
14282
14283 struct S
14284 {
14285 mat3x2 m[2];
14286 };
14287
14288 layout(std140, column_major) uniform Ubo140c
14289 {
14290 uint u;
14291 layout(row_major) S s;
14292 } ubo140cIn;
14293
14294 layout(std430, row_major, binding = 0) buffer Ubo430r
14295 {
14296 uint u;
14297 layout(column_major) S s;
14298 } ubo430rIn;
14299
14300 layout(std140, column_major, binding = 1) buffer Ssbo140c
14301 {
14302 uint u;
14303 S s;
14304 } ssbo140cIn;
14305
14306 layout(std430, row_major, binding = 2) buffer Ssbo430r
14307 {
14308 S s1;
14309 S s2;
14310 } ssbo430rOut;
14311
14312 void main(){
14313 ssbo430rOut.s1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.s : ubo430rIn.s;
14314 ssbo430rOut.s2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.s : ubo140cIn.s;
14315
14316 S s;
14317 s.m[0] = mat3x2(0);
14318 s.m[1] = mat3x2(0);
14319
14320 ssbo430rOut.s1 = ubo140cIn.u == 0u ? s : ssbo430rOut.s1;
14321 })";
14322
14323 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14324 EXPECT_GL_NO_ERROR();
14325
14326 // Test data, laid out with padding (0) based on std140/std430 rules.
14327 // clang-format off
14328 const std::vector<float> ubo140cData = {
14329 // u (uint)
14330 1, 0, 0, 0,
14331
14332 // s.m[0] (mat3x2, row-major)
14333 5, 7, 9, 0, 6, 8, 10, 0,
14334 // s.m[1] (mat3x2, row-major)
14335 25, 27, 29, 0, 26, 28, 30, 0,
14336 };
14337 const std::vector<float> ubo430rData = {
14338 // u (uint)
14339 135, 0,
14340
14341 // s.m[0] (mat3x2, column-major)
14342 139, 140, 141, 142, 143, 144,
14343 // s.m[1] (mat3x2, column-major)
14344 189, 190, 191, 192, 193, 194,
14345 };
14346 const std::vector<float> ssbo140cData = {
14347 // u (uint)
14348 204, 0, 0, 0,
14349
14350 // s.m[0] (mat3x2, column-major)
14351 205, 206, 0, 0, 207, 208, 0, 0, 209, 210, 0, 0,
14352 // s.m[1] (mat3x2, column-major)
14353 245, 246, 0, 0, 247, 248, 0, 0, 249, 250, 0, 0,
14354 };
14355 const std::vector<float> ssbo430rExpect = {
14356 // s1.m[0] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
14357 139, 141, 143, 0, 140, 142, 144, 0,
14358 // s1.m[1] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
14359 189, 191, 193, 0, 190, 192, 194, 0,
14360
14361 // s2.m[0] (mat3x2, row-major), copied from ssbo140cIn.m
14362 205, 207, 209, 0, 206, 208, 210, 0,
14363 // s2.m[1] (mat3x2, row-major), copied from ssbo140cIn.m
14364 245, 247, 249, 0, 246, 248, 250, 0,
14365 };
14366 const std::vector<float> zeros(ssbo430rExpect.size(), 0);
14367 // clang-format on
14368
14369 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
14370 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
14371
14372 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
14373 static_cast<uint32_t>(ubo140cData.size()), true);
14374 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
14375 static_cast<uint32_t>(ubo430rData.size()), false);
14376 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
14377 static_cast<uint32_t>(ssbo140cData.size()), false);
14378 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
14379 static_cast<uint32_t>(ssbo430rExpect.size()), false);
14380 EXPECT_GL_NO_ERROR();
14381
14382 glUseProgram(program);
14383 glDispatchCompute(1, 1, 1);
14384 EXPECT_GL_NO_ERROR();
14385
14386 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
14387 static_cast<uint32_t>(ssbo430rExpect.size())));
14388 }
14389
14390 // Verify that uint in interface block cast to bool works.
TEST_P(GLSLTest_ES3,UintCastToBoolFromInterfaceBlocks)14391 TEST_P(GLSLTest_ES3, UintCastToBoolFromInterfaceBlocks)
14392 {
14393 constexpr char kFS[] = R"(#version 300 es
14394 precision mediump float;
14395
14396 uniform uvec4 uv4;
14397 uniform uvec2 uv2;
14398 uniform uint u1;
14399 uniform uint u2;
14400
14401 out vec4 colorOut;
14402
14403 void main()
14404 {
14405 bvec4 bv4 = bvec4(uv4);
14406 bvec2 bv2 = bvec2(uv2);
14407 bool b1 = bool(u1);
14408 bool b2 = bool(u2);
14409
14410 vec4 vv4 = mix(vec4(0), vec4(0.4), bv4);
14411 vec2 vv2 = mix(vec2(0), vec2(0.7), bv2);
14412 float v1 = b1 ? 1.0 : 0.0;
14413 float v2 = b2 ? 0.0 : 1.0;
14414
14415 colorOut = vec4(vv4.x - vv4.y + vv4.z + vv4.w,
14416 (vv2.y - vv2.x) * 1.5,
14417 v1,
14418 v2);
14419 })";
14420
14421 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
14422 EXPECT_GL_NO_ERROR();
14423
14424 glUseProgram(program);
14425 GLint uv4 = glGetUniformLocation(program, "uv4");
14426 GLint uv2 = glGetUniformLocation(program, "uv2");
14427 GLint u1 = glGetUniformLocation(program, "u1");
14428 GLint u2 = glGetUniformLocation(program, "u2");
14429 ASSERT_NE(uv4, -1);
14430 ASSERT_NE(uv2, -1);
14431 ASSERT_NE(u1, -1);
14432 ASSERT_NE(u2, -1);
14433
14434 glUniform4ui(uv4, 123, 0, 9, 8297312);
14435 glUniform2ui(uv2, 0, 90812);
14436 glUniform1ui(u1, 8979421);
14437 glUniform1ui(u2, 0);
14438
14439 glClearColor(0, 0, 0, 0);
14440 glClear(GL_COLOR_BUFFER_BIT);
14441
14442 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
14443 EXPECT_GL_NO_ERROR();
14444
14445 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14446 }
14447
14448 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)14449 TEST_P(GLSLTest_ES3, PreciseNotReserved)
14450 {
14451 // Skip in ES3.1+ as the precise keyword is reserved/core.
14452 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
14453 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
14454
14455 constexpr char kFS[] = R"(#version 300 es
14456 precision mediump float;
14457 in float precise;
14458 out vec4 my_FragColor;
14459 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
14460
14461 constexpr char kVS[] = R"(#version 300 es
14462 in vec4 a_position;
14463 out float precise;
14464 void main() { precise = a_position.x; gl_Position = a_position; })";
14465
14466 GLuint program = CompileProgram(kVS, kFS);
14467 EXPECT_NE(0u, program);
14468 }
14469
14470 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)14471 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
14472 {
14473 // Skip if EXT_gpu_shader5 is enabled.
14474 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14475 // Skip in ES3.2+ as the precise keyword is core.
14476 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
14477 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
14478
14479 constexpr char kFS[] = R"(#version 310 es
14480 precision mediump float;
14481 in float v_varying;
14482 out vec4 my_FragColor;
14483 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
14484
14485 constexpr char kVS[] = R"(#version 310 es
14486 in vec4 a_position;
14487 precise out float v_varying;
14488 void main() { v_varying = a_position.x; gl_Position = a_position; })";
14489
14490 // Should fail, as precise is a reserved keyword when the extension is not enabled.
14491 GLuint program = CompileProgram(kVS, kFS);
14492 EXPECT_EQ(0u, program);
14493 }
14494
14495 // Regression test for a bug with precise in combination with constructor, swizzle and dynamic
14496 // index.
TEST_P(GLSLTest_ES31,PreciseVsVectorConstructorSwizzleAndIndex)14497 TEST_P(GLSLTest_ES31, PreciseVsVectorConstructorSwizzleAndIndex)
14498 {
14499 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14500
14501 constexpr char kVS[] = R"(#version 310 es
14502 #extension GL_EXT_gpu_shader5 : require
14503
14504 uniform highp float u;
14505
14506 void main()
14507 {
14508 precise float p = vec4(u, u, u, u).xyz[int(u)];
14509 gl_Position = vec4(p);
14510 })";
14511
14512 constexpr char kFS[] = R"(#version 310 es
14513 precision mediump float;
14514 out vec4 oColor;
14515 void main()
14516 {
14517 oColor = vec4(1.0);
14518 })";
14519
14520 ANGLE_GL_PROGRAM(program, kVS, kFS);
14521 }
14522
14523 // Regression test for a bug with precise in combination with matrix constructor and column index.
TEST_P(GLSLTest_ES31,PreciseVsMatrixConstructorAndIndex)14524 TEST_P(GLSLTest_ES31, PreciseVsMatrixConstructorAndIndex)
14525 {
14526 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14527
14528 constexpr char kVS[] = R"(#version 310 es
14529 #extension GL_EXT_gpu_shader5 : require
14530
14531 uniform highp vec4 u;
14532
14533 void main()
14534 {
14535 precise vec4 p = mat4(u,vec4(0),vec4(0),vec4(0))[0];
14536 gl_Position = p;
14537 })";
14538
14539 constexpr char kFS[] = R"(#version 310 es
14540 precision mediump float;
14541 out vec4 oColor;
14542 void main()
14543 {
14544 oColor = vec4(1.0);
14545 })";
14546
14547 ANGLE_GL_PROGRAM(program, kVS, kFS);
14548 }
14549
14550 // Regression test for a bug with precise in combination with struct constructor and field
14551 // selection.
TEST_P(GLSLTest_ES31,PreciseVsStructConstructorAndFieldSelection)14552 TEST_P(GLSLTest_ES31, PreciseVsStructConstructorAndFieldSelection)
14553 {
14554 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14555
14556 constexpr char kVS[] = R"(#version 310 es
14557 #extension GL_EXT_gpu_shader5 : require
14558
14559 struct S
14560 {
14561 float a;
14562 float b;
14563 };
14564
14565 uniform highp float u;
14566
14567 void main()
14568 {
14569 precise float p = S(u, u).b;
14570 gl_Position = vec4(p);
14571 })";
14572
14573 constexpr char kFS[] = R"(#version 310 es
14574 precision mediump float;
14575 out vec4 oColor;
14576 void main()
14577 {
14578 oColor = vec4(1.0);
14579 })";
14580
14581 ANGLE_GL_PROGRAM(program, kVS, kFS);
14582 }
14583
14584 // Test that reusing the same variable name for different uses across stages links fine. The SPIR-V
14585 // transformation should ignore all names for non-shader-interface variables and not get confused by
14586 // them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)14587 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
14588 {
14589 constexpr char kVS[] = R"(#version 310 es
14590 precision mediump float;
14591 uniform highp vec4 a;
14592 in highp vec4 b;
14593 in highp vec4 c;
14594 in highp vec4 d;
14595 out highp vec4 e;
14596
14597 vec4 f(vec4 a)
14598 {
14599 return a;
14600 }
14601
14602 vec4 g(vec4 f)
14603 {
14604 return f + f;
14605 }
14606
14607 void main() {
14608 e = f(b) + a;
14609 gl_Position = g(c) + f(d);
14610 }
14611 )";
14612
14613 constexpr char kFS[] = R"(#version 310 es
14614 precision mediump float;
14615 in highp vec4 e;
14616 uniform sampler2D f;
14617 layout(rgba8) uniform highp readonly image2D g;
14618 uniform A
14619 {
14620 vec4 x;
14621 } c;
14622 layout(std140, binding=0) buffer B
14623 {
14624 vec4 x;
14625 } d[2];
14626 out vec4 col;
14627
14628 vec4 h(vec4 c)
14629 {
14630 return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
14631 }
14632
14633 vec4 i(vec4 x, vec4 y)
14634 {
14635 return vec4(x.xy, y.zw);
14636 }
14637
14638 void main() {
14639 col = h(e) + i(c.x, d[0].x) + d[1].x;
14640 }
14641 )";
14642
14643 GLuint program = CompileProgram(kVS, kFS);
14644 EXPECT_NE(0u, program);
14645 }
14646
14647 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)14648 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
14649 {
14650 constexpr char kVS[] = R"(#version 310 es
14651 precision mediump float;
14652 in highp vec4 variableWithSameName;
14653
14654 void main() {
14655 gl_Position = variableWithSameName;
14656 }
14657 )";
14658
14659 constexpr char kFS[] = R"(#version 310 es
14660 precision mediump float;
14661 uniform vec4 variableWithSameName;
14662 out vec4 col;
14663
14664 void main() {
14665 col = vec4(variableWithSameName);
14666 }
14667 )";
14668
14669 GLuint program = CompileProgram(kVS, kFS);
14670 EXPECT_NE(0u, program);
14671 }
14672
14673 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)14674 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
14675 {
14676 // Nvidia driver bug: http://anglebug.com/42263793
14677 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
14678
14679 constexpr char kVSUnused[] = R"(#version 300 es
14680 precision highp float;
14681 uniform highp vec4 positionIn;
14682
14683 void main()
14684 {
14685 gl_Position = vec4(1, 0, 0, 1);
14686 })";
14687
14688 constexpr char kVSStaticUse[] = R"(#version 300 es
14689 precision highp float;
14690 uniform highp vec4 positionIn;
14691
14692 void main()
14693 {
14694 gl_Position = positionIn;
14695 })";
14696
14697 constexpr char kFSUnused[] = R"(#version 300 es
14698 precision highp float;
14699 uniform highp vec4 positionIn;
14700 out vec4 my_FragColor;
14701
14702 void main()
14703 {
14704 my_FragColor = vec4(1, 0, 0, 1);
14705 })";
14706
14707 constexpr char kFSStaticUse[] = R"(#version 300 es
14708 precision highp float;
14709 uniform mediump vec4 positionIn;
14710 out vec4 my_FragColor;
14711
14712 void main()
14713 {
14714 my_FragColor = vec4(1, 0, 0, positionIn.z);
14715 })";
14716
14717 GLuint program = 0;
14718
14719 program = CompileProgram(kVSUnused, kFSUnused);
14720 EXPECT_NE(0u, program);
14721
14722 program = CompileProgram(kVSUnused, kFSStaticUse);
14723 EXPECT_NE(0u, program);
14724
14725 program = CompileProgram(kVSStaticUse, kFSUnused);
14726 EXPECT_NE(0u, program);
14727
14728 program = CompileProgram(kVSStaticUse, kFSStaticUse);
14729 EXPECT_EQ(0u, program);
14730 }
14731
14732 // Validate that link fails when two instanceless interface blocks with different block names but
14733 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)14734 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
14735 {
14736 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14737
14738 constexpr char kVS[] = R"(#version 310 es
14739 in highp vec4 position;
14740 layout(binding = 0) buffer BlockA { mediump float a; };
14741 void main()
14742 {
14743 a = 0.0;
14744 gl_Position = position;
14745 })";
14746
14747 constexpr char kFS[] = R"(#version 310 es
14748 precision mediump float;
14749 layout(location = 0) out mediump vec4 color;
14750 uniform BlockB { float a; };
14751 void main()
14752 {
14753 color = vec4(a, a, a, 1.0);
14754 })";
14755
14756 GLuint program = CompileProgram(kVS, kFS);
14757 EXPECT_EQ(0u, program);
14758 }
14759
14760 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)14761 TEST_P(GLSLTest_ES31, IOBlockLocations)
14762 {
14763 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14764 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14765
14766 constexpr char kVS[] = R"(#version 310 es
14767 #extension GL_EXT_shader_io_blocks : require
14768
14769 in highp vec4 position;
14770
14771 layout(location = 0) out vec4 aOut;
14772
14773 layout(location = 6) out VSBlock
14774 {
14775 vec4 b; // location 6
14776 vec4 c; // location 7
14777 layout(location = 1) vec4 d;
14778 vec4 e; // location 2
14779 vec4 f[2]; // locations 3 and 4
14780 } blockOut;
14781
14782 layout(location = 5) out vec4 gOut;
14783
14784 void main()
14785 {
14786 aOut = vec4(0.03, 0.06, 0.09, 0.12);
14787 blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
14788 blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
14789 blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
14790 blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
14791 blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
14792 blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
14793 gOut = vec4(0.84, 0.87, 0.9, 0.93);
14794 gl_Position = position;
14795 })";
14796
14797 constexpr char kGS[] = R"(#version 310 es
14798 #extension GL_EXT_geometry_shader : require
14799 layout (triangles) in;
14800 layout (triangle_strip, max_vertices = 3) out;
14801
14802 // Input varyings
14803 layout(location = 0) in vec4 aIn[];
14804
14805 layout(location = 6) in VSBlock
14806 {
14807 vec4 b;
14808 vec4 c;
14809 layout(location = 1) vec4 d;
14810 vec4 e;
14811 vec4 f[2];
14812 } blockIn[];
14813
14814 layout(location = 5) in vec4 gIn[];
14815
14816 // Output varyings
14817 layout(location = 1) out vec4 aOut;
14818
14819 layout(location = 0) out GSBlock
14820 {
14821 vec4 b; // location 0
14822 layout(location = 3) vec4 c;
14823 layout(location = 7) vec4 d;
14824 layout(location = 5) vec4 e[2];
14825 layout(location = 4) vec4 f;
14826 } blockOut;
14827
14828 layout(location = 2) out vec4 gOut;
14829
14830 void main()
14831 {
14832 int n;
14833 for (n = 0; n < gl_in.length(); n++)
14834 {
14835 gl_Position = gl_in[n].gl_Position;
14836
14837 aOut = aIn[n];
14838 blockOut.b = blockIn[n].b;
14839 blockOut.c = blockIn[n].c;
14840 blockOut.d = blockIn[n].d;
14841 blockOut.e[0] = blockIn[n].e;
14842 blockOut.e[1] = blockIn[n].f[0];
14843 blockOut.f = blockIn[n].f[1];
14844 gOut = gIn[n];
14845
14846 EmitVertex();
14847 }
14848 EndPrimitive();
14849 })";
14850
14851 constexpr char kFS[] = R"(#version 310 es
14852 #extension GL_EXT_shader_io_blocks : require
14853 precision mediump float;
14854
14855 layout(location = 0) out mediump vec4 color;
14856
14857 layout(location = 1) in vec4 aIn;
14858
14859 layout(location = 0) in GSBlock
14860 {
14861 vec4 b;
14862 layout(location = 3) vec4 c;
14863 layout(location = 7) vec4 d;
14864 layout(location = 5) vec4 e[2];
14865 layout(location = 4) vec4 f;
14866 } blockIn;
14867
14868 layout(location = 2) in vec4 gIn;
14869
14870 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14871
14872 void main()
14873 {
14874 bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
14875 bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
14876 isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
14877 isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
14878 isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14879 isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
14880 isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
14881 bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
14882
14883 color = vec4(passR, passG, passB, 1.0);
14884 })";
14885
14886 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14887 EXPECT_GL_NO_ERROR();
14888
14889 GLTexture color;
14890 glBindTexture(GL_TEXTURE_2D, color);
14891 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14892
14893 GLFramebuffer fbo;
14894 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14895 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14896
14897 drawQuad(program, "position", 0);
14898
14899 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14900 }
14901
14902 // Test using builtins that can only be redefined with gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexRedefinition)14903 TEST_P(GLSLTest_ES31, PerVertexRedefinition)
14904 {
14905 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14906 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14907
14908 constexpr char kVS[] = R"(#version 310 es
14909 void main()
14910 {
14911 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14912 })";
14913
14914 constexpr char kGS[] = R"(#version 310 es
14915 #extension GL_EXT_geometry_shader : require
14916 #extension GL_EXT_clip_cull_distance : require
14917
14918 layout(lines_adjacency, invocations = 3) in;
14919 layout(points, max_vertices = 16) out;
14920
14921 out gl_PerVertex {
14922 vec4 gl_Position;
14923 float gl_ClipDistance[4];
14924 float gl_CullDistance[4];
14925 };
14926
14927 void main()
14928 {
14929 for (int n = 0; n < 16; ++n)
14930 {
14931 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14932 EmitVertex();
14933 }
14934
14935 EndPrimitive();
14936 })";
14937
14938 constexpr char kFS[] = R"(#version 310 es
14939 precision highp float;
14940
14941 out vec4 result;
14942
14943 void main()
14944 {
14945 result = vec4(1.0);
14946 })";
14947
14948 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14949 EXPECT_GL_NO_ERROR();
14950 }
14951
14952 // Negative test using builtins that can only be used when redefining gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexNegativeTest)14953 TEST_P(GLSLTest_ES31, PerVertexNegativeTest)
14954 {
14955 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14956 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14957
14958 constexpr char kVS[] = R"(#version 310 es
14959 void main()
14960 {
14961 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14962 })";
14963
14964 constexpr char kGS[] = R"(#version 310 es
14965 #extension GL_EXT_geometry_shader : require
14966 #extension GL_EXT_clip_cull_distance : require
14967
14968 layout(lines_adjacency, invocations = 3) in;
14969 layout(points, max_vertices = 16) out;
14970
14971 vec4 gl_Position;
14972 float gl_ClipDistance[4];
14973 float gl_CullDistance[4];
14974
14975 void main()
14976 {
14977 for (int n = 0; n < 16; ++n)
14978 {
14979 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14980 EmitVertex();
14981 }
14982
14983 EndPrimitive();
14984 })";
14985
14986 constexpr char kFS[] = R"(#version 310 es
14987 precision highp float;
14988
14989 out vec4 result;
14990
14991 void main()
14992 {
14993 result = vec4(1.0);
14994 })";
14995
14996 GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14997 EXPECT_EQ(0u, program);
14998 glDeleteProgram(program);
14999 }
15000
15001 // Negative test using builtins that can only be used when redefining gl_PerVertex
15002 // but have the builtins in a differently named struct
TEST_P(GLSLTest_ES31,PerVertexRenamedNegativeTest)15003 TEST_P(GLSLTest_ES31, PerVertexRenamedNegativeTest)
15004 {
15005 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
15006 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
15007
15008 constexpr char kVS[] = R"(#version 310 es
15009 void main()
15010 {
15011 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
15012 })";
15013
15014 constexpr char kGS[] = R"(#version 310 es
15015 #extension GL_EXT_geometry_shader : require
15016 #extension GL_EXT_clip_cull_distance : require
15017
15018 layout(lines_adjacency, invocations = 3) in;
15019 layout(points, max_vertices = 16) out;
15020
15021 out Block {
15022 vec4 gl_Position;
15023 float gl_ClipDistance[4];
15024 float gl_CullDistance[4];
15025 };
15026
15027 void main()
15028 {
15029 for (int n = 0; n < 16; ++n)
15030 {
15031 gl_Position = vec4(n, 0.0, 0.0, 1.0);
15032 EmitVertex();
15033 }
15034
15035 EndPrimitive();
15036 })";
15037
15038 constexpr char kFS[] = R"(#version 310 es
15039 precision highp float;
15040
15041 out vec4 result;
15042
15043 void main()
15044 {
15045 result = vec4(1.0);
15046 })";
15047
15048 GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
15049 EXPECT_EQ(0u, program);
15050 glDeleteProgram(program);
15051 }
15052
15053 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)15054 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
15055 {
15056 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15057
15058 constexpr char kVS[] = R"(#version 310 es
15059 #extension GL_EXT_shader_io_blocks : require
15060
15061 in highp vec4 position;
15062
15063 out VSBlock1
15064 {
15065 vec4 a;
15066 vec4 b[2];
15067 } blockOut1;
15068
15069 out VSBlock2
15070 {
15071 vec4 c[2];
15072 vec4 d;
15073 } blockOut2;
15074
15075 void main()
15076 {
15077 blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
15078 blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
15079 blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
15080 blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
15081 blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
15082 blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
15083 gl_Position = position;
15084 })";
15085
15086 constexpr char kFS[] = R"(#version 310 es
15087 #extension GL_EXT_shader_io_blocks : require
15088 precision mediump float;
15089
15090 layout(location = 0) out mediump vec4 color;
15091
15092 in VSBlock1
15093 {
15094 vec4 a;
15095 vec4 b[2];
15096 } blockIn1;
15097
15098 in VSBlock2
15099 {
15100 vec4 c[2];
15101 vec4 d;
15102 } blockIn2;
15103
15104 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
15105
15106 void main()
15107 {
15108 bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
15109 bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
15110 isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
15111 bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
15112 isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
15113 bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
15114
15115 color = vec4(passR, passG, passB, passA);
15116 })";
15117
15118 ANGLE_GL_PROGRAM(program, kVS, kFS);
15119 EXPECT_GL_NO_ERROR();
15120
15121 GLTexture color;
15122 glBindTexture(GL_TEXTURE_2D, color);
15123 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
15124
15125 GLFramebuffer fbo;
15126 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15127 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
15128
15129 drawQuad(program, "position", 0);
15130
15131 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15132 }
15133
15134 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)15135 TEST_P(GLSLTest_ES31, IOBlockArray)
15136 {
15137 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15138
15139 constexpr char kVS[] = R"(#version 310 es
15140 #extension GL_EXT_shader_io_blocks : require
15141
15142 in highp vec4 position;
15143
15144 out VSBlock1
15145 {
15146 vec4 b[2];
15147 } blockOut1[2];
15148
15149 out VSBlock2
15150 {
15151 vec4 d;
15152 } blockOut2[3];
15153
15154 void main()
15155 {
15156 blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
15157 blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
15158 blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
15159 blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
15160 blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
15161 blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
15162 blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
15163 gl_Position = position;
15164 })";
15165
15166 constexpr char kFS[] = R"(#version 310 es
15167 #extension GL_EXT_shader_io_blocks : require
15168 precision mediump float;
15169
15170 layout(location = 0) out mediump vec4 color;
15171
15172 in VSBlock1
15173 {
15174 vec4 b[2];
15175 } blockIn1[2];
15176
15177 in VSBlock2
15178 {
15179 vec4 d;
15180 } blockIn2[3];
15181
15182 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
15183
15184 void main()
15185 {
15186 bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
15187 isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
15188 bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
15189 isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
15190 bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
15191 bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
15192 isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
15193
15194 color = vec4(passR, passG, passB, passA);
15195 })";
15196
15197 ANGLE_GL_PROGRAM(program, kVS, kFS);
15198 EXPECT_GL_NO_ERROR();
15199
15200 GLTexture color;
15201 glBindTexture(GL_TEXTURE_2D, color);
15202 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
15203
15204 GLFramebuffer fbo;
15205 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15206 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
15207
15208 drawQuad(program, "position", 0);
15209
15210 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15211 }
15212
15213 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)15214 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
15215 {
15216 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15217
15218 constexpr char kVS[] = R"(#version 310 es
15219 #extension GL_EXT_shader_io_blocks : require
15220 in highp vec4 position;
15221 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15222 void main()
15223 {
15224 blockOut1.a = vec4(0);
15225 blockOut1.b[0] = vec4(0);
15226 blockOut1.b[1] = vec4(0);
15227 gl_Position = position;
15228 })";
15229
15230 constexpr char kFS[] = R"(#version 310 es
15231 #extension GL_EXT_shader_io_blocks : require
15232 precision mediump float;
15233 layout(location = 0) out mediump vec4 color;
15234 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
15235 void main()
15236 {
15237 color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15238 })";
15239
15240 GLuint program = CompileProgram(kVS, kFS);
15241 EXPECT_EQ(0u, program);
15242 }
15243
15244 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)15245 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
15246 {
15247 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15248
15249 constexpr char kVS[] = R"(#version 310 es
15250 #extension GL_EXT_shader_io_blocks : require
15251 in highp vec4 position;
15252 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15253 void main()
15254 {
15255 blockOut1.a = vec4(0);
15256 blockOut1.b[0] = vec4(0);
15257 blockOut1.b[1] = vec4(0);
15258 gl_Position = position;
15259 })";
15260
15261 constexpr char kFS[] = R"(#version 310 es
15262 #extension GL_EXT_shader_io_blocks : require
15263 precision mediump float;
15264 layout(location = 0) out mediump vec4 color;
15265 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
15266 void main()
15267 {
15268 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15269 })";
15270
15271 GLuint program = CompileProgram(kVS, kFS);
15272 EXPECT_EQ(0u, program);
15273 }
15274
15275 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)15276 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
15277 {
15278 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15279
15280 constexpr char kVS[] = R"(#version 310 es
15281 #extension GL_EXT_shader_io_blocks : require
15282 in highp vec4 position;
15283 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15284 void main()
15285 {
15286 blockOut1.a = vec4(0);
15287 blockOut1.b[0] = vec4(0);
15288 blockOut1.b[1] = vec4(0);
15289 gl_Position = position;
15290 })";
15291
15292 constexpr char kFS[] = R"(#version 310 es
15293 #extension GL_EXT_shader_io_blocks : require
15294 precision mediump float;
15295 layout(location = 0) out mediump vec4 color;
15296 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
15297 void main()
15298 {
15299 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15300 })";
15301
15302 GLuint program = CompileProgram(kVS, kFS);
15303 EXPECT_EQ(0u, program);
15304 }
15305
15306 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)15307 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
15308 {
15309 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15310
15311 constexpr char kVS[] = R"(#version 310 es
15312 #extension GL_EXT_shader_io_blocks : require
15313 in highp vec4 position;
15314 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15315 void main()
15316 {
15317 blockOut1.a = vec4(0);
15318 blockOut1.b[0] = vec4(0);
15319 blockOut1.b[1] = vec4(0);
15320 gl_Position = position;
15321 })";
15322
15323 constexpr char kFS[] = R"(#version 310 es
15324 #extension GL_EXT_shader_io_blocks : require
15325 precision mediump float;
15326 layout(location = 0) out mediump vec4 color;
15327 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
15328 void main()
15329 {
15330 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15331 })";
15332
15333 GLuint program = CompileProgram(kVS, kFS);
15334 EXPECT_EQ(0u, program);
15335 }
15336
15337 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)15338 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
15339 {
15340 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15341
15342 constexpr char kVS[] = R"(#version 310 es
15343 #extension GL_EXT_shader_io_blocks : require
15344 in highp vec4 position;
15345 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
15346 void main()
15347 {
15348 blockOut1.a = vec4(0);
15349 blockOut1.b[0] = vec4(0);
15350 blockOut1.b[1] = vec4(0);
15351 gl_Position = position;
15352 })";
15353
15354 constexpr char kFS[] = R"(#version 310 es
15355 #extension GL_EXT_shader_io_blocks : require
15356 precision mediump float;
15357 layout(location = 0) out mediump vec4 color;
15358 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
15359 void main()
15360 {
15361 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15362 })";
15363
15364 GLuint program = CompileProgram(kVS, kFS);
15365 EXPECT_EQ(0u, program);
15366 }
15367
15368 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)15369 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
15370 {
15371 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15372
15373 constexpr char kVS[] = R"(#version 310 es
15374 #extension GL_EXT_shader_io_blocks : require
15375 in highp vec4 position;
15376 struct S1 { vec4 a; vec4 b[2]; };
15377 out VSBlock { S1 s; } blockOut1;
15378 void main()
15379 {
15380 blockOut1.s.a = vec4(0);
15381 blockOut1.s.b[0] = vec4(0);
15382 blockOut1.s.b[1] = vec4(0);
15383 gl_Position = position;
15384 })";
15385
15386 constexpr char kFS[] = R"(#version 310 es
15387 #extension GL_EXT_shader_io_blocks : require
15388 precision mediump float;
15389 layout(location = 0) out mediump vec4 color;
15390 struct S2 { vec4 a; vec4 b[2]; };
15391 in VSBlock { S2 s; } blockIn1;
15392 void main()
15393 {
15394 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15395 })";
15396
15397 GLuint program = CompileProgram(kVS, kFS);
15398 EXPECT_EQ(0u, program);
15399 }
15400
15401 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)15402 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
15403 {
15404 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15405
15406 constexpr char kVS[] = R"(#version 310 es
15407 #extension GL_EXT_shader_io_blocks : require
15408 in highp vec4 position;
15409 struct S { vec4 c; vec4 b[2]; };
15410 out VSBlock { S s; } blockOut1;
15411 void main()
15412 {
15413 blockOut1.s.c = vec4(0);
15414 blockOut1.s.b[0] = vec4(0);
15415 blockOut1.s.b[1] = vec4(0);
15416 gl_Position = position;
15417 })";
15418
15419 constexpr char kFS[] = R"(#version 310 es
15420 #extension GL_EXT_shader_io_blocks : require
15421 precision mediump float;
15422 layout(location = 0) out mediump vec4 color;
15423 struct S { vec4 a; vec4 b[2]; };
15424 in VSBlock { S s; } blockIn1;
15425 void main()
15426 {
15427 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15428 })";
15429
15430 GLuint program = CompileProgram(kVS, kFS);
15431 EXPECT_EQ(0u, program);
15432 }
15433
15434 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)15435 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
15436 {
15437 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15438
15439 constexpr char kVS[] = R"(#version 310 es
15440 #extension GL_EXT_shader_io_blocks : require
15441 in highp vec4 position;
15442 struct S { vec4 a; vec4 b[2]; };
15443 out VSBlock { S s; } blockOut1;
15444 void main()
15445 {
15446 blockOut1.s.a = vec4(0);
15447 blockOut1.s.b[0] = vec4(0);
15448 blockOut1.s.b[1] = vec4(0);
15449 gl_Position = position;
15450 })";
15451
15452 constexpr char kFS[] = R"(#version 310 es
15453 #extension GL_EXT_shader_io_blocks : require
15454 precision mediump float;
15455 layout(location = 0) out mediump vec4 color;
15456 struct S { vec3 a; vec4 b[2]; };
15457 in VSBlock { S s; } blockIn1;
15458 void main()
15459 {
15460 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15461 })";
15462
15463 GLuint program = CompileProgram(kVS, kFS);
15464 EXPECT_EQ(0u, program);
15465 }
15466
15467 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)15468 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
15469 {
15470 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15471
15472 constexpr char kVS[] = R"(#version 310 es
15473 #extension GL_EXT_shader_io_blocks : require
15474 in highp vec4 position;
15475 struct S { vec4 a; vec4 b[3]; };
15476 out VSBlock { S s; } blockOut1;
15477 void main()
15478 {
15479 blockOut1.s.a = vec4(0);
15480 blockOut1.s.b[0] = vec4(0);
15481 blockOut1.s.b[1] = vec4(0);
15482 gl_Position = position;
15483 })";
15484
15485 constexpr char kFS[] = R"(#version 310 es
15486 #extension GL_EXT_shader_io_blocks : require
15487 precision mediump float;
15488 layout(location = 0) out mediump vec4 color;
15489 struct S { vec4 a; vec4 b[2]; };
15490 in VSBlock { S s; } blockIn1;
15491 void main()
15492 {
15493 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15494 })";
15495
15496 GLuint program = CompileProgram(kVS, kFS);
15497 EXPECT_EQ(0u, program);
15498 }
15499
15500 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)15501 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
15502 {
15503 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15504
15505 constexpr char kVS[] = R"(#version 310 es
15506 #extension GL_EXT_shader_io_blocks : require
15507 in highp vec4 position;
15508 struct S { vec4 a; vec4 b[2]; vec4 c; };
15509 out VSBlock { S s; } blockOut1;
15510 void main()
15511 {
15512 blockOut1.s.c = vec4(0);
15513 blockOut1.s.b[0] = vec4(0);
15514 blockOut1.s.b[1] = vec4(0);
15515 gl_Position = position;
15516 })";
15517
15518 constexpr char kFS[] = R"(#version 310 es
15519 #extension GL_EXT_shader_io_blocks : require
15520 precision mediump float;
15521 layout(location = 0) out mediump vec4 color;
15522 struct S { vec4 a; vec4 b[2]; };
15523 in VSBlock { S s; } blockIn1;
15524 void main()
15525 {
15526 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15527 })";
15528
15529 GLuint program = CompileProgram(kVS, kFS);
15530 EXPECT_EQ(0u, program);
15531 }
15532
15533 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)15534 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
15535 {
15536 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15537
15538 constexpr char kVS[] = R"(#version 310 es
15539 #extension GL_EXT_shader_io_blocks : require
15540 in highp vec4 position;
15541 struct S1 { vec4 c; vec4 b[2]; };
15542 struct S2 { S1 s; };
15543 struct S3 { S2 s; };
15544 out VSBlock { S3 s; } blockOut1;
15545 void main()
15546 {
15547 blockOut1.s.s.s.c = vec4(0);
15548 blockOut1.s.s.s.b[0] = vec4(0);
15549 blockOut1.s.s.s.b[1] = vec4(0);
15550 gl_Position = position;
15551 })";
15552
15553 constexpr char kFS[] = R"(#version 310 es
15554 #extension GL_EXT_shader_io_blocks : require
15555 precision mediump float;
15556 layout(location = 0) out mediump vec4 color;
15557 struct S1 { vec4 a; vec4 b[2]; };
15558 struct S2 { S1 s; };
15559 struct S3 { S2 s; };
15560 in VSBlock { S3 s; } blockIn1;
15561 void main()
15562 {
15563 color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
15564 })";
15565
15566 GLuint program = CompileProgram(kVS, kFS);
15567 EXPECT_EQ(0u, program);
15568 }
15569
15570 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)15571 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
15572 {
15573 constexpr char kVS[] = R"(#version 310 es
15574 precision highp float;
15575
15576 struct S
15577 {
15578 mat4 a;
15579 mat4 b;
15580 };
15581
15582 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
15583
15584 void main() {
15585 S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
15586
15587 gl_Position = vec4(s3[1].a[0].x, s2[0][2].b[1].y, s4[1][0].a[2].z, s6[0].b[3].w);
15588 })";
15589
15590 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15591
15592 const char *sourceArray[1] = {kVS};
15593 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15594 glShaderSource(shader, 1, sourceArray, lengths);
15595 glCompileShader(shader);
15596
15597 GLint compileResult;
15598 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15599 EXPECT_NE(compileResult, 0);
15600 }
15601
15602 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)15603 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
15604 {
15605 constexpr char kVS[] = R"(#version 310 es
15606 precision highp float;
15607
15608 struct S
15609 {
15610 mat4 a;
15611 mat4 b;
15612 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
15613
15614 void main() {
15615 struct T
15616 {
15617 mat4 a;
15618 mat4 b;
15619 } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
15620
15621 float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
15622
15623 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
15624 })";
15625
15626 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15627
15628 const char *sourceArray[1] = {kVS};
15629 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15630 glShaderSource(shader, 1, sourceArray, lengths);
15631 glCompileShader(shader);
15632
15633 GLint compileResult;
15634 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15635 EXPECT_NE(compileResult, 0);
15636 }
15637
15638 // Test that separating declarators works with structs that are simultaneously defined and that are
15639 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)15640 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
15641 {
15642 constexpr char kVS[] = R"(#version 310 es
15643 precision highp float;
15644
15645 struct
15646 {
15647 mat4 a;
15648 mat4 b;
15649 } s1, s2[2][3], s3[2];
15650
15651 void main() {
15652 struct
15653 {
15654 mat4 a;
15655 mat4 b;
15656 } s4[2][3], s5, s6[2], s7 = s5;
15657
15658 float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
15659
15660 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
15661 })";
15662
15663 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15664
15665 const char *sourceArray[1] = {kVS};
15666 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15667 glShaderSource(shader, 1, sourceArray, lengths);
15668 glCompileShader(shader);
15669
15670 GLint compileResult;
15671 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15672 EXPECT_NE(compileResult, 0);
15673 }
15674
15675 // Test separation of struct declarations, case where separated struct is used as a member of
15676 // another struct.
TEST_P(GLSLTest,SeparateStructDeclaratorStructInStruct)15677 TEST_P(GLSLTest, SeparateStructDeclaratorStructInStruct)
15678 {
15679 const char kFragmentShader[] = R"(precision mediump float;
15680 uniform vec4 u;
15681 struct S1 { vec4 v; } a;
15682 void main()
15683 {
15684 struct S2 { S1 s1; } b;
15685 a.v = u;
15686 b.s1 = a;
15687 gl_FragColor = b.s1.v + vec4(0, 0, 0, 1);
15688 }
15689 )";
15690 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
15691 glUseProgram(program);
15692 GLint u = glGetUniformLocation(program, "u");
15693 glUniform4f(u, 0, 1, 0, 0);
15694 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
15695 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15696 }
15697
15698 // Regression test for transformation bug which separates struct declarations from uniform
15699 // declarations. The bug was that the uniform variable usage in the initializer of a new
15700 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)15701 TEST_P(GLSLTest, UniformStructBug)
15702 {
15703 constexpr char kVS[] = R"(precision highp float;
15704
15705 uniform struct Global
15706 {
15707 float x;
15708 } u_global;
15709
15710 void main() {
15711 float y = u_global.x;
15712
15713 gl_Position = vec4(y);
15714 })";
15715
15716 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15717
15718 const char *sourceArray[1] = {kVS};
15719 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15720 glShaderSource(shader, 1, sourceArray, lengths);
15721 glCompileShader(shader);
15722
15723 GLint compileResult;
15724 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15725 EXPECT_NE(compileResult, 0);
15726 }
15727
15728 // Regression test for transformation bug which separates struct declarations from uniform
15729 // declarations. The bug was that the arrayness of the declaration was not being applied to the
15730 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)15731 TEST_P(GLSLTest_ES31, UniformStructBug2)
15732 {
15733 constexpr char kVS[] = R"(#version 310 es
15734 precision highp float;
15735
15736 uniform struct Global
15737 {
15738 float x;
15739 } u_global[2][3];
15740
15741 void main() {
15742 float y = u_global[0][0].x;
15743
15744 gl_Position = vec4(y);
15745 })";
15746
15747 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15748
15749 const char *sourceArray[1] = {kVS};
15750 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15751 glShaderSource(shader, 1, sourceArray, lengths);
15752 glCompileShader(shader);
15753
15754 GLint compileResult;
15755 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15756 EXPECT_NE(compileResult, 0);
15757 }
15758
15759 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
15760 // was not found in the tree. Tests that struct declaration in function return value is visible to
15761 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)15762 TEST_P(GLSLTest, MissingStructDeclarationBug)
15763 {
15764 constexpr char kVS[] = R"(
15765 struct S
15766 {
15767 vec4 i;
15768 } p();
15769 void main()
15770 {
15771 S s;
15772 })";
15773
15774 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15775 EXPECT_NE(0u, shader);
15776 glDeleteShader(shader);
15777 }
15778
15779 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
15780 // was not found in the tree. Tests that struct declaration in function return value is visible to
15781 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)15782 TEST_P(GLSLTest, MissingStructDeclarationBug2)
15783 {
15784 constexpr char kVS[] = R"(
15785 struct T
15786 {
15787 vec4 I;
15788 } p();
15789 struct
15790 {
15791 T c;
15792 };
15793 void main()
15794 {
15795 })";
15796
15797 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15798 EXPECT_NE(0u, shader);
15799 glDeleteShader(shader);
15800 }
15801
15802 // Regression test for bug in HLSL code generation where the for loop init expression was expected
15803 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)15804 TEST_P(GLSLTest, HandleExcessiveLoopBug)
15805 {
15806 constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
15807
15808 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15809 EXPECT_NE(0u, shader);
15810 glDeleteShader(shader);
15811 }
15812
15813 // Regression test for a validation bug in the translator where func(void, int) was accepted even
15814 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)15815 TEST_P(GLSLTest, NoParameterAfterVoid)
15816 {
15817 constexpr char kVS[] = R"(void f(void, int a){}
15818 void main(){f(1);})";
15819
15820 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15821 EXPECT_EQ(0u, shader);
15822 glDeleteShader(shader);
15823 }
15824
15825 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)15826 TEST_P(GLSLTest, NoParameterAfterVoid2)
15827 {
15828 constexpr char kVS[] = R"(void f(void, void){}
15829 void main(){f();})";
15830
15831 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15832 EXPECT_EQ(0u, shader);
15833 glDeleteShader(shader);
15834 }
15835
15836 // Test that providing more components to a matrix constructor than necessary works. Based on a
15837 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)15838 TEST_P(GLSLTest, MatrixConstructor)
15839 {
15840 constexpr char kVS[] = R"(attribute vec4 aPosition;
15841 varying vec4 vColor;
15842 void main()
15843 {
15844 gl_Position = aPosition;
15845 vec4 color = vec4(aPosition.xy, 0, 1);
15846 mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
15847 vColor = m4[0];
15848 })";
15849
15850 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15851 EXPECT_NE(0u, shader);
15852 glDeleteShader(shader);
15853 }
15854
15855 // Test constructors without precision
TEST_P(GLSLTest,ConstructFromBoolVector)15856 TEST_P(GLSLTest, ConstructFromBoolVector)
15857 {
15858 constexpr char kFS[] = R"(precision mediump float;
15859 uniform float u;
15860 void main()
15861 {
15862 mat4 m = mat4(u);
15863 mat2(0, bvec3(m));
15864 gl_FragColor = vec4(m);
15865 })";
15866
15867 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15868 EXPECT_NE(0u, shader);
15869 glDeleteShader(shader);
15870 }
15871
15872 // Test constructing vector from matrix
TEST_P(GLSLTest,VectorConstructorFromMatrix)15873 TEST_P(GLSLTest, VectorConstructorFromMatrix)
15874 {
15875 constexpr char kFS[] = R"(precision mediump float;
15876 uniform mat2 umat2;
15877 void main()
15878 {
15879 gl_FragColor = vec4(umat2);
15880 })";
15881
15882 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15883 EXPECT_NE(0u, shader);
15884 glDeleteShader(shader);
15885 }
15886
15887 // Test constructing matrix from vectors
TEST_P(GLSLTest,MatrixConstructorFromVectors)15888 TEST_P(GLSLTest, MatrixConstructorFromVectors)
15889 {
15890 constexpr char kFS[] = R"(precision mediump float;
15891 uniform vec2 uvec2;
15892 void main()
15893 {
15894 mat2 m = mat2(uvec2, uvec2.yx);
15895 gl_FragColor = vec4(m * uvec2, uvec2);
15896 })";
15897
15898 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15899 glUseProgram(program);
15900
15901 GLint uloc = glGetUniformLocation(program, "uvec2");
15902 ASSERT_NE(uloc, -1);
15903 glUniform2f(uloc, 0.5, 0.8);
15904
15905 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15906 EXPECT_GL_NO_ERROR();
15907
15908 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(227, 204, 127, 204), 1);
15909 }
15910
15911 // Test that constructing vector and matrix inside multiple declarations preserves the correct order
15912 // of operations.
TEST_P(GLSLTest,ConstructorinSequenceOperator)15913 TEST_P(GLSLTest, ConstructorinSequenceOperator)
15914 {
15915 constexpr char kFS[] = R"(precision mediump float;
15916 uniform vec2 u;
15917 void main()
15918 {
15919 vec2 v = u;
15920 mat2 m = (v[0] += 1.0, mat2(v, v[1], -v[0]));
15921 gl_FragColor = vec4(m[0], m[1]);
15922 })";
15923
15924 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15925 glUseProgram(program);
15926
15927 GLint uloc = glGetUniformLocation(program, "u");
15928 ASSERT_NE(uloc, -1);
15929 glUniform2f(uloc, -0.5, 1.0);
15930
15931 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15932 EXPECT_GL_NO_ERROR();
15933
15934 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 255, 255, 0), 1);
15935 }
15936
15937 // Test that constructing vectors inside multiple declarations preserves the correct order
15938 // of operations.
TEST_P(GLSLTest,VectorConstructorsInMultiDeclaration)15939 TEST_P(GLSLTest, VectorConstructorsInMultiDeclaration)
15940 {
15941 constexpr char kFS[] = R"(precision mediump float;
15942 uniform vec2 u;
15943 void main()
15944 {
15945 vec2 v = vec2(u[0]),
15946 w = mat2(v, v) * u;
15947 gl_FragColor = vec4(v, w);
15948 })";
15949
15950 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15951 glUseProgram(program);
15952
15953 GLint uloc = glGetUniformLocation(program, "u");
15954 ASSERT_NE(uloc, -1);
15955 glUniform2f(uloc, 0.5, 0.8);
15956
15957 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15958 EXPECT_GL_NO_ERROR();
15959
15960 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 166, 166), 1);
15961 }
15962
15963 // Test complex constructor usage.
TEST_P(GLSLTest_ES3,ComplexConstructor)15964 TEST_P(GLSLTest_ES3, ComplexConstructor)
15965 {
15966 constexpr char kFS[] = R"(#version 300 es
15967 precision mediump float;
15968 uniform vec2 u; // = vec2(0.5, 0.8)
15969 uniform vec2 v; // = vec2(-0.2, 1.0)
15970
15971 out vec4 color;
15972
15973 bool f(mat2 m)
15974 {
15975 return m[0][0] > 0.;
15976 }
15977
15978 bool isEqual(float a, float b)
15979 {
15980 return abs(a - b) < 0.01;
15981 }
15982
15983 void main()
15984 {
15985 int shouldRemainZero = 0;
15986
15987 // Test side effects inside constructor args after short-circuit
15988 if (u.x < 0. && f(mat2(shouldRemainZero += 1, u, v)))
15989 {
15990 shouldRemainZero += 2;
15991 }
15992
15993 int shouldBecomeFive = 0;
15994
15995 // Test directly nested constructors
15996 mat4x3 m = mat4x3(mat2(shouldBecomeFive += 5, v, u));
15997
15998 // Test indirectly nested constructors
15999 mat2 m2 = mat2(f(mat2(u, v)), f(mat2(v, u)), f(mat2(f(mat2(1.)))), -1.);
16000
16001 // Verify
16002 bool sideEffectsOk = shouldRemainZero == 0 && shouldBecomeFive == 5;
16003
16004 bool mOk = isEqual(m[0][0], 5.) && isEqual(m[0][1], -0.2) && isEqual(m[0][2], 0.) &&
16005 isEqual(m[1][0], 1.) && isEqual(m[1][1], 0.5) && isEqual(m[1][2], 0.) &&
16006 isEqual(m[2][0], 0.) && isEqual(m[2][1], 0.) && isEqual(m[2][2], 1.) &&
16007 isEqual(m[3][0], 0.) && isEqual(m[3][1], 0.) && isEqual(m[3][2], 0.);
16008
16009 bool m2Ok = isEqual(m2[0][0], 1.) && isEqual(m2[0][1], 0.) &&
16010 isEqual(m2[1][0], 1.) && isEqual(m2[1][1], -1.);
16011
16012 color = vec4(sideEffectsOk ? 1 : 0, mOk ? 1 : 0, m2Ok ? 1 : 0, 1);
16013 })";
16014
16015 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16016 glUseProgram(program);
16017
16018 GLint uloc = glGetUniformLocation(program, "u");
16019 GLint vloc = glGetUniformLocation(program, "v");
16020 ASSERT_NE(uloc, -1);
16021 ASSERT_NE(vloc, -1);
16022 glUniform2f(uloc, 0.5, 0.8);
16023 glUniform2f(vloc, -0.2, 1.0);
16024
16025 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16026 EXPECT_GL_NO_ERROR();
16027
16028 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
16029 }
16030
16031 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)16032 TEST_P(GLSLTest_ES3, ScalarConstructor)
16033 {
16034 constexpr char kFS[] = R"(#version 300 es
16035 precision mediump float;
16036 uniform vec4 u;
16037 out vec4 color;
16038 void main()
16039 {
16040 float f1 = float(u);
16041 mat3 m = mat3(u, u, u);
16042 int i = int(m);
16043 color = vec4(f1, float(i), 0, 1);
16044 })";
16045
16046 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16047 glUseProgram(program);
16048
16049 GLint uloc = glGetUniformLocation(program, "u");
16050 ASSERT_NE(uloc, -1);
16051 glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
16052
16053 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16054 EXPECT_GL_NO_ERROR();
16055
16056 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
16057 }
16058
16059 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)16060 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
16061 {
16062 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
16063
16064 constexpr char kVS[] = R"(#version 300 es
16065 #extension GL_EXT_shader_non_constant_global_initializers : require
16066 uniform vec4 u;
16067 out vec4 color;
16068
16069 vec4 global1 = u;
16070 vec4 global2 = u + vec4(1);
16071 vec4 global3 = global1 * global2;
16072 void main()
16073 {
16074 color = global3;
16075 })";
16076
16077 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
16078 EXPECT_NE(0u, shader);
16079 glDeleteShader(shader);
16080 }
16081
16082 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)16083 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
16084 {
16085 constexpr char kFS[] = R"(#version 300 es
16086 precision highp float;
16087 out vec4 color;
16088
16089 struct T
16090 {
16091 float f;
16092 };
16093
16094 struct S
16095 {
16096 vec4 v;
16097 mat3x4 m[2];
16098 T t;
16099 };
16100
16101 S s = S(
16102 vec4(0, 1, 2, 3),
16103 mat3x4[2](
16104 mat3x4(
16105 vec4(4, 5, 6, 7),
16106 vec4(8, 9, 10, 11),
16107 vec4(12, 13, 14, 15)
16108 ),
16109 mat3x4(
16110 vec4(16, 17, 18, 19),
16111 vec4(20, 21, 22, 23),
16112 vec4(24, 25, 26, 27)
16113 )
16114 ),
16115 T(28.0)
16116 );
16117
16118 void main()
16119 {
16120 vec4 result = vec4(0, 1, 0, 1);
16121
16122 if (s.v != vec4(0, 1, 2, 3))
16123 result = vec4(1, 0, 0, 0);
16124
16125 for (int index = 0; index < 2; ++index)
16126 {
16127 for (int column = 0; column < 3; ++column)
16128 {
16129 int expect = index * 12 + column * 4 + 4;
16130 if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
16131 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
16132 }
16133 }
16134
16135 if (s.t.f != 28.0)
16136 result = vec4(0, 0, 1, 0);
16137
16138 color = result;
16139 })";
16140
16141 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16142
16143 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16144 EXPECT_GL_NO_ERROR();
16145
16146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16147 }
16148
16149 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)16150 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
16151 {
16152 constexpr char kFS[] = R"(#version 310 es
16153 precision highp float;
16154 precision highp int;
16155
16156 out vec4 color;
16157
16158 uniform float f; // = 3.41
16159 uniform uvec4 u1; // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
16160 uniform uvec4 u2; // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
16161
16162 struct S
16163 {
16164 float fvalue;
16165 int ivalues[2];
16166 uvec4 uvalues[3];
16167 };
16168
16169 struct T
16170 {
16171 S s[2];
16172 };
16173
16174 void main()
16175 {
16176 float integer;
16177 float fraction = modf(f, integer);
16178
16179 T t;
16180
16181 t.s[0].fvalue = frexp(f, t.s[0].ivalues[0]);
16182 float significand = t.s[0].fvalue;
16183 int exponent = t.s[0].ivalues[0];
16184
16185 t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
16186 uvec4 addResult = t.s[0].uvalues[0];
16187 uvec4 addCarry = t.s[0].uvalues[1].yxwz;
16188
16189 t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
16190 uvec2 subResult = t.s[0].uvalues[2].wx;
16191 uvec2 subBorrow = t.s[1].uvalues[0].wx;
16192
16193 umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
16194 uvec4 mulMsb = t.s[1].uvalues[1];
16195 uvec4 mulLsb = t.s[1].uvalues[2];
16196
16197 ivec2 imulMsb, imulLsb;
16198 imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
16199
16200 bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
16201 bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
16202 bool addPassed =
16203 addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
16204 addCarry == uvec4(1, 0, 1, 0);
16205 bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
16206 bool mulPassed =
16207 mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
16208 mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
16209 bool imulPassed =
16210 imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
16211 imulLsb == ivec2(0x35068740, 0x822E97E0);
16212
16213 color = vec4(modfPassed ? 1 : 0,
16214 frexpPassed ? 1 : 0,
16215 (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
16216 (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
16217 })";
16218
16219 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
16220 glUseProgram(program);
16221
16222 GLint floc = glGetUniformLocation(program, "f");
16223 GLint u1loc = glGetUniformLocation(program, "u1");
16224 GLint u2loc = glGetUniformLocation(program, "u2");
16225 ASSERT_NE(floc, -1);
16226 ASSERT_NE(u1loc, -1);
16227 ASSERT_NE(u2loc, -1);
16228 glUniform1f(floc, 3.41);
16229 glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
16230 glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
16231
16232 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
16233 EXPECT_GL_NO_ERROR();
16234
16235 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
16236 }
16237
16238 class GLSLTestLoops : public GLSLTest
16239 {
16240 protected:
runTest(const char * fs)16241 void runTest(const char *fs)
16242 {
16243 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
16244
16245 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16246 EXPECT_GL_NO_ERROR();
16247
16248 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16249 }
16250 };
16251
16252 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)16253 TEST_P(GLSLTestLoops, BasicFor)
16254 {
16255 constexpr char kFS[] = R"(#version 300 es
16256 precision mediump float;
16257 out vec4 color;
16258
16259 void main()
16260 {
16261 int result = 0;
16262 for (int i = 0; i < 10; ++i)
16263 for (int j = 0; j < 8; ++j)
16264 {
16265 for (int k = 0; k < 2; ++k, ++j) ++result;
16266 for (int k = 0; k < 3; ++k) ++result;
16267 for (int k = 0; k < 0; ++k) ++result;
16268 }
16269
16270 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16271 })";
16272
16273 runTest(kFS);
16274 }
16275
16276 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)16277 TEST_P(GLSLTestLoops, ForNoCondition)
16278 {
16279 constexpr char kFS[] = R"(#version 300 es
16280 precision mediump float;
16281 out vec4 color;
16282
16283 void main()
16284 {
16285 int result = 0;
16286 for (int i = 0; i < 10; ++i)
16287 for (int j = 0; ; ++j)
16288 {
16289 for (int k = 0; k < 2; ++k, ++j) ++result;
16290 for (int k = 0; k < 3; ++k) ++result;
16291 for (int k = 0; k < 0; ++k) ++result;
16292
16293 if (j >= 8)
16294 break;
16295 }
16296
16297 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16298 })";
16299
16300 runTest(kFS);
16301 }
16302
16303 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)16304 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
16305 {
16306 constexpr char kFS[] = R"(#version 300 es
16307 precision mediump float;
16308 out vec4 color;
16309
16310 void main()
16311 {
16312 int result = 0;
16313 for (int i = 0; i < 10; ++i)
16314 {
16315 int j = 0;
16316 for (;;)
16317 {
16318 for (int k = 0; k < 2; ++k, ++j) ++result;
16319 for (int k = 0; k < 3; ++k) ++result;
16320 for (int k = 0; k < 0; ++k) ++result;
16321
16322 if (j >= 8)
16323 break;
16324 ++j;
16325 }
16326 }
16327
16328 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16329 })";
16330
16331 runTest(kFS);
16332 }
16333
16334 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)16335 TEST_P(GLSLTestLoops, ForContinue)
16336 {
16337 constexpr char kFS[] = R"(#version 300 es
16338 precision mediump float;
16339 out vec4 color;
16340
16341 void main()
16342 {
16343 int result = 0;
16344 for (int i = 0; i < 10; ++i)
16345 for (int j = 0; j < 8; ++j)
16346 {
16347 for (int k = 0; k < 2; ++k, ++j) ++result;
16348 for (int k = 0; k < 3; ++k) ++result;
16349 if (i > 3)
16350 continue;
16351 for (int k = 0; k < 0; ++k) ++result;
16352 }
16353
16354 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16355 })";
16356
16357 runTest(kFS);
16358 }
16359
16360 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)16361 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
16362 {
16363 constexpr char kFS[] = R"(#version 300 es
16364 precision mediump float;
16365 out vec4 color;
16366
16367 void main()
16368 {
16369 int result = 0;
16370 for (int i = 0; i < 10; ++i)
16371 for (int j = 0; j < 8; ++j)
16372 {
16373 for (int k = 0; k < 2; ++k, ++j) ++result;
16374 for (int k = 0; k < 3; ++k) ++result;
16375 for (int k = 0; k < 0; ++k) ++result;
16376 continue;
16377 }
16378
16379 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16380 })";
16381
16382 runTest(kFS);
16383 }
16384
16385 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)16386 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
16387 {
16388 constexpr char kFS[] = R"(#version 300 es
16389 precision mediump float;
16390 out vec4 color;
16391
16392 void main()
16393 {
16394 int result = 0;
16395 for (int i = 0; i < 10; ++i)
16396 for (int j = 0; j < 8; ++j)
16397 {
16398 for (int k = 0; k < 2; ++k, ++j) ++result;
16399 for (int k = 0; k < 3; ++k) ++result;
16400 for (int k = 0; k < 0; ++k) ++result;
16401 break;
16402 }
16403
16404 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16405 })";
16406
16407 runTest(kFS);
16408 }
16409
16410 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)16411 TEST_P(GLSLTestLoops, ForBreakContinue)
16412 {
16413 constexpr char kFS[] = R"(#version 300 es
16414 precision mediump float;
16415 out vec4 color;
16416
16417 void main()
16418 {
16419 int result = 0;
16420 for (int i = 0; i < 10; ++i)
16421 for (int j = 0; j < 8; ++j)
16422 {
16423 if (j < 2) continue;
16424 if (j > 6) break;
16425 if (i < 3) continue;
16426 if (i > 8) break;
16427 ++result;
16428 }
16429
16430 color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16431 })";
16432
16433 runTest(kFS);
16434 }
16435
16436 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)16437 TEST_P(GLSLTestLoops, BasicWhile)
16438 {
16439 constexpr char kFS[] = R"(#version 300 es
16440 precision mediump float;
16441 out vec4 color;
16442
16443 void main()
16444 {
16445 int result = 0;
16446 int i = 0;
16447 while (i < 10)
16448 {
16449 int j = 0;
16450 while (j < 8)
16451 {
16452 int k = 0;
16453 while (k < 2) { ++result; ++k; ++j; }
16454 while (k < 5) { ++result; ++k; }
16455 while (k < 4) { ++result; }
16456 ++j;
16457 }
16458 ++i;
16459 }
16460
16461 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16462 })";
16463
16464 runTest(kFS);
16465 }
16466
16467 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)16468 TEST_P(GLSLTestLoops, WhileContinue)
16469 {
16470 constexpr char kFS[] = R"(#version 300 es
16471 precision mediump float;
16472 out vec4 color;
16473
16474 void main()
16475 {
16476 int result = 0;
16477 int i = 0;
16478 while (i < 10)
16479 {
16480 int j = 0;
16481 while (j < 8)
16482 {
16483 int k = 0;
16484 while (k < 2) { ++result; ++k; ++j; }
16485 while (k < 5) { ++result; ++k; }
16486 if (i > 3)
16487 {
16488 ++j;
16489 continue;
16490 }
16491 while (k < 4) { ++result; }
16492 ++j;
16493 }
16494 ++i;
16495 }
16496
16497 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16498 })";
16499
16500 runTest(kFS);
16501 }
16502
16503 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)16504 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
16505 {
16506 constexpr char kFS[] = R"(#version 300 es
16507 precision mediump float;
16508 out vec4 color;
16509
16510 void main()
16511 {
16512 int result = 0;
16513 int i = 0;
16514 while (i < 10)
16515 {
16516 int j = 0;
16517 while (j < 8)
16518 {
16519 int k = 0;
16520 while (k < 2) { ++result; ++k; ++j; }
16521 while (k < 5) { ++result; ++k; }
16522 while (k < 4) { ++result; }
16523 ++j;
16524 continue;
16525 }
16526 ++i;
16527 }
16528
16529 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16530 })";
16531
16532 runTest(kFS);
16533 }
16534
16535 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)16536 TEST_P(GLSLTestLoops, WhileBreak)
16537 {
16538 constexpr char kFS[] = R"(#version 300 es
16539 precision mediump float;
16540 out vec4 color;
16541
16542 void main()
16543 {
16544 int result = 0;
16545 int i = 0;
16546 while (i < 10)
16547 {
16548 int j = 0;
16549 while (true)
16550 {
16551 int k = 0;
16552 while (k < 2) { ++result; ++k; ++j; }
16553 while (k < 5) { ++result; ++k; }
16554 while (k < 4) { ++result; }
16555 ++j;
16556 if (j >= 8)
16557 break;
16558 }
16559 ++i;
16560 }
16561
16562 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16563 })";
16564
16565 runTest(kFS);
16566 }
16567
16568 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)16569 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
16570 {
16571 constexpr char kFS[] = R"(#version 300 es
16572 precision mediump float;
16573 out vec4 color;
16574
16575 void main()
16576 {
16577 int result = 0;
16578 int i = 0;
16579 while (i < 10)
16580 {
16581 int j = 0;
16582 while (j < 8)
16583 {
16584 int k = 0;
16585 while (k < 2) { ++result; ++k; ++j; }
16586 while (k < 5) { ++result; ++k; }
16587 while (k < 4) { ++result; }
16588 ++j;
16589 break;
16590 }
16591 ++i;
16592 }
16593
16594 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16595 })";
16596
16597 runTest(kFS);
16598 }
16599
16600 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)16601 TEST_P(GLSLTestLoops, BasicDoWhile)
16602 {
16603 constexpr char kFS[] = R"(#version 300 es
16604 precision mediump float;
16605 out vec4 color;
16606
16607 void main()
16608 {
16609 int result = 0;
16610 int i = 0;
16611 do
16612 {
16613 int j = 0;
16614 do
16615 {
16616 int k = 0;
16617 do { ++result; ++k; ++j; } while (k < 2);
16618 do { ++result; ++k; } while (k < 5);
16619 do { ++result; } while (k < 3);
16620 ++j;
16621 } while (j < 8);
16622 ++i;
16623 } while (i < 10);
16624
16625 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16626 })";
16627
16628 runTest(kFS);
16629 }
16630
16631 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)16632 TEST_P(GLSLTestLoops, DoWhileContinue)
16633 {
16634 constexpr char kFS[] = R"(#version 300 es
16635 precision mediump float;
16636 out vec4 color;
16637
16638 void main()
16639 {
16640 int result = 0;
16641 int i = 0;
16642 do
16643 {
16644 int j = 0;
16645 do
16646 {
16647 int k = 0;
16648 do { ++result; ++k; ++j; } while (k < 2);
16649 if (i > 3)
16650 {
16651 ++j;
16652 continue;
16653 }
16654 do { ++result; ++k; } while (k < 5);
16655 do { ++result; } while (k < 3);
16656 ++j;
16657 } while (j < 8);
16658 ++i;
16659 } while (i < 10);
16660
16661 color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16662 })";
16663
16664 runTest(kFS);
16665 }
16666
16667 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)16668 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
16669 {
16670 constexpr char kFS[] = R"(#version 300 es
16671 precision mediump float;
16672 out vec4 color;
16673
16674 void main()
16675 {
16676 int result = 0;
16677 int i = 0;
16678 do
16679 {
16680 int j = 0;
16681 do
16682 {
16683 int k = 0;
16684 do { ++result; ++k; ++j; continue; } while (k < 2);
16685 do { ++result; ++k; continue; } while (k < 5);
16686 do { ++result; continue; } while (k < 3);
16687 ++j;
16688 } while (j < 8);
16689 ++i;
16690 } while (i < 10);
16691
16692 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16693 })";
16694
16695 runTest(kFS);
16696 }
16697
16698 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)16699 TEST_P(GLSLTestLoops, DoWhileBreak)
16700 {
16701 constexpr char kFS[] = R"(#version 300 es
16702 precision mediump float;
16703 out vec4 color;
16704
16705 void main()
16706 {
16707 int result = 0;
16708 int i = 0;
16709 do
16710 {
16711 int j = 0;
16712 do
16713 {
16714 int k = 0;
16715 do { ++result; ++k; ++j; } while (k < 2);
16716 do { ++result; ++k; } while (k < 5);
16717 do { ++result; } while (k < 3);
16718 ++j;
16719 if (j >= 8)
16720 break;
16721 } while (true);
16722 ++i;
16723 } while (i < 10);
16724
16725 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16726 })";
16727
16728 runTest(kFS);
16729 }
16730
16731 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)16732 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
16733 {
16734 constexpr char kFS[] = R"(#version 300 es
16735 precision mediump float;
16736 out vec4 color;
16737
16738 void main()
16739 {
16740 int result = 0;
16741 int i = 0;
16742 do
16743 {
16744 int j = 0;
16745 do
16746 {
16747 int k = 0;
16748 do { ++result; ++k; ++j; break; } while (k < 2);
16749 do { ++result; ++k; break; } while (k < 5);
16750 do { ++result; break; } while (k < 3);
16751 ++j;
16752 } while (j < 8);
16753 ++i;
16754 } while (i < 10);
16755
16756 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16757 })";
16758
16759 runTest(kFS);
16760 }
16761
16762 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)16763 TEST_P(GLSLTestLoops, ForContinueInSwitch)
16764 {
16765 constexpr char kFS[] = R"(#version 300 es
16766 precision mediump float;
16767 out vec4 color;
16768
16769 void main()
16770 {
16771 int result = 0;
16772 for (int i = 0; i < 10; ++i)
16773 for (int j = 0; j < 8; ++j)
16774 {
16775 switch (j)
16776 {
16777 case 2:
16778 case 3:
16779 case 4:
16780 ++result;
16781 // fallthrough
16782 case 5:
16783 case 6:
16784 ++result;
16785 break;
16786 default:
16787 continue;
16788 }
16789 }
16790
16791 color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16792 })";
16793
16794 runTest(kFS);
16795 }
16796
16797 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)16798 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
16799 {
16800 constexpr char kFS[] = R"(#version 300 es
16801 precision mediump float;
16802 out vec4 color;
16803
16804 void main()
16805 {
16806 int result = 0;
16807 int i = 0;
16808 while (i < 10)
16809 {
16810 int j = 0;
16811 while (j < 8)
16812 {
16813 switch (j)
16814 {
16815 case 2:
16816 default:
16817 case 3:
16818 case 4:
16819 ++j;
16820 ++result;
16821 continue;
16822 case 0:
16823 case 1:
16824 case 7:
16825 break;
16826 }
16827 ++j;
16828 }
16829 ++i;
16830 }
16831
16832 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16833 })";
16834
16835 runTest(kFS);
16836 }
16837
16838 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)16839 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
16840 {
16841 constexpr char kFS[] = R"(#version 300 es
16842 precision mediump float;
16843 out vec4 color;
16844
16845 void main()
16846 {
16847 int result = 0;
16848 int i = 0;
16849 do
16850 {
16851 int j = 0;
16852 do
16853 {
16854 switch (j)
16855 {
16856 case 0:
16857 ++j;
16858 continue;
16859 default:
16860 case 2:
16861 case 3:
16862 case 4:
16863 ++j;
16864 ++result;
16865 if (j >= 2 && j <= 6)
16866 break;
16867 else
16868 continue;
16869 }
16870 ++result;
16871 } while (j < 8);
16872 ++i;
16873 } while (i < 10);
16874
16875 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16876 })";
16877
16878 runTest(kFS);
16879 }
16880
16881 // Test prune-able loop with side effect in statements.
TEST_P(GLSLTestLoops,SideEffectsInPrunableFor)16882 TEST_P(GLSLTestLoops, SideEffectsInPrunableFor)
16883 {
16884 constexpr char kFS[] = R"(#version 300 es
16885 precision mediump float;
16886 out vec4 color;
16887
16888 void main()
16889 {
16890 int a = 4;
16891 float b = 0.;
16892 for (int c = a++; (b += float(c) / 8.) < 0.; b += 0.3)
16893 {
16894 if (2 == 0);
16895 }
16896 int c = a - 4;
16897
16898 // Expect c to be 1 and b to be 0.5
16899 color = c == 1 && abs(b - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16900 })";
16901
16902 runTest(kFS);
16903 }
16904
16905 // Test that precision is retained for constants (which are constant folded). Adapted from a WebGL
16906 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)16907 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
16908 {
16909 constexpr char kFS[] = R"(
16910 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
16911 uniform mediump float uTest;
16912 void main() {
16913 // exact representation of 4096.5 requires 13 bits of relative precision.
16914 const highp float c = 4096.5;
16915 mediump float a = 0.0;
16916 // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
16917 // Thus fract should also be evaluated at highp.
16918 // See OpenGL ES Shading Language spec section 4.5.2.
16919 // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
16920 // (exceptions for operation precision are allowed for a small number of computationally
16921 // intensive built-in functions, but it is reasonable to think that fract is not one of those).
16922 // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
16923 // or at IEEE half float precision, the result is 0.0.
16924 a = fract(c + uTest);
16925 // Multiply by 2.0 to make the color green.
16926 gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
16927 })";
16928
16929 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
16930
16931 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16932 EXPECT_GL_NO_ERROR();
16933
16934 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16935 }
16936
16937 // Test that vector and matrix scalarization does not affect rendering.
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)16938 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
16939 {
16940 constexpr char kFS[] = R"(
16941 precision mediump float;
16942
16943 varying vec2 v_texCoord;
16944
16945 float a = 0.;
16946 #define A 0.
16947
16948 #define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
16949 vec2 c;
16950 #define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
16951
16952 void main() {
16953 vec2 U = v_texCoord;
16954
16955 gl_FragColor = U.y > .5
16956 ? vec4( f(U,a) , f(U*4.,a) , 0,1.0) // top
16957 : vec4( f(U,A) , f(U*4.,A) , 0,1.0); // bottom
16958 }
16959
16960 )";
16961
16962 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
16963 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16964
16965 // Make sure we rendered something.
16966 EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
16967
16968 // Comapare one line in top half to one line in bottom half.
16969 int compareWidth = getWindowWidth();
16970 int compareHeight = getWindowHeight() / 4;
16971
16972 ASSERT_GE(compareWidth, 2);
16973 ASSERT_GE(compareHeight, 2);
16974
16975 GLubyte pixelValue[4];
16976 constexpr int tolerance = 12;
16977
16978 for (int x = 0; x < compareWidth; ++x)
16979 {
16980 glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
16981 EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
16982 pixelValue[2], pixelValue[3], tolerance);
16983 }
16984 EXPECT_GL_NO_ERROR();
16985 }
16986
16987 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)16988 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
16989 {
16990 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16991
16992 const char kVS[] = R"(#version 310 es
16993 #extension GL_EXT_shader_io_blocks : require
16994 in vec4 position;
16995 out BlockType {
16996 vec4 blockMember;
16997 } BlockTypeOut;
16998
16999 void main()
17000 {
17001 gl_Position = position;
17002 })";
17003
17004 const char kFS[] = R"(#version 310 es
17005 #extension GL_EXT_shader_io_blocks : require
17006 precision mediump float;
17007 out vec4 colorOut;
17008 in BlockType {
17009 vec4 blockMember;
17010 } BlockTypeOut;
17011
17012 void main()
17013 {
17014 if (BlockTypeOut.blockMember == vec4(0)) {
17015 colorOut = vec4(0, 1, 0, 1);
17016 } else {
17017 colorOut = vec4(1, 0, 0, 1);
17018 }
17019 })";
17020
17021 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17022 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17023 ASSERT_GL_NO_ERROR();
17024 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17025 }
17026
17027 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)17028 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
17029 {
17030 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17031
17032 const char kVS[] = R"(#version 310 es
17033 #extension GL_EXT_shader_io_blocks : require
17034 in vec4 position;
17035 out BlockType {
17036 vec4 blockMember;
17037 };
17038
17039 void main()
17040 {
17041 gl_Position = position;
17042 })";
17043
17044 const char kFS[] = R"(#version 310 es
17045 #extension GL_EXT_shader_io_blocks : require
17046 precision mediump float;
17047 out vec4 colorOut;
17048 in BlockType {
17049 vec4 blockMember;
17050 };
17051
17052 void main()
17053 {
17054 if (blockMember == vec4(0)) {
17055 colorOut = vec4(0, 1, 0, 1);
17056 } else {
17057 colorOut = vec4(1, 0, 0, 1);
17058 }
17059 })";
17060
17061 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17062 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17063 ASSERT_GL_NO_ERROR();
17064 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17065 }
17066
17067 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)17068 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
17069 {
17070 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17071
17072 const char kVS[] = R"(#version 310 es
17073 #extension GL_EXT_shader_io_blocks : require
17074 in vec4 position;
17075 out BlockType {
17076 vec4 blockMember[2];
17077 } BlockTypeOut;
17078
17079 void main()
17080 {
17081 gl_Position = position;
17082 })";
17083
17084 const char kFS[] = R"(#version 310 es
17085 #extension GL_EXT_shader_io_blocks : require
17086 precision mediump float;
17087 out vec4 colorOut;
17088 in BlockType {
17089 vec4 blockMember[2];
17090 } BlockTypeOut;
17091
17092 void main()
17093 {
17094 if (BlockTypeOut.blockMember[0] == vec4(0) &&
17095 BlockTypeOut.blockMember[1] == vec4(0)) {
17096 colorOut = vec4(0, 1, 0, 1);
17097 } else {
17098 colorOut = vec4(1, 0, 0, 1);
17099 }
17100 })";
17101
17102 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17103 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17104 ASSERT_GL_NO_ERROR();
17105 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17106 }
17107
17108 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)17109 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
17110 {
17111 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17112
17113 const char kVS[] = R"(#version 310 es
17114 #extension GL_EXT_shader_io_blocks : require
17115 in vec4 position;
17116 out BlockType {
17117 vec4 blockMember;
17118 } BlockTypeOut[2];
17119
17120 void main()
17121 {
17122 gl_Position = position;
17123 })";
17124
17125 const char kFS[] = R"(#version 310 es
17126 #extension GL_EXT_shader_io_blocks : require
17127 precision mediump float;
17128 out vec4 colorOut;
17129 in BlockType {
17130 vec4 blockMember;
17131 } BlockTypeOut[2];
17132
17133 void main()
17134 {
17135 if (BlockTypeOut[0].blockMember == vec4(0) &&
17136 BlockTypeOut[1].blockMember == vec4(0)) {
17137 colorOut = vec4(0, 1, 0, 1);
17138 } else {
17139 colorOut = vec4(1, 0, 0, 1);
17140 }
17141 })";
17142
17143 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17144 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17145 ASSERT_GL_NO_ERROR();
17146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17147 }
17148
17149 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)17150 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
17151 {
17152 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17153
17154 const char kVS[] = R"(#version 310 es
17155 #extension GL_EXT_shader_io_blocks : require
17156 in vec4 position;
17157 struct s {
17158 float f;
17159 vec2 v;
17160 };
17161 out BlockType {
17162 s blockMember;
17163 } BlockTypeOut;
17164
17165 void main()
17166 {
17167 gl_Position = position;
17168 })";
17169
17170 const char kFS[] = R"(#version 310 es
17171 #extension GL_EXT_shader_io_blocks : require
17172 precision mediump float;
17173 out vec4 colorOut;
17174 struct s {
17175 float f;
17176 vec2 v;
17177 };
17178 in BlockType {
17179 s blockMember;
17180 } BlockTypeOut;
17181
17182 void main()
17183 {
17184 if (BlockTypeOut.blockMember.f == 0.0 &&
17185 BlockTypeOut.blockMember.v == vec2(0)) {
17186 colorOut = vec4(0, 1, 0, 1);
17187 } else {
17188 colorOut = vec4(1, 0, 0, 1);
17189 }
17190 })";
17191
17192 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17193 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17194 ASSERT_GL_NO_ERROR();
17195 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17196 }
17197
17198 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)17199 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
17200 {
17201 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17202
17203 const char kVS[] = R"(#version 310 es
17204 #extension GL_EXT_shader_io_blocks : require
17205 in vec4 position;
17206 struct s {
17207 float f;
17208 vec2 v;
17209 };
17210 out BlockType {
17211 vec4 v;
17212 s s1;
17213 s s2[2];
17214 } BlockTypeOut;
17215
17216 void main()
17217 {
17218 gl_Position = position;
17219 })";
17220
17221 const char kFS[] = R"(#version 310 es
17222 #extension GL_EXT_shader_io_blocks : require
17223 precision mediump float;
17224 out vec4 colorOut;
17225 struct s {
17226 float f;
17227 vec2 v;
17228 };
17229 in BlockType {
17230 vec4 v;
17231 s s1;
17232 s s2[2];
17233 } BlockTypeOut;
17234
17235 void main()
17236 {
17237 s sz = s(0.0, vec2(0));
17238 if (BlockTypeOut.v == vec4(0) &&
17239 BlockTypeOut.s1 == sz &&
17240 BlockTypeOut.s2[0] == sz &&
17241 BlockTypeOut.s2[1] == sz) {
17242 colorOut = vec4(0, 1, 0, 1);
17243 } else {
17244 colorOut = vec4(1, 0, 0, 1);
17245 }
17246 })";
17247
17248 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17249 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17250 ASSERT_GL_NO_ERROR();
17251 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17252 }
17253
17254 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)17255 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
17256 {
17257 // Make a simple program.
17258 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17259
17260 // Install the executable.
17261 glUseProgram(testProgram);
17262
17263 // Re-link with a bad XFB varying and a bound attrib location.
17264 const char *tfVaryings = "gl_FragColor";
17265 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17266 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
17267 glLinkProgram(testProgram);
17268 GLint linkStatus = 999;
17269 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
17270 ASSERT_GL_NO_ERROR();
17271 ASSERT_EQ(linkStatus, GL_FALSE);
17272
17273 // Under normal GL this is not an error.
17274 glDrawArrays(GL_TRIANGLES, 79, 16);
17275 EXPECT_GL_NO_ERROR();
17276 }
17277
17278 // Regression test for an unsuccessful link with a varying followed by another link
TEST_P(GLSLTest_ES3,UnsuccessfulLinkFollowedByAnotherLink)17279 TEST_P(GLSLTest_ES3, UnsuccessfulLinkFollowedByAnotherLink)
17280 {
17281 // Make a simple program.
17282 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17283
17284 // Install the executable.
17285 glUseProgram(program);
17286
17287 // Re-link with a bad XFB varying and a bound attrib location.
17288 const char *tfVaryings = "gl_FragColor";
17289 glTransformFeedbackVaryings(program, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17290 glBindAttribLocation(program, 8, essl1_shaders::PositionAttrib());
17291 glLinkProgram(program);
17292 GLint linkStatus = 999;
17293 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
17294 ASSERT_GL_NO_ERROR();
17295 // Link expected to fail on the first program
17296 ASSERT_EQ(linkStatus, GL_FALSE);
17297
17298 // Another program with the same shaders but without the varying is expected to link
17299 ANGLE_GL_PROGRAM(anotherProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17300 ASSERT_NE(program, anotherProgram);
17301 glUseProgram(anotherProgram);
17302 glLinkProgram(anotherProgram);
17303 ASSERT_GL_NO_ERROR();
17304 ASSERT_NE(CheckLinkStatusAndReturnProgram(anotherProgram, true), 0u);
17305 }
17306
17307 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)17308 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
17309 {
17310 // Make a simple program.
17311 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17312
17313 // Install the executable.
17314 glUseProgram(testProgram);
17315
17316 // Re-link with a bad XFB varying and a bound attrib location.
17317 const char *tfVaryings = "gl_FragColor";
17318 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17319 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
17320 glLinkProgram(testProgram);
17321 GLint linkStatus = 999;
17322 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
17323 ASSERT_GL_NO_ERROR();
17324 ASSERT_EQ(linkStatus, GL_FALSE);
17325
17326 // Under WebGL this is an error.
17327 glDrawArrays(GL_TRIANGLES, 79, 16);
17328 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
17329 }
17330
17331 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)17332 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
17333 {
17334 constexpr char kFS[] = R"(#version 300 es
17335 precision mediump float;
17336 vec3 a = vec3(0.0);
17337 out vec4 color;
17338 void main()
17339 {
17340 cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
17341 })";
17342
17343 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17344 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17345 ASSERT_GL_NO_ERROR();
17346 }
17347
17348 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)17349 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
17350 {
17351 constexpr char kFS[] = R"(#version 300 es
17352 struct S {
17353 int foo;
17354 };
17355 void main() {
17356 S a[3];
17357 a = S[3](S(0), S(1), S(2));
17358 })";
17359
17360 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17361
17362 const char *sourceArray[1] = {kFS};
17363 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17364 glShaderSource(shader, 1, sourceArray, lengths);
17365 glCompileShader(shader);
17366
17367 GLint compileResult;
17368 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17369 EXPECT_NE(compileResult, 0);
17370 }
17371
17372 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)17373 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
17374 {
17375 constexpr char kFS[] = R"(#version 300 es
17376
17377 precision mediump float;
17378
17379 layout(location=0) out vec4 color;
17380
17381 uniform float f;
17382
17383 void main()
17384 {
17385 mat3x2 m = f + mat3x2(0);
17386 color = vec4(m[0][0]);
17387 })";
17388
17389 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17390
17391 const char *sourceArray[1] = {kFS};
17392 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17393 glShaderSource(shader, 1, sourceArray, lengths);
17394 glCompileShader(shader);
17395
17396 GLint compileResult;
17397 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17398 EXPECT_NE(compileResult, 0);
17399 }
17400
17401 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
17402 // folding it into a TIntermConstantUnion. This transformation is clamping non-constant indices in
17403 // WebGL. The |false ? i : 5| as index caused the transformation to consider this a non-constant
17404 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)17405 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
17406 {
17407 constexpr char kFS[] = R"(#version 300 es
17408 precision highp float;
17409
17410 layout(location=0) out float f;
17411
17412 uniform int i;
17413
17414 void main()
17415 {
17416 float data[10];
17417 f = data[false ? i : 5];
17418 })";
17419
17420 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17421
17422 const char *sourceArray[1] = {kFS};
17423 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17424 glShaderSource(shader, 1, sourceArray, lengths);
17425 glCompileShader(shader);
17426
17427 GLint compileResult;
17428 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17429 EXPECT_NE(compileResult, 0);
17430 }
17431
17432 // Test robustness of out-of-bounds lod in texelFetch
TEST_P(WebGL2GLSLTest,TexelFetchLodOutOfBounds)17433 TEST_P(WebGL2GLSLTest, TexelFetchLodOutOfBounds)
17434 {
17435 constexpr char kVS[] = R"(#version 300 es
17436 in vec4 vertexPosition;
17437 void main() {
17438 gl_Position = vertexPosition;
17439 })";
17440
17441 constexpr char kFS[] = R"(#version 300 es
17442 precision highp float;
17443 uniform highp sampler2DArray textureArray;
17444 uniform int textureLod;
17445 out vec4 fragColor;
17446 void main() {
17447 fragColor = texelFetch(textureArray, ivec3(gl_FragCoord.xy, 0), textureLod);
17448 })";
17449
17450 ANGLE_GL_PROGRAM(program, kVS, kFS);
17451 glUseProgram(program);
17452 const GLint lodLoc = glGetUniformLocation(program, "textureLod");
17453 EXPECT_NE(lodLoc, -1);
17454 const GLint textureLoc = glGetUniformLocation(program, "textureArray");
17455 EXPECT_NE(textureLoc, -1);
17456
17457 const GLint attribLocation = glGetAttribLocation(program, "vertexPosition");
17458 GLBuffer buffer;
17459 glBindBuffer(GL_ARRAY_BUFFER, buffer);
17460 constexpr float vertices[12] = {
17461 -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
17462 };
17463 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
17464 glEnableVertexAttribArray(attribLocation);
17465 glVertexAttribPointer(attribLocation, 2, GL_FLOAT, false, 0, 0);
17466
17467 GLTexture texture;
17468 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
17469 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
17470 glUniform1i(textureLoc, 0);
17471
17472 // Test LOD too large
17473 glUniform1i(lodLoc, 0x7FFF);
17474 glDrawArrays(GL_TRIANGLES, 0, 6);
17475
17476 // Test LOD negative
17477 glUniform1i(lodLoc, -1);
17478 glDrawArrays(GL_TRIANGLES, 0, 6);
17479 }
17480
17481 // Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without
17482 // failing validation (adapted from a Chromium test, see anglebug.com/42265427)
TEST_P(GLSLTest,FramebufferFetchWithLastFragData)17483 TEST_P(GLSLTest, FramebufferFetchWithLastFragData)
17484 {
17485 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
17486
17487 constexpr char kFS[] = R"(#version 100
17488
17489 #extension GL_EXT_shader_framebuffer_fetch : require
17490 varying mediump vec4 color;
17491 void main() {
17492 gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0];
17493 })";
17494
17495 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17496
17497 const char *sourceArray[1] = {kFS};
17498 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17499 glShaderSource(shader, 1, sourceArray, lengths);
17500 glCompileShader(shader);
17501
17502 GLint compileResult;
17503 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17504 EXPECT_NE(compileResult, 0);
17505 }
17506
17507 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch1)17508 TEST_P(GLSLTest, LoopBodyEndingInBranch1)
17509 {
17510 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})";
17511
17512 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17513
17514 const char *sourceArray[1] = {kFS};
17515 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17516 glShaderSource(shader, 1, sourceArray, lengths);
17517 glCompileShader(shader);
17518
17519 GLint compileResult;
17520 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17521 EXPECT_NE(compileResult, 0);
17522 }
17523
17524 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch2)17525 TEST_P(GLSLTest, LoopBodyEndingInBranch2)
17526 {
17527 constexpr char kFS[] =
17528 R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})";
17529
17530 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17531
17532 const char *sourceArray[1] = {kFS};
17533 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17534 glShaderSource(shader, 1, sourceArray, lengths);
17535 glCompileShader(shader);
17536
17537 GLint compileResult;
17538 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17539 EXPECT_NE(compileResult, 0);
17540 }
17541
17542 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch3)17543 TEST_P(GLSLTest, LoopBodyEndingInBranch3)
17544 {
17545 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})";
17546
17547 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17548
17549 const char *sourceArray[1] = {kFS};
17550 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17551 glShaderSource(shader, 1, sourceArray, lengths);
17552 glCompileShader(shader);
17553
17554 GLint compileResult;
17555 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17556 EXPECT_NE(compileResult, 0);
17557 }
17558
17559 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch4)17560 TEST_P(GLSLTest, LoopBodyEndingInBranch4)
17561 {
17562 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})";
17563
17564 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17565
17566 const char *sourceArray[1] = {kFS};
17567 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17568 glShaderSource(shader, 1, sourceArray, lengths);
17569 glCompileShader(shader);
17570
17571 GLint compileResult;
17572 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17573 EXPECT_NE(compileResult, 0);
17574 }
17575
17576 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch5)17577 TEST_P(GLSLTest, LoopBodyEndingInBranch5)
17578 {
17579 constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})";
17580
17581 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17582
17583 const char *sourceArray[1] = {kFS};
17584 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17585 glShaderSource(shader, 1, sourceArray, lengths);
17586 glCompileShader(shader);
17587
17588 GLint compileResult;
17589 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17590 EXPECT_NE(compileResult, 0);
17591 }
17592
17593 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch6)17594 TEST_P(GLSLTest, LoopBodyEndingInBranch6)
17595 {
17596 constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})";
17597
17598 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17599
17600 const char *sourceArray[1] = {kFS};
17601 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17602 glShaderSource(shader, 1, sourceArray, lengths);
17603 glCompileShader(shader);
17604
17605 GLint compileResult;
17606 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17607 EXPECT_NE(compileResult, 0);
17608 }
17609
17610 // Test that aliasing function out parameters work. The GLSL spec says:
17611 //
17612 // > Because the function works with local copies of parameters, there are no issues regarding
17613 // > aliasing of variables within a function.
17614 //
17615 // In the test below, while the value of x is unknown after the function call, the result of the
17616 // function must deterministically be true.
TEST_P(GLSLTest,AliasingFunctionOutParams)17617 TEST_P(GLSLTest, AliasingFunctionOutParams)
17618 {
17619 constexpr char kFS[] = R"(precision highp float;
17620
17621 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17622 const vec4 colorRed = vec4(1.,0.,0.,1.);
17623
17624 bool outParametersAreDistinct(out float x, out float y) {
17625 x = 1.0;
17626 y = 2.0;
17627 return x == 1.0 && y == 2.0;
17628 }
17629 void main() {
17630 float x = 0.0;
17631 gl_FragColor = outParametersAreDistinct(x, x) ? colorGreen : colorRed;
17632 }
17633 )";
17634
17635 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17636 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17638 ASSERT_GL_NO_ERROR();
17639 }
17640
17641 // Test that aliasing function out parameters work even when multiple params are aliased.
TEST_P(GLSLTest,AliasingFunctionOutParamsMultiple)17642 TEST_P(GLSLTest, AliasingFunctionOutParamsMultiple)
17643 {
17644 constexpr char kFS[] = R"(precision highp float;
17645
17646 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17647 const vec4 colorRed = vec4(1.,0.,0.,1.);
17648
17649 bool outParametersAreDistinct(out float x, out float y, out float z, out float a) {
17650 x = 1.0;
17651 y = 2.0;
17652 z = 3.0;
17653 a = 4.0;
17654 return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17655 }
17656 void main() {
17657 float x = 0.0;
17658 float y = 0.0;
17659 gl_FragColor = outParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17660 }
17661 )";
17662
17663 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17664 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17665 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17666 ASSERT_GL_NO_ERROR();
17667 }
17668
17669 // Test that aliasing function inout parameters work.
TEST_P(GLSLTest,AliasingFunctionInOutParams)17670 TEST_P(GLSLTest, AliasingFunctionInOutParams)
17671 {
17672 constexpr char kFS[] = R"(precision highp float;
17673
17674 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17675 const vec4 colorRed = vec4(1.,0.,0.,1.);
17676
17677 bool inoutParametersAreDistinct(inout float x, inout float y) {
17678 x = 1.0;
17679 y = 2.0;
17680 return x == 1.0 && y == 2.0;
17681 }
17682 void main() {
17683 float x = 0.0;
17684 gl_FragColor = inoutParametersAreDistinct(x, x) ? colorGreen : colorRed;
17685 }
17686 )";
17687
17688 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17689 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17690 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17691 ASSERT_GL_NO_ERROR();
17692 }
17693
17694 // Test coverage of some matrix/scalar ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixScalarOps)17695 TEST_P(GLSLTest, MatrixScalarOps)
17696 {
17697 constexpr char kFS[] = R"(precision highp float;
17698 void main() {
17699 float scalar = 0.5;
17700 mat3 matrix = mat3(vec3(0.1), vec3(0.1), vec3(0.1));
17701
17702 mat3 m0 = scalar / matrix;
17703 mat3 m1 = scalar * matrix;
17704 mat3 m2 = scalar + matrix;
17705 mat3 m3 = scalar - matrix;
17706
17707 gl_FragColor = vec4(m0[0][0], m1[0][0], m2[0][0], m3[0][0]);
17708 }
17709 )";
17710
17711 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17712 ASSERT_GL_NO_ERROR();
17713
17714 drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17715 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 13, 153, 102), 1.0);
17716 ASSERT_GL_NO_ERROR();
17717 }
17718
17719 // Test coverage of some matrix ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixNegate)17720 TEST_P(GLSLTest, MatrixNegate)
17721 {
17722 constexpr char kFS[] = R"(precision highp float;
17723 void main() {
17724 mat3 matrix = mat3(vec3(-0.1), vec3(-0.1), vec3(-0.1));
17725
17726 mat3 m0 = -matrix;
17727
17728 gl_FragColor = vec4(m0[0][0], 0, 0, 1);
17729 }
17730 )";
17731
17732 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17733 ASSERT_GL_NO_ERROR();
17734
17735 drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17736 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(26, 0, 0, 255), 1.0);
17737 ASSERT_GL_NO_ERROR();
17738 }
17739
17740 // Test coverage of the mix(float, float, bool) overload which was missing in Metal translation
TEST_P(GLSLTest_ES3,MixFloatFloatBool)17741 TEST_P(GLSLTest_ES3, MixFloatFloatBool)
17742 {
17743 constexpr char kFS[] = R"(#version 300 es
17744 precision highp float;
17745 out vec4 fragColor;
17746 void main() {
17747 vec4 testData = vec4(0.0, 1.0, 0.5, 0.25);
17748 float scalar = mix(testData.x, testData.y, testData.x < 0.5);
17749 vec2 vector = mix(testData.xy, testData.xw, bvec2(testData.x < 0.5, testData.y < 0.5));
17750 fragColor = vec4(scalar, vector.x, vector.y, 1);
17751 }
17752 )";
17753
17754 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17755 ASSERT_GL_NO_ERROR();
17756
17757 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17758 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 255, 255));
17759 ASSERT_GL_NO_ERROR();
17760 }
17761
17762 // Test coverage of the mix(uint, uint, bool) overload which was missing in D3D11 translation
TEST_P(GLSLTest_ES31,MixUintUintBool)17763 TEST_P(GLSLTest_ES31, MixUintUintBool)
17764 {
17765 constexpr char kFS[] = R"(#version 310 es
17766 precision highp float;
17767 out vec4 fragColor;
17768 void main() {
17769 uvec4 testData1 = uvec4(0, 1, 2, 3);
17770 uvec4 testData2 = uvec4(4, 5, 6, 7);
17771 uint scalar = mix(testData1.x, testData2.x, true);
17772 uvec4 vector = mix(testData1, testData2, bvec4(false, true, true, false));
17773 fragColor = vec4(scalar == 4u ? 1.0 : 0.0, vector == uvec4(0, 5, 6, 3) ? 1.0 : 0.0, 0.0, 1.0);
17774 }
17775 )";
17776
17777 ANGLE_GL_PROGRAM(testProgram, essl31_shaders::vs::Simple(), kFS);
17778 ASSERT_GL_NO_ERROR();
17779
17780 drawQuad(testProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17781 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255));
17782 ASSERT_GL_NO_ERROR();
17783 }
17784
17785 // Test coverage of the mix(int, int, bool) overload which was missing in D3D11 translation
TEST_P(GLSLTest_ES31,MixIntIntBool)17786 TEST_P(GLSLTest_ES31, MixIntIntBool)
17787 {
17788 constexpr char kFS[] = R"(#version 310 es
17789 precision highp float;
17790 out vec4 fragColor;
17791 void main() {
17792 ivec4 testData1 = ivec4(-4, -3, -2, -1);
17793 ivec4 testData2 = ivec4(4, 5, 6, 7);
17794 int scalar = mix(testData1.x, testData2.x, true);
17795 ivec4 vector = mix(testData1, testData2, bvec4(false, true, true, false));
17796 fragColor = vec4(scalar == 4 ? 1.0 : 0.0, vector == ivec4(-4, 5, 6, -1) ? 1.0 : 0.0, 0.0, 1.0);
17797 }
17798 )";
17799
17800 ANGLE_GL_PROGRAM(testProgram, essl31_shaders::vs::Simple(), kFS);
17801 ASSERT_GL_NO_ERROR();
17802
17803 drawQuad(testProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17804 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255));
17805 ASSERT_GL_NO_ERROR();
17806 }
17807
17808 // Test that aliasing function inout parameters work when more than one param is aliased.
TEST_P(GLSLTest,AliasingFunctionInOutParamsMultiple)17809 TEST_P(GLSLTest, AliasingFunctionInOutParamsMultiple)
17810 {
17811 constexpr char kFS[] = R"(precision highp float;
17812
17813 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17814 const vec4 colorRed = vec4(1.,0.,0.,1.);
17815
17816 bool inoutParametersAreDistinct(inout float x, inout float y, inout float z, inout float a) {
17817 x = 1.0;
17818 y = 2.0;
17819 z = 3.0;
17820 a = 4.0;
17821 return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17822 }
17823 void main() {
17824 float x = 0.0;
17825 float y = 0.0;
17826 gl_FragColor = inoutParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17827 }
17828 )";
17829
17830 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17831 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17832 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17833 ASSERT_GL_NO_ERROR();
17834 }
17835
17836 // Test that aliasing function out parameter with a global works.
TEST_P(GLSLTest,AliasingFunctionOutParamAndGlobal)17837 TEST_P(GLSLTest, AliasingFunctionOutParamAndGlobal)
17838 {
17839 constexpr char kFS[] = R"(precision highp float;
17840
17841 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17842 const vec4 colorRed = vec4(1.,0.,0.,1.);
17843
17844 float x = 1.0;
17845 bool outParametersAreDistinctFromGlobal(out float y) {
17846 y = 2.0;
17847 return x == 1.0 && y == 2.0;
17848 }
17849 void main() {
17850 gl_FragColor = outParametersAreDistinctFromGlobal(x) ? colorGreen : colorRed;
17851 }
17852 )";
17853
17854 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17855 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17856 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17857 ASSERT_GL_NO_ERROR();
17858 }
17859
17860 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstSamplerParameter)17861 TEST_P(GLSLTest, ConstSamplerParameter)
17862 {
17863 constexpr char kFS[] = R"(precision mediump float;
17864 uniform sampler2D samp;
17865
17866 vec4 sampleConstSampler(const sampler2D s) {
17867 return texture2D(s, vec2(0));
17868 }
17869
17870 void main() {
17871 gl_FragColor = sampleConstSampler(samp);
17872 }
17873 )";
17874 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17875 glUseProgram(program);
17876 GLTexture texture;
17877 GLColor expected = MakeGLColor(32, 64, 96, 255);
17878 glBindTexture(GL_TEXTURE_2D, texture);
17879 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17880 GLint u = glGetUniformLocation(program, "samp");
17881 EXPECT_NE(u, -1);
17882 glUniform1i(u, 0);
17883 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17884 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17885 ASSERT_GL_NO_ERROR();
17886 }
17887
17888 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstInSamplerParameter)17889 TEST_P(GLSLTest, ConstInSamplerParameter)
17890 {
17891 constexpr char kFS[] = R"(precision mediump float;
17892 uniform sampler2D u;
17893 vec4 sampleConstSampler(const in sampler2D s) {
17894 return texture2D(s, vec2(0));
17895 }
17896 void main() {
17897 gl_FragColor = sampleConstSampler(u);
17898 }
17899 )";
17900 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17901 glUseProgram(program);
17902 GLTexture texture;
17903 GLColor expected = MakeGLColor(32, 64, 96, 255);
17904 glBindTexture(GL_TEXTURE_2D, texture);
17905 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17906 GLint u = glGetUniformLocation(program, "u");
17907 EXPECT_NE(u, -1);
17908 glUniform1i(u, 0);
17909 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17910 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17911 ASSERT_GL_NO_ERROR();
17912 }
17913
17914 // Make sure passing const sampler parameters to another function work.
TEST_P(GLSLTest,ConstSamplerParameterAsArgument)17915 TEST_P(GLSLTest, ConstSamplerParameterAsArgument)
17916 {
17917 constexpr char kFS[] = R"(precision mediump float;
17918
17919 uniform sampler2D samp;
17920
17921 vec4 sampleSampler(sampler2D s) {
17922 return texture2D(s, vec2(0));
17923 }
17924
17925 vec4 sampleConstSampler(const sampler2D s) {
17926 return sampleSampler(s);
17927 }
17928
17929 void main() {
17930 gl_FragColor = sampleConstSampler(samp);
17931 }
17932 )";
17933 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17934 glUseProgram(program);
17935 GLTexture texture;
17936 GLColor expected = MakeGLColor(32, 64, 96, 255);
17937 glBindTexture(GL_TEXTURE_2D, texture);
17938 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17939 GLint u = glGetUniformLocation(program, "samp");
17940 EXPECT_NE(u, -1);
17941 glUniform1i(u, 0);
17942 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17943 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17944 ASSERT_GL_NO_ERROR();
17945 }
17946
17947 // Test for a driver bug with matrix multiplication in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixMultiplicationBug)17948 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixMultiplicationBug)
17949 {
17950 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17951
17952 constexpr char kTCS[] = R"(#version 310 es
17953 #extension GL_EXT_tessellation_shader : enable
17954 layout(vertices = 1) out;
17955 precision highp float;
17956
17957 patch out mat4 x;
17958
17959 void main()
17960 {
17961 x = mat4(
17962 0.53455, 0.47307, 0.34935, 0.28717,
17963 0.67195, 0.59992, 0.48213, 0.43678,
17964 0.76376, 0.6772, 0.55361, 0.5165,
17965 0.77996, 0.68862, 0.56187, 0.52611
17966 );
17967
17968 const mat4 m = mat4(
17969 vec4( -1.0, 3.0,-3.0, 1.0),
17970 vec4( 3.0,-6.0, 3.0, 0.0),
17971 vec4( -3.0, 3.0, 0.0, 0.0),
17972 vec4( 1.0, 0.0, 0.0, 0.0)
17973 );
17974
17975 x = m * x;
17976
17977 gl_TessLevelInner[0u] = 1.;
17978 gl_TessLevelInner[1u] = 1.;
17979 gl_TessLevelOuter[0u] = 1.;
17980 gl_TessLevelOuter[1u] = 1.;
17981 gl_TessLevelOuter[2u] = 1.;
17982 gl_TessLevelOuter[3u] = 1.;
17983 })";
17984
17985 constexpr char kTES[] = R"(#version 310 es
17986 #extension GL_EXT_tessellation_shader : enable
17987 layout(quads, cw, fractional_odd_spacing) in;
17988 precision highp float;
17989
17990 patch in mat4 x;
17991
17992 out mat4 x_fs;
17993
17994 void main()
17995 {
17996 x_fs = x;
17997 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17998 })";
17999
18000 constexpr char kFS[] = R"(#version 310 es
18001 precision highp float;
18002
18003 in mat4 x_fs;
18004 out vec4 color;
18005
18006 void main()
18007 {
18008 // Note: on the failing driver, .w of every column has the same value as .x of the same column.
18009
18010 const mat4 expect = mat4(
18011 0.12378, -0.18672, -0.18444, 0.53455,
18012 0.1182, -0.13728, -0.21609, 0.67195,
18013 0.12351, -0.11109, -0.25968, 0.76376,
18014 0.1264, -0.10623, -0.27402, 0.77996
18015 );
18016
18017 color = vec4(all(lessThan(abs(x_fs[0] - expect[0]), vec4(0.01))),
18018 all(lessThan(abs(x_fs[1] - expect[1]), vec4(0.01))),
18019 all(lessThan(abs(x_fs[2] - expect[2]), vec4(0.01))),
18020 all(lessThan(abs(x_fs[3] - expect[3]), vec4(0.01))));
18021 })";
18022
18023 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18024 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18025 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
18026 ASSERT_GL_NO_ERROR();
18027 }
18028
18029 // Test for a driver bug with matrix copy in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixCopyBug)18030 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixCopyBug)
18031 {
18032 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18033
18034 constexpr char kTCS[] = R"(#version 310 es
18035 #extension GL_EXT_tessellation_shader : enable
18036 layout(vertices = 1) out;
18037 precision highp float;
18038
18039 patch out mat4 x;
18040 patch out vec4 col0;
18041
18042 void main()
18043 {
18044 // Note: if |x| is not an |out| varying, the test passes.
18045 x = mat4(
18046 0.53455, 0.47307, 0.34935, 0.28717,
18047 0.67195, 0.59992, 0.48213, 0.43678,
18048 0.76376, 0.6772, 0.55361, 0.5165,
18049 0.77996, 0.68862, 0.56187, 0.52611
18050 );
18051
18052 const mat4 m = mat4(
18053 vec4( -1.0, 3.0,-3.0, 1.0),
18054 vec4( 3.0,-6.0, 3.0, 0.0),
18055 vec4( -3.0, 3.0, 0.0, 0.0),
18056 vec4( 1.0, 0.0, 0.0, 0.0)
18057 );
18058
18059 mat4 temp = x;
18060
18061 // Note: On the failing driver, commenting this line makes the test pass.
18062 // However, the output being tested is |temp|, assigned above, not |x|.
18063 x = m * x;
18064
18065 col0 = temp[0];
18066
18067 gl_TessLevelInner[0u] = 1.;
18068 gl_TessLevelInner[1u] = 1.;
18069 gl_TessLevelOuter[0u] = 1.;
18070 gl_TessLevelOuter[1u] = 1.;
18071 gl_TessLevelOuter[2u] = 1.;
18072 gl_TessLevelOuter[3u] = 1.;
18073 })";
18074
18075 constexpr char kTES[] = R"(#version 310 es
18076 #extension GL_EXT_tessellation_shader : enable
18077 layout(quads, cw, fractional_odd_spacing) in;
18078 precision highp float;
18079
18080 patch in vec4 col0;
18081
18082 out vec4 col0_fs;
18083
18084 void main()
18085 {
18086 col0_fs = col0;
18087 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18088 })";
18089
18090 constexpr char kFS[] = R"(#version 310 es
18091 precision highp float;
18092
18093 in vec4 col0_fs;
18094 out vec4 color;
18095
18096 void main()
18097 {
18098 // Note: on the failing driver, |col0| has the value of |m * x|, not |temp|.
18099 color = vec4(abs(col0_fs.x - 0.53455) < 0.01,
18100 abs(col0_fs.y - 0.47307) < 0.01,
18101 abs(col0_fs.z - 0.34935) < 0.01,
18102 abs(col0_fs.w - 0.28717) < 0.01);
18103 })";
18104
18105 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18106 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18107 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
18108 ASSERT_GL_NO_ERROR();
18109 }
18110
18111 // Tests the generation of HLSL functions with uint/int parameters that may be ambiguous.
TEST_P(GLSLTest_ES3,AmbiguousHLSLIntegerFunctionParameters)18112 TEST_P(GLSLTest_ES3, AmbiguousHLSLIntegerFunctionParameters)
18113 {
18114 const char kVS[] = R"(#version 300 es
18115 precision highp float;
18116 void main()
18117 {
18118 gl_Position = vec4(0, 0, 0, 0);
18119 })";
18120
18121 const char kFS[] = R"(#version 300 es
18122 precision highp float;
18123 out vec4 color;
18124 void main()
18125 {
18126 // Ensure that both uint and int to float constructors are generated before the ambiguous usage.
18127 int i = int(gl_FragCoord.x);
18128 float f1 = float(i);
18129 color.r = f1;
18130
18131 uint ui = uint(gl_FragCoord.x);
18132 float f2 = float(i);
18133 color.g = f2;
18134
18135 // Ambiguous call
18136 float f3 = float(1u << (2u * ui));
18137 color.b = f3;
18138 })";
18139
18140 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18141 }
18142
18143 // Tests adding a struct definition inline in a shader.
18144 // Metal backend contains a pass that separates struct definition and declaration.
TEST_P(GLSLTest_ES3,StructInShader)18145 TEST_P(GLSLTest_ES3, StructInShader)
18146 {
18147 const char kVS[] = R"(#version 300 es
18148 precision highp float;
18149 void main(void)
18150 {
18151 struct structMain {
18152 float i;
18153 } testStruct;
18154
18155 testStruct.i = 5.0 ;
18156 gl_Position = vec4(testStruct.i - 4.0, 0, 0, 1);
18157 })";
18158
18159 const char kFS[] = R"(#version 300 es
18160 precision highp float;
18161 out vec4 color;
18162 void main()
18163 {
18164 color = vec4(0,1,0,0);
18165 })";
18166
18167 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18168 }
18169
18170 // Issue: A while loop's expression, and a branch
18171 // condition with EOpContinue were being deep
18172 // copied as part of monomorphize functions,
18173 // causing a crash, as they were not null-checked.
18174 // Tests transforming a function that will be monomorphized.
TEST_P(GLSLTest_ES3,MonomorphizeForAndContinue)18175 TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue)
18176 {
18177
18178 constexpr char kFS[] =
18179 R"(#version 300 es
18180
18181 precision mediump float;
18182 out vec4 fragOut;
18183 struct aParam
18184 {
18185 sampler2D sampler;
18186 };
18187 uniform aParam theParam;
18188
18189 float monomorphizedFunction(aParam a)
18190 {
18191 int i = 0;
18192 vec4 j = vec4(0);
18193 for(;;)
18194 {
18195 if(i++ < 10)
18196 {
18197 j += texture(a.sampler, vec2(0.0f,0.0f));
18198 continue;
18199 }
18200 break;
18201 }
18202 return j.a;
18203 }
18204 void main()
18205 {
18206 fragOut.a = monomorphizedFunction(theParam);
18207 }
18208 )";
18209 CompileShader(GL_FRAGMENT_SHADER, kFS);
18210 ASSERT_GL_NO_ERROR();
18211 }
18212
18213 // Tests inout parameters with array references.
TEST_P(GLSLTest_ES3,InoutWithArrayRefs)18214 TEST_P(GLSLTest_ES3, InoutWithArrayRefs)
18215 {
18216 const char kVS[] = R"(#version 300 es
18217 precision highp float;
18218 void swap(inout float a, inout float b)
18219 {
18220 float tmp = a;
18221 a = b;
18222 b = tmp;
18223 }
18224
18225 void main(void)
18226 {
18227 vec3 testVec = vec3(0.0, 1.0, 1.0);
18228 swap(testVec[0], testVec[1]);
18229 gl_Position = vec4(testVec[0], testVec[1], testVec[2], 1.0);
18230 })";
18231
18232 const char kFS[] = R"(#version 300 es
18233 precision highp float;
18234 out vec4 color;
18235 void main()
18236 {
18237 color = vec4(0,1,0,0);
18238 })";
18239
18240 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18241 }
18242
18243 // Test that sample variables compile.
TEST_P(GLSLTest_ES3,SampleVariables)18244 TEST_P(GLSLTest_ES3, SampleVariables)
18245 {
18246 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
18247
18248 const char kFS[] = R"(#version 300 es
18249 #extension GL_OES_sample_variables : require
18250 precision highp float;
18251 out vec4 color;
18252 void main()
18253 {
18254 gl_SampleMask[0] = gl_SampleMaskIn[0] & 0x55555555;
18255 color = vec4(gl_SamplePosition.yx, float(gl_SampleID), float(gl_MaxSamples + gl_NumSamples));
18256 })";
18257
18258 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
18259 }
18260
18261 // Test that shader caching maintains uniforms across compute shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniform)18262 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniform)
18263 {
18264 ANGLE_SKIP_TEST_IF(!IsVulkan());
18265 constexpr char kCS[] = R"(#version 310 es
18266 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
18267
18268 uniform uint inputs[6];
18269
18270 layout (binding = 0, std430) buffer OutputBuffer {
18271 uint outputs[6];
18272 };
18273
18274 void main() {
18275 outputs[gl_LocalInvocationIndex] = inputs[gl_LocalInvocationIndex];
18276 }
18277 )";
18278
18279 ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
18280 ASSERT_GL_NO_ERROR();
18281 // Delete the shader and recompile to fetch from cache.
18282 glDeleteProgram(unusedProgram);
18283 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
18284 ASSERT_GL_NO_ERROR();
18285 glUseProgram(program);
18286
18287 constexpr std::array<GLuint, 6> kInputUniform = {1, 2, 3, 4, 5, 6};
18288 for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
18289 {
18290 const std::string uniformName =
18291 std::string("inputs[") + std::to_string(i) + std::string("]");
18292 int inputLocation =
18293 glGetUniformLocation(program, static_cast<const GLchar *>(uniformName.c_str()));
18294 glUniform1ui(inputLocation, kInputUniform[i]);
18295 ASSERT_GL_NO_ERROR();
18296 }
18297
18298 constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
18299 GLBuffer outputBuffer;
18300 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
18301 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
18302 kOutputInitData.data(), GL_STATIC_READ);
18303 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
18304
18305 glDispatchCompute(1, 1, 1);
18306 glDeleteProgram(program);
18307 ASSERT_GL_NO_ERROR();
18308 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
18309
18310 auto outputData = static_cast<const GLuint *>(glMapBufferRange(
18311 GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
18312 for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
18313 {
18314 EXPECT_EQ(kInputUniform[i], outputData[i]);
18315 }
18316 }
18317
18318 // Test that shader caching maintains uniform blocks across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniformBlocks)18319 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniformBlocks)
18320 {
18321 ANGLE_SKIP_TEST_IF(!IsVulkan());
18322 constexpr char kCS[] = R"(#version 310 es
18323 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
18324
18325 layout (std140) uniform Input1 {
18326 uint input1;
18327 };
18328
18329 layout (std140) uniform Input2 {
18330 uint input2;
18331 };
18332
18333 layout (binding = 0, std430) buffer OutputBuffer {
18334 uint outputs[6];
18335 };
18336
18337 void main() {
18338 if (gl_LocalInvocationIndex < uint(3))
18339 {
18340 outputs[gl_LocalInvocationIndex] = input1;
18341 }
18342 else
18343 {
18344 outputs[gl_LocalInvocationIndex] = input2;
18345 }
18346 }
18347 )";
18348
18349 ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
18350 ASSERT_GL_NO_ERROR();
18351 // Delete the shader and recompile to fetch from cache.
18352 glDeleteProgram(unusedProgram);
18353 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
18354 ASSERT_GL_NO_ERROR();
18355 glUseProgram(program);
18356
18357 constexpr GLuint kInput1Data = 1;
18358 GLBuffer input1;
18359 glBindBuffer(GL_UNIFORM_BUFFER, input1);
18360 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput1Data, GL_STATIC_COPY);
18361 const GLuint kInput1Index = glGetUniformBlockIndex(program, "Input1");
18362 glUniformBlockBinding(program, kInput1Index, 1);
18363 glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
18364 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18365 ASSERT_GL_NO_ERROR();
18366
18367 constexpr GLuint kInput2Data = 2;
18368 GLBuffer input2;
18369 glBindBuffer(GL_UNIFORM_BUFFER, input2);
18370 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput2Data, GL_STATIC_COPY);
18371 const GLuint kInput2Index = glGetUniformBlockIndex(program, "Input2");
18372 glUniformBlockBinding(program, kInput2Index, 2);
18373 glBindBufferBase(GL_UNIFORM_BUFFER, 2, input2);
18374 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18375 ASSERT_GL_NO_ERROR();
18376
18377 constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
18378 GLBuffer outputBuffer;
18379 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
18380 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
18381 kOutputInitData.data(), GL_STATIC_READ);
18382 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
18383 ASSERT_GL_NO_ERROR();
18384
18385 glDispatchCompute(1, 1, 1);
18386 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
18387 glDeleteProgram(program);
18388 ASSERT_GL_NO_ERROR();
18389
18390 auto outputData = static_cast<const GLuint *>(glMapBufferRange(
18391 GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
18392 constexpr std::array<GLuint, 6> kWant = {kInput1Data, kInput1Data, kInput1Data,
18393 kInput2Data, kInput2Data, kInput2Data};
18394 for (int i = 0; i < static_cast<int>(kWant.size()); ++i)
18395 {
18396 EXPECT_EQ(kWant[i], outputData[i]);
18397 }
18398 }
18399
18400 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniform)18401 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniform)
18402 {
18403 ANGLE_SKIP_TEST_IF(!IsVulkan());
18404 constexpr char kVS[] = R"(#version 310 es
18405
18406 precision mediump float;
18407
18408 layout (location = 0) in vec4 a_position;
18409
18410 uniform float redInput;
18411
18412 out float redValue;
18413
18414 void main() {
18415 gl_Position = a_position;
18416 redValue = redInput;
18417 })";
18418
18419 constexpr char kFS[] = R"(#version 310 es
18420
18421 precision mediump float;
18422
18423 in float redValue;
18424
18425 out vec4 fragColor;
18426
18427 void main()
18428 {
18429 fragColor = vec4(redValue, 0., 0., 1.);
18430 })";
18431
18432 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18433 ASSERT_GL_NO_ERROR();
18434 // Delete the shader and recompile to fetch from cache.
18435 glDeleteProgram(unusedProgram);
18436 ANGLE_GL_PROGRAM(program, kVS, kFS);
18437 ASSERT_GL_NO_ERROR();
18438 glUseProgram(program);
18439
18440 constexpr GLfloat kRedValue = 1.0f;
18441 int redInputLocation = glGetUniformLocation(program, "redInput");
18442 glUniform1f(redInputLocation, kRedValue);
18443 ASSERT_GL_NO_ERROR();
18444
18445 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18446 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18447 }
18448
18449 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniformBlock)18450 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniformBlock)
18451 {
18452 ANGLE_SKIP_TEST_IF(!IsVulkan());
18453 constexpr char kVS[] = R"(#version 310 es
18454
18455 precision mediump float;
18456
18457 layout (location = 0) in vec4 a_position;
18458
18459 layout (std140) uniform Input {
18460 float redInput;
18461 };
18462
18463 out float redValue;
18464
18465 void main() {
18466 gl_Position = a_position;
18467 redValue = redInput;
18468 })";
18469
18470 constexpr char kFS[] = R"(#version 310 es
18471
18472 precision mediump float;
18473
18474 in float redValue;
18475
18476 out vec4 fragColor;
18477
18478 void main()
18479 {
18480 fragColor = vec4(redValue, 0., 0., 1.);
18481 })";
18482
18483 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18484 ASSERT_GL_NO_ERROR();
18485 // Delete the shader and recompile to fetch from cache.
18486 glDeleteProgram(unusedProgram);
18487 ANGLE_GL_PROGRAM(program, kVS, kFS);
18488 ASSERT_GL_NO_ERROR();
18489 glUseProgram(program);
18490
18491 constexpr GLfloat kInputData = 1.0f;
18492 GLBuffer input;
18493 glBindBuffer(GL_UNIFORM_BUFFER, input);
18494 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18495 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18496 glUniformBlockBinding(program, kInputIndex, 0);
18497 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18498 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18499 ASSERT_GL_NO_ERROR();
18500
18501 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18502 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18503 }
18504
18505 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithSSBO)18506 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithSSBO)
18507 {
18508 ANGLE_SKIP_TEST_IF(!IsVulkan());
18509
18510 // Check that GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS is at least 1.
18511 GLint maxVertexShaderStorageBlocks;
18512 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
18513 ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks == 0);
18514 constexpr char kVS[] = R"(#version 310 es
18515
18516 precision mediump float;
18517
18518 layout (location = 0) in vec4 a_position;
18519
18520 layout (binding = 0, std430) buffer Input {
18521 float redInput;
18522 };
18523
18524 out float redValue;
18525
18526 void main() {
18527 gl_Position = a_position;
18528 redValue = redInput;
18529 })";
18530
18531 constexpr char kFS[] = R"(#version 310 es
18532
18533 precision mediump float;
18534
18535 in float redValue;
18536
18537 out vec4 fragColor;
18538
18539 void main()
18540 {
18541 fragColor = vec4(redValue, 0., 0., 1.);
18542 })";
18543
18544 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18545 ASSERT_GL_NO_ERROR();
18546 // Delete the shader and recompile to fetch from cache.
18547 glDeleteProgram(unusedProgram);
18548 ANGLE_GL_PROGRAM(program, kVS, kFS);
18549 ASSERT_GL_NO_ERROR();
18550 glUseProgram(program);
18551
18552 constexpr GLfloat kInputData = 1.0f;
18553 GLBuffer input;
18554 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18555 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18556 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18557 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18558 ASSERT_GL_NO_ERROR();
18559
18560 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18561 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18562 }
18563
18564 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniform)18565 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniform)
18566 {
18567 ANGLE_SKIP_TEST_IF(!IsVulkan());
18568 constexpr char kFS[] = R"(#version 310 es
18569
18570 precision mediump float;
18571
18572 uniform float redValue;
18573
18574 out vec4 fragColor;
18575
18576 void main()
18577 {
18578 fragColor = vec4(redValue, 0., 0., 1.);
18579 })";
18580
18581 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18582 ASSERT_GL_NO_ERROR();
18583 // Delete the shader and recompile to fetch from cache.
18584 glDeleteProgram(unusedProgram);
18585 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18586 ASSERT_GL_NO_ERROR();
18587 glUseProgram(program);
18588
18589 GLfloat redValue = 1.0f;
18590 int redInputLocation = glGetUniformLocation(program, "redValue");
18591 glUniform1f(redInputLocation, redValue);
18592 ASSERT_GL_NO_ERROR();
18593
18594 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18595 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18596 }
18597
18598 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniformBlock)18599 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniformBlock)
18600 {
18601 ANGLE_SKIP_TEST_IF(!IsVulkan());
18602 constexpr char kFS[] = R"(#version 310 es
18603
18604 precision mediump float;
18605
18606 layout (std140) uniform Input {
18607 float redValue;
18608 };
18609
18610 out vec4 fragColor;
18611
18612 void main()
18613 {
18614 fragColor = vec4(redValue, 0., 0., 1.);
18615 })";
18616
18617 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18618 ASSERT_GL_NO_ERROR();
18619 // Delete the shader and recompile to fetch from cache.
18620 glDeleteProgram(unusedProgram);
18621 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18622 ASSERT_GL_NO_ERROR();
18623 glUseProgram(program);
18624
18625 constexpr GLfloat kInputData = 1.0f;
18626 GLBuffer input;
18627 glBindBuffer(GL_UNIFORM_BUFFER, input);
18628 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18629 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18630 glUniformBlockBinding(program, kInputIndex, 0);
18631 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18632 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18633 ASSERT_GL_NO_ERROR();
18634
18635 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18636 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18637 }
18638
18639 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithSSBO)18640 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithSSBO)
18641 {
18642 ANGLE_SKIP_TEST_IF(!IsVulkan());
18643 constexpr char kFS[] = R"(#version 310 es
18644
18645 precision mediump float;
18646
18647 layout (binding = 0, std430) buffer Input {
18648 float redValue;
18649 };
18650
18651 out vec4 fragColor;
18652
18653 void main()
18654 {
18655 fragColor = vec4(redValue, 0., 0., 1.);
18656 })";
18657
18658 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18659 ASSERT_GL_NO_ERROR();
18660 // Delete the shader and recompile to fetch from cache.
18661 glDeleteProgram(unusedProgram);
18662 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18663 ASSERT_GL_NO_ERROR();
18664 glUseProgram(program);
18665
18666 constexpr GLfloat kInputData = 1.0f;
18667 GLBuffer input;
18668 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18669 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18670 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18671 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18672 ASSERT_GL_NO_ERROR();
18673
18674 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18675 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18676 }
18677
18678 // Test that shader caching maintains whether GL_ARB_sample_shading is enabled across shader
18679 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithARBSampleShading)18680 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithARBSampleShading)
18681 {
18682 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARB_sample_shading"));
18683 ANGLE_SKIP_TEST_IF(!IsVulkan());
18684
18685 constexpr char kFS[] = R"(#version 310 es
18686 #extension GL_ARB_sample_shading : enable
18687
18688 precision mediump float;
18689
18690 out vec4 fragColor;
18691
18692 void main()
18693 {
18694 #ifdef GL_ARB_sample_shading
18695 fragColor = vec4(1., 0., 0., 1.);
18696 #else
18697 fragColor = vec4(0.);
18698 #endif
18699 })";
18700
18701 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18702 ASSERT_GL_NO_ERROR();
18703 // Delete the shader and recompile to fetch from cache.
18704 glDeleteProgram(unusedProgram);
18705 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18706 ASSERT_GL_NO_ERROR();
18707 glUseProgram(program);
18708
18709 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18710 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18711 }
18712
18713 // Test that shader caching maintains which advanced blending equations (provided by
18714 // GL_KHR_blend_equation_advanced) are used across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithKHRAdvancedBlendEquations)18715 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithKHRAdvancedBlendEquations)
18716 {
18717 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
18718 ANGLE_SKIP_TEST_IF(!IsVulkan());
18719
18720 constexpr char kFS[] = R"(#version 310 es
18721 #extension GL_KHR_blend_equation_advanced : require
18722
18723 layout (blend_support_multiply) out;
18724
18725 precision mediump float;
18726
18727 out vec4 fragColor;
18728
18729 void main()
18730 {
18731 fragColor = vec4(1., 0., 0., 1.);
18732 })";
18733
18734 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18735 ASSERT_GL_NO_ERROR();
18736 // Delete the shader and recompile to fetch from cache.
18737 glDeleteProgram(unusedProgram);
18738 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18739 ASSERT_GL_NO_ERROR();
18740 glUseProgram(program);
18741
18742 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18743 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18744 }
18745
18746 // Test that shader caching maintains uniforms in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniform)18747 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniform)
18748 {
18749 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18750 ANGLE_SKIP_TEST_IF(!IsVulkan());
18751
18752 constexpr char kGS[] = R"(#version 310 es
18753 #extension GL_EXT_geometry_shader : require
18754 precision mediump float;
18755
18756 layout (triangles) in;
18757 layout (triangle_strip, max_vertices = 3) out;
18758
18759 uniform float redInput;
18760
18761 out float redValue;
18762
18763 void main() {
18764 gl_Position = gl_in[0].gl_Position;
18765 redValue = redInput;
18766 EmitVertex();
18767
18768 gl_Position = gl_in[1].gl_Position;
18769 redValue = redInput;
18770 EmitVertex();
18771
18772 gl_Position = gl_in[2].gl_Position;
18773 redValue = redInput;
18774 EmitVertex();
18775
18776 EndPrimitive();
18777 }
18778 )";
18779
18780 constexpr char kFS[] = R"(#version 310 es
18781 precision mediump float;
18782
18783 out vec4 fragColor;
18784
18785 in float redValue;
18786
18787 void main()
18788 {
18789 fragColor = vec4(redValue, 0., 0., 1.);
18790 })";
18791
18792 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18793 ASSERT_GL_NO_ERROR();
18794 // Delete the shader and recompile to fetch from cache.
18795 glDeleteProgram(unusedProgram);
18796 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18797 ASSERT_GL_NO_ERROR();
18798 glUseProgram(program);
18799
18800 constexpr GLfloat kRedValue = 1.0f;
18801 int redInputLocation = glGetUniformLocation(program, "redInput");
18802 glUniform1f(redInputLocation, kRedValue);
18803 ASSERT_GL_NO_ERROR();
18804
18805 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18806 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18807 }
18808
18809 // Test that shader caching maintains uniform blocks in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniformBlock)18810 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniformBlock)
18811 {
18812 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18813 ANGLE_SKIP_TEST_IF(!IsVulkan());
18814
18815 constexpr char kGS[] = R"(#version 310 es
18816 #extension GL_EXT_geometry_shader : require
18817 precision mediump float;
18818
18819 layout (triangles) in;
18820 layout (triangle_strip, max_vertices = 3) out;
18821
18822 layout (std140) uniform Input {
18823 float redInput;
18824 };
18825
18826 out float redValue;
18827
18828 void main() {
18829 gl_Position = gl_in[0].gl_Position;
18830 redValue = redInput;
18831 EmitVertex();
18832
18833 gl_Position = gl_in[1].gl_Position;
18834 redValue = redInput;
18835 EmitVertex();
18836
18837 gl_Position = gl_in[2].gl_Position;
18838 redValue = redInput;
18839 EmitVertex();
18840
18841 EndPrimitive();
18842 }
18843 )";
18844
18845 constexpr char kFS[] = R"(#version 310 es
18846 precision mediump float;
18847
18848 out vec4 fragColor;
18849
18850 in float redValue;
18851
18852 void main()
18853 {
18854 fragColor = vec4(redValue, 0., 0., 1.);
18855 })";
18856
18857 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18858 ASSERT_GL_NO_ERROR();
18859 // Delete the shader and recompile to fetch from cache.
18860 glDeleteProgram(unusedProgram);
18861 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18862 ASSERT_GL_NO_ERROR();
18863 glUseProgram(program);
18864
18865 constexpr GLfloat kInputData = 1.0f;
18866 GLBuffer input;
18867 glBindBuffer(GL_UNIFORM_BUFFER, input);
18868 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18869 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18870 glUniformBlockBinding(program, kInputIndex, 0);
18871 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18872 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18873 ASSERT_GL_NO_ERROR();
18874
18875 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18876 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18877 }
18878
18879 // Test that shader caching maintains SSBO in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithSSBO)18880 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithSSBO)
18881 {
18882 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18883 ANGLE_SKIP_TEST_IF(!IsVulkan());
18884 GLint maxGeometryShaderStorageBlocks = 0;
18885 glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
18886 ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
18887
18888 constexpr char kGS[] = R"(#version 310 es
18889 #extension GL_EXT_geometry_shader : require
18890 precision mediump float;
18891
18892 layout (triangles) in;
18893 layout (triangle_strip, max_vertices = 3) out;
18894
18895 layout (binding = 0, std430) buffer Input {
18896 float redInput;
18897 };
18898
18899 out float redValue;
18900
18901 void main() {
18902 gl_Position = gl_in[0].gl_Position;
18903 redValue = redInput;
18904 EmitVertex();
18905
18906 gl_Position = gl_in[1].gl_Position;
18907 redValue = redInput;
18908 EmitVertex();
18909
18910 gl_Position = gl_in[2].gl_Position;
18911 redValue = redInput;
18912 EmitVertex();
18913
18914 EndPrimitive();
18915 }
18916 )";
18917
18918 constexpr char kFS[] = R"(#version 310 es
18919 precision mediump float;
18920
18921 out vec4 fragColor;
18922
18923 in float redValue;
18924
18925 void main()
18926 {
18927 fragColor = vec4(redValue, 0., 0., 1.);
18928 })";
18929
18930 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18931 ASSERT_GL_NO_ERROR();
18932 // Delete the shader and recompile to fetch from cache.
18933 glDeleteProgram(unusedProgram);
18934 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18935 ASSERT_GL_NO_ERROR();
18936 glUseProgram(program);
18937
18938 constexpr GLfloat kInputData = 1.0f;
18939 GLBuffer input;
18940 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18941 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18942 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18943 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18944 ASSERT_GL_NO_ERROR();
18945
18946 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18947 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18948 }
18949
18950 // Test that shader caching maintains the number of invocations in geometry shaders across shader
18951 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithInvocations)18952 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithInvocations)
18953 {
18954 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18955 ANGLE_SKIP_TEST_IF(!IsVulkan());
18956
18957 constexpr char kGS[] = R"(#version 310 es
18958 #extension GL_EXT_geometry_shader : require
18959 precision mediump float;
18960
18961 layout (triangles, invocations = 2) in;
18962 layout (triangle_strip, max_vertices = 3) out;
18963
18964 out float redValue;
18965
18966 void main() {
18967 float redOut = 0.;
18968 if (gl_InvocationID == 1) {
18969 redOut = 1.;
18970 }
18971
18972 gl_Position = gl_in[0].gl_Position;
18973 redValue = redOut;
18974 EmitVertex();
18975
18976 gl_Position = gl_in[1].gl_Position;
18977 redValue = redOut;
18978 EmitVertex();
18979
18980 gl_Position = gl_in[2].gl_Position;
18981 redValue = redOut;
18982 EmitVertex();
18983
18984 EndPrimitive();
18985 }
18986 )";
18987
18988 constexpr char kFS[] = R"(#version 310 es
18989 precision mediump float;
18990
18991 out vec4 fragColor;
18992
18993 in float redValue;
18994
18995 void main()
18996 {
18997 fragColor = vec4(redValue, 0., 0., 1.);
18998 })";
18999
19000 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
19001 ASSERT_GL_NO_ERROR();
19002 // Delete the shader and recompile to fetch from cache.
19003 glDeleteProgram(unusedProgram);
19004 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
19005 ASSERT_GL_NO_ERROR();
19006 glUseProgram(program);
19007
19008 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19009 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19010 }
19011
19012 // Test that shader caching maintains uniforms in tessellation control shaders across shader
19013 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniform)19014 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniform)
19015 {
19016 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19017 ANGLE_SKIP_TEST_IF(!IsVulkan());
19018
19019 constexpr char kTCS[] = R"(#version 310 es
19020 #extension GL_EXT_tessellation_shader : require
19021 precision mediump float;
19022
19023 layout (vertices = 1) out;
19024
19025 uniform float redInput;
19026
19027 patch out float redValueCS;
19028
19029 void main()
19030 {
19031 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19032 gl_TessLevelInner[0] = 1.0;
19033 gl_TessLevelInner[1] = 1.0;
19034 gl_TessLevelOuter[0] = 1.0;
19035 gl_TessLevelOuter[1] = 1.0;
19036 gl_TessLevelOuter[2] = 1.0;
19037 gl_TessLevelOuter[3] = 1.0;
19038
19039 redValueCS = redInput;
19040 }
19041
19042 )";
19043
19044 constexpr char kTES[] = R"(#version 310 es
19045 #extension GL_EXT_tessellation_shader : require
19046 precision mediump float;
19047
19048 layout (quads, cw, fractional_odd_spacing) in;
19049
19050 patch in float redValueCS;
19051
19052 out float redValue;
19053
19054 void main()
19055 {
19056 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19057
19058 redValue = redValueCS;
19059 }
19060 )";
19061
19062 constexpr char kFS[] = R"(#version 310 es
19063 precision mediump float;
19064
19065 out vec4 fragColor;
19066
19067 in float redValue;
19068
19069 void main()
19070 {
19071 fragColor = vec4(redValue, 0., 0., 1.);
19072 })";
19073
19074 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19075 ASSERT_GL_NO_ERROR();
19076 // Delete the shader and recompile to fetch from cache.
19077 glDeleteProgram(unusedProgram);
19078 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19079 ASSERT_GL_NO_ERROR();
19080 glUseProgram(program);
19081
19082 constexpr GLfloat kRedValue = 1.0f;
19083 int redInputLocation = glGetUniformLocation(program, "redInput");
19084 glUniform1f(redInputLocation, kRedValue);
19085 ASSERT_GL_NO_ERROR();
19086
19087 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19088 ASSERT_GL_NO_ERROR();
19089
19090 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19091 }
19092
19093 // Test that shader caching maintains uniform blocks in tessellation control shaders across shader
19094 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniformBlock)19095 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniformBlock)
19096 {
19097 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19098 ANGLE_SKIP_TEST_IF(!IsVulkan());
19099
19100 constexpr char kTCS[] = R"(#version 310 es
19101 #extension GL_EXT_tessellation_shader : require
19102 precision mediump float;
19103
19104 layout (vertices = 1) out;
19105
19106 layout (std140) uniform Input {
19107 float redInput;
19108 };
19109
19110 patch out float redValueCS;
19111
19112 void main()
19113 {
19114 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19115 gl_TessLevelInner[0] = 1.0;
19116 gl_TessLevelInner[1] = 1.0;
19117 gl_TessLevelOuter[0] = 1.0;
19118 gl_TessLevelOuter[1] = 1.0;
19119 gl_TessLevelOuter[2] = 1.0;
19120 gl_TessLevelOuter[3] = 1.0;
19121
19122 redValueCS = redInput;
19123 }
19124
19125 )";
19126
19127 constexpr char kTES[] = R"(#version 310 es
19128 #extension GL_EXT_tessellation_shader : require
19129 precision mediump float;
19130
19131 layout (quads, cw, fractional_odd_spacing) in;
19132
19133 patch in float redValueCS;
19134
19135 out float redValue;
19136
19137 void main()
19138 {
19139 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19140
19141 redValue = redValueCS;
19142 }
19143 )";
19144
19145 constexpr char kFS[] = R"(#version 310 es
19146 precision mediump float;
19147
19148 out vec4 fragColor;
19149
19150 in float redValue;
19151
19152 void main()
19153 {
19154 fragColor = vec4(redValue, 0., 0., 1.);
19155 })";
19156
19157 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19158 ASSERT_GL_NO_ERROR();
19159 // Delete the shader and recompile to fetch from cache.
19160 glDeleteProgram(unusedProgram);
19161 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19162 ASSERT_GL_NO_ERROR();
19163 glUseProgram(program);
19164
19165 constexpr GLfloat kInputData = 1.0f;
19166 GLBuffer input;
19167 glBindBuffer(GL_UNIFORM_BUFFER, input);
19168 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19169 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
19170 glUniformBlockBinding(program, kInputIndex, 0);
19171 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
19172 glBindBuffer(GL_UNIFORM_BUFFER, 0);
19173 ASSERT_GL_NO_ERROR();
19174
19175 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19176 ASSERT_GL_NO_ERROR();
19177
19178 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19179 }
19180
19181 // Test that shader caching maintains SSBOs in tessellation control shaders across shader
19182 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithSSBO)19183 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithSSBO)
19184 {
19185 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19186 ANGLE_SKIP_TEST_IF(!IsVulkan());
19187 GLint maxTessControlShaderStorageBlocks;
19188 glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT,
19189 &maxTessControlShaderStorageBlocks);
19190 ANGLE_SKIP_TEST_IF(maxTessControlShaderStorageBlocks == 0);
19191
19192 constexpr char kTCS[] = R"(#version 310 es
19193 #extension GL_EXT_tessellation_shader : require
19194 precision mediump float;
19195
19196 layout (vertices = 1) out;
19197
19198 layout (binding = 0, std430) buffer Input {
19199 float redInput;
19200 };
19201
19202 patch out float redValueCS;
19203
19204 void main()
19205 {
19206 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19207 gl_TessLevelInner[0] = 1.0;
19208 gl_TessLevelInner[1] = 1.0;
19209 gl_TessLevelOuter[0] = 1.0;
19210 gl_TessLevelOuter[1] = 1.0;
19211 gl_TessLevelOuter[2] = 1.0;
19212 gl_TessLevelOuter[3] = 1.0;
19213
19214 redValueCS = redInput;
19215 }
19216
19217 )";
19218
19219 constexpr char kTES[] = R"(#version 310 es
19220 #extension GL_EXT_tessellation_shader : require
19221 precision mediump float;
19222
19223 layout (quads, cw, fractional_odd_spacing) in;
19224
19225 patch in float redValueCS;
19226
19227 out float redValue;
19228
19229 void main()
19230 {
19231 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19232
19233 redValue = redValueCS;
19234 }
19235 )";
19236
19237 constexpr char kFS[] = R"(#version 310 es
19238 precision mediump float;
19239
19240 out vec4 fragColor;
19241
19242 in float redValue;
19243
19244 void main()
19245 {
19246 fragColor = vec4(redValue, 0., 0., 1.);
19247 })";
19248
19249 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19250 ASSERT_GL_NO_ERROR();
19251 // Delete the shader and recompile to fetch from cache.
19252 glDeleteProgram(unusedProgram);
19253 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19254 ASSERT_GL_NO_ERROR();
19255 glUseProgram(program);
19256
19257 constexpr GLfloat kInputData = 1.0f;
19258 GLBuffer input;
19259 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
19260 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19261 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
19262 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
19263 ASSERT_GL_NO_ERROR();
19264
19265 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19266 ASSERT_GL_NO_ERROR();
19267
19268 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19269 }
19270
19271 // Test that shader caching maintains uniforms in tessellation evaluation shaders across shader
19272 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniform)19273 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniform)
19274 {
19275 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19276 ANGLE_SKIP_TEST_IF(!IsVulkan());
19277
19278 constexpr char kTCS[] = R"(#version 310 es
19279 #extension GL_EXT_tessellation_shader : require
19280 precision mediump float;
19281
19282 layout (vertices = 1) out;
19283
19284 void main()
19285 {
19286 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19287 gl_TessLevelInner[0] = 1.0;
19288 gl_TessLevelInner[1] = 1.0;
19289 gl_TessLevelOuter[0] = 1.0;
19290 gl_TessLevelOuter[1] = 1.0;
19291 gl_TessLevelOuter[2] = 1.0;
19292 gl_TessLevelOuter[3] = 1.0;
19293 }
19294
19295 )";
19296
19297 constexpr char kTES[] = R"(#version 310 es
19298 #extension GL_EXT_tessellation_shader : require
19299 precision mediump float;
19300
19301 layout (quads, cw, fractional_odd_spacing) in;
19302
19303 uniform float redInput;
19304
19305 out float redValue;
19306
19307 void main()
19308 {
19309 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19310
19311 redValue = redInput;
19312 }
19313 )";
19314
19315 constexpr char kFS[] = R"(#version 310 es
19316 precision mediump float;
19317
19318 out vec4 fragColor;
19319
19320 in float redValue;
19321
19322 void main()
19323 {
19324 fragColor = vec4(redValue, 0., 0., 1.);
19325 })";
19326
19327 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19328 ASSERT_GL_NO_ERROR();
19329 // Delete the shader and recompile to fetch from cache.
19330 glDeleteProgram(unusedProgram);
19331 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19332 ASSERT_GL_NO_ERROR();
19333 glUseProgram(program);
19334
19335 constexpr GLfloat kRedValue = 1.0f;
19336 int redInputLocation = glGetUniformLocation(program, "redInput");
19337 glUniform1f(redInputLocation, kRedValue);
19338 ASSERT_GL_NO_ERROR();
19339
19340 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19341 ASSERT_GL_NO_ERROR();
19342
19343 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19344 }
19345
19346 // Test that shader caching maintains uniform blocks in tessellation evaluation shaders across
19347 // shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniformBlock)19348 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniformBlock)
19349 {
19350 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19351 ANGLE_SKIP_TEST_IF(!IsVulkan());
19352
19353 constexpr char kTCS[] = R"(#version 310 es
19354 #extension GL_EXT_tessellation_shader : require
19355 precision mediump float;
19356
19357 layout (vertices = 1) out;
19358
19359 void main()
19360 {
19361 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19362 gl_TessLevelInner[0] = 1.0;
19363 gl_TessLevelInner[1] = 1.0;
19364 gl_TessLevelOuter[0] = 1.0;
19365 gl_TessLevelOuter[1] = 1.0;
19366 gl_TessLevelOuter[2] = 1.0;
19367 gl_TessLevelOuter[3] = 1.0;
19368 }
19369
19370 )";
19371
19372 constexpr char kTES[] = R"(#version 310 es
19373 #extension GL_EXT_tessellation_shader : require
19374 precision mediump float;
19375
19376 layout (quads, cw, fractional_odd_spacing) in;
19377
19378 layout (std140) uniform Input {
19379 float redInput;
19380 };
19381
19382 out float redValue;
19383
19384 void main()
19385 {
19386 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19387
19388 redValue = redInput;
19389 }
19390 )";
19391
19392 constexpr char kFS[] = R"(#version 310 es
19393 precision mediump float;
19394
19395 out vec4 fragColor;
19396
19397 in float redValue;
19398
19399 void main()
19400 {
19401 fragColor = vec4(redValue, 0., 0., 1.);
19402 })";
19403
19404 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19405 ASSERT_GL_NO_ERROR();
19406 // Delete the shader and recompile to fetch from cache.
19407 glDeleteProgram(unusedProgram);
19408 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19409 ASSERT_GL_NO_ERROR();
19410 glUseProgram(program);
19411
19412 constexpr GLfloat kInputData = 1.0f;
19413 GLBuffer input;
19414 glBindBuffer(GL_UNIFORM_BUFFER, input);
19415 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19416 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
19417 glUniformBlockBinding(program, kInputIndex, 0);
19418 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
19419 glBindBuffer(GL_UNIFORM_BUFFER, 0);
19420 ASSERT_GL_NO_ERROR();
19421
19422 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19423 ASSERT_GL_NO_ERROR();
19424
19425 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19426 }
19427
19428 // Test that shader caching maintains SSBOs in tessellation evaluation shaders across shader
19429 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithSSBO)19430 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithSSBO)
19431 {
19432 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19433 ANGLE_SKIP_TEST_IF(!IsVulkan());
19434 GLint maxTessEvalShaderStorageBlocks;
19435 glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT,
19436 &maxTessEvalShaderStorageBlocks);
19437 ANGLE_SKIP_TEST_IF(maxTessEvalShaderStorageBlocks == 0);
19438
19439 constexpr char kTCS[] = R"(#version 310 es
19440 #extension GL_EXT_tessellation_shader : require
19441 precision mediump float;
19442
19443 layout (vertices = 1) out;
19444
19445 void main()
19446 {
19447 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19448 gl_TessLevelInner[0] = 1.0;
19449 gl_TessLevelInner[1] = 1.0;
19450 gl_TessLevelOuter[0] = 1.0;
19451 gl_TessLevelOuter[1] = 1.0;
19452 gl_TessLevelOuter[2] = 1.0;
19453 gl_TessLevelOuter[3] = 1.0;
19454 }
19455
19456 )";
19457
19458 constexpr char kTES[] = R"(#version 310 es
19459 #extension GL_EXT_tessellation_shader : require
19460 precision mediump float;
19461
19462 layout (quads, cw, fractional_odd_spacing) in;
19463
19464 layout (binding = 0, std430) buffer Input {
19465 float redInput;
19466 };
19467
19468 out float redValue;
19469
19470 void main()
19471 {
19472 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19473
19474 redValue = redInput;
19475 }
19476 )";
19477
19478 constexpr char kFS[] = R"(#version 310 es
19479 precision mediump float;
19480
19481 out vec4 fragColor;
19482
19483 in float redValue;
19484
19485 void main()
19486 {
19487 fragColor = vec4(redValue, 0., 0., 1.);
19488 })";
19489
19490 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19491 ASSERT_GL_NO_ERROR();
19492 // Delete the shader and recompile to fetch from cache.
19493 glDeleteProgram(unusedProgram);
19494 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19495 ASSERT_GL_NO_ERROR();
19496 glUseProgram(program);
19497
19498 constexpr GLfloat kInputData = 1.0f;
19499 GLBuffer input;
19500 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
19501 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19502 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
19503 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
19504 ASSERT_GL_NO_ERROR();
19505
19506 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19507 ASSERT_GL_NO_ERROR();
19508
19509 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19510 }
19511
19512 // Test that only macros for ESSL 1.0 compatible extensions are defined
TEST_P(GLSLTest,ESSL1ExtensionMacros)19513 TEST_P(GLSLTest, ESSL1ExtensionMacros)
19514 {
19515 std::string fs = essl1_shaders::fs::Red();
19516 fs += ExpectedExtensionMacros({
19517 "GL_ANGLE_multi_draw",
19518 "GL_APPLE_clip_distance",
19519 "GL_ARB_texture_rectangle",
19520 "GL_ARM_shader_framebuffer_fetch",
19521 "GL_EXT_blend_func_extended",
19522 "GL_EXT_draw_buffers",
19523 "GL_EXT_frag_depth",
19524 "GL_EXT_separate_shader_objects",
19525 "GL_EXT_shader_framebuffer_fetch_non_coherent",
19526 "GL_EXT_shader_framebuffer_fetch",
19527 "GL_EXT_shader_non_constant_global_initializers",
19528 "GL_EXT_shader_texture_lod",
19529 "GL_EXT_shadow_samplers",
19530 "GL_KHR_blend_equation_advanced",
19531 "GL_NV_EGL_stream_consumer_external",
19532 "GL_NV_shader_framebuffer_fetch",
19533 "GL_OES_EGL_image_external",
19534 "GL_OES_standard_derivatives",
19535 "GL_OES_texture_3D",
19536 "GL_WEBGL_video_texture",
19537 });
19538 fs += UnexpectedExtensionMacros({
19539 "GL_ANDROID_extension_pack_es31a",
19540 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19541 "GL_ANGLE_clip_cull_distance",
19542 "GL_ANGLE_shader_pixel_local_storage",
19543 "GL_ANGLE_texture_multisample",
19544 "GL_EXT_clip_cull_distance",
19545 "GL_EXT_geometry_shader",
19546 "GL_EXT_gpu_shader5",
19547 "GL_EXT_primitive_bounding_box",
19548 "GL_EXT_shader_io_blocks",
19549 "GL_EXT_tessellation_shader",
19550 "GL_EXT_texture_buffer",
19551 "GL_EXT_texture_cube_map_array",
19552 "GL_EXT_YUV_target",
19553 "GL_NV_shader_noperspective_interpolation",
19554 "GL_OES_EGL_image_external_essl3",
19555 "GL_OES_geometry_shader",
19556 "GL_OES_primitive_bounding_box",
19557 "GL_OES_sample_variables",
19558 "GL_OES_shader_image_atomic",
19559 "GL_OES_shader_io_blocks",
19560 "GL_OES_shader_multisample_interpolation",
19561 "GL_OES_texture_buffer",
19562 "GL_OES_texture_cube_map_array",
19563 "GL_OES_texture_storage_multisample_2d_array",
19564 "GL_OVR_multiview",
19565 "GL_OVR_multiview2",
19566 });
19567 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs.c_str());
19568 ASSERT_GL_NO_ERROR();
19569 }
19570
19571 // Test that only macros for ESSL 3.0 compatible extensions are defined
TEST_P(GLSLTest_ES3,ESSL3ExtensionMacros)19572 TEST_P(GLSLTest_ES3, ESSL3ExtensionMacros)
19573 {
19574 std::string fs = essl3_shaders::fs::Red();
19575 fs += ExpectedExtensionMacros({
19576 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19577 "GL_ANGLE_clip_cull_distance",
19578 "GL_ANGLE_multi_draw",
19579 "GL_ANGLE_shader_pixel_local_storage",
19580 "GL_ANGLE_texture_multisample",
19581 "GL_APPLE_clip_distance",
19582 "GL_ARB_texture_rectangle",
19583 "GL_ARM_shader_framebuffer_fetch",
19584 "GL_EXT_blend_func_extended",
19585 "GL_EXT_clip_cull_distance",
19586 "GL_EXT_separate_shader_objects",
19587 "GL_EXT_shader_framebuffer_fetch_non_coherent",
19588 "GL_EXT_shader_framebuffer_fetch",
19589 "GL_EXT_shader_non_constant_global_initializers",
19590 "GL_EXT_YUV_target",
19591 "GL_KHR_blend_equation_advanced",
19592 "GL_NV_EGL_stream_consumer_external",
19593 "GL_NV_shader_noperspective_interpolation",
19594 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19595 "GL_OES_EGL_image_external",
19596 "GL_OES_EGL_image_external_essl3",
19597 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19598 "GL_OES_texture_3D",
19599 "GL_OES_sample_variables",
19600 "GL_OES_shader_multisample_interpolation",
19601 // Enabled on ESSL 3+ because ANGLE can support multisample textures with ES 3.0 contexts.
19602 "GL_OES_texture_storage_multisample_2d_array",
19603 "GL_OVR_multiview",
19604 "GL_OVR_multiview2",
19605 "GL_WEBGL_video_texture",
19606 });
19607 fs += UnexpectedExtensionMacros({
19608 "GL_ANDROID_extension_pack_es31a",
19609 "GL_EXT_draw_buffers",
19610 "GL_EXT_frag_depth",
19611 "GL_EXT_geometry_shader",
19612 "GL_EXT_gpu_shader5",
19613 "GL_EXT_primitive_bounding_box",
19614 "GL_EXT_shader_io_blocks",
19615 "GL_EXT_shader_texture_lod",
19616 "GL_EXT_shadow_samplers",
19617 "GL_EXT_tessellation_shader",
19618 "GL_EXT_texture_buffer",
19619 "GL_EXT_texture_cube_map_array",
19620 "GL_NV_shader_framebuffer_fetch",
19621 "GL_OES_geometry_shader",
19622 "GL_OES_primitive_bounding_box",
19623 "GL_OES_shader_image_atomic",
19624 "GL_OES_shader_io_blocks",
19625 "GL_OES_standard_derivatives",
19626 "GL_OES_texture_buffer",
19627 "GL_OES_texture_cube_map_array",
19628 });
19629 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.c_str());
19630 ASSERT_GL_NO_ERROR();
19631 }
19632
19633 // Test that only macros for ESSL 3.1 compatible extensions are defined
TEST_P(GLSLTest_ES31,ESSL31ExtensionMacros)19634 TEST_P(GLSLTest_ES31, ESSL31ExtensionMacros)
19635 {
19636 std::string fs = essl31_shaders::fs::Red();
19637 fs += ExpectedExtensionMacros({
19638 "GL_ANDROID_extension_pack_es31a",
19639 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19640 "GL_ANGLE_clip_cull_distance",
19641 "GL_ANGLE_multi_draw",
19642 "GL_ANGLE_shader_pixel_local_storage",
19643 "GL_ANGLE_texture_multisample",
19644 "GL_APPLE_clip_distance",
19645 "GL_ARB_texture_rectangle",
19646 "GL_ARM_shader_framebuffer_fetch",
19647 "GL_EXT_blend_func_extended",
19648 "GL_EXT_clip_cull_distance",
19649 "GL_EXT_geometry_shader",
19650 "GL_EXT_gpu_shader5",
19651 "GL_EXT_primitive_bounding_box",
19652 "GL_EXT_separate_shader_objects",
19653 "GL_EXT_shader_framebuffer_fetch_non_coherent",
19654 "GL_EXT_shader_framebuffer_fetch",
19655 "GL_EXT_shader_io_blocks",
19656 "GL_EXT_shader_non_constant_global_initializers",
19657 "GL_EXT_tessellation_shader",
19658 "GL_EXT_texture_buffer",
19659 "GL_EXT_texture_cube_map_array",
19660 "GL_EXT_YUV_target",
19661 "GL_KHR_blend_equation_advanced",
19662 "GL_NV_EGL_stream_consumer_external",
19663 "GL_NV_shader_noperspective_interpolation",
19664 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19665 "GL_OES_EGL_image_external",
19666 "GL_OES_EGL_image_external_essl3",
19667 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19668 "GL_OES_texture_3D",
19669 "GL_OES_geometry_shader",
19670 "GL_OES_primitive_bounding_box",
19671 "GL_OES_sample_variables",
19672 "GL_OES_shader_image_atomic",
19673 "GL_OES_shader_io_blocks",
19674 "GL_OES_shader_multisample_interpolation",
19675 "GL_OES_texture_buffer",
19676 "GL_OES_texture_cube_map_array",
19677 "GL_OES_texture_storage_multisample_2d_array",
19678 "GL_OVR_multiview",
19679 "GL_OVR_multiview2",
19680 "GL_WEBGL_video_texture",
19681 });
19682 fs += UnexpectedExtensionMacros({
19683 "GL_EXT_draw_buffers",
19684 "GL_EXT_frag_depth",
19685 "GL_EXT_shader_texture_lod",
19686 "GL_EXT_shadow_samplers",
19687 "GL_NV_shader_framebuffer_fetch",
19688 "GL_OES_standard_derivatives",
19689 });
19690 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fs.c_str());
19691 ASSERT_GL_NO_ERROR();
19692 }
19693
19694 // Make sure names starting with webgl_ work.
TEST_P(GLSLTest_ES3,NameWithWebgl)19695 TEST_P(GLSLTest_ES3, NameWithWebgl)
19696 {
19697 constexpr char kFS[] = R"(#version 300 es
19698 out highp vec4 webgl_color;
19699 void main()
19700 {
19701 webgl_color = vec4(0, 1, 0, 1);
19702 })";
19703
19704 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19705 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19706 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19707 }
19708
19709 // Make sure webgl_FragColor works.
TEST_P(GLSLTest_ES3,NameWithWebglFragColor)19710 TEST_P(GLSLTest_ES3, NameWithWebglFragColor)
19711 {
19712 constexpr char kFS[] = R"(#version 300 es
19713 out highp vec4 webgl_FragColor;
19714 void main()
19715 {
19716 webgl_FragColor = vec4(0, 1, 0, 1);
19717 })";
19718
19719 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19720 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19721 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19722 }
19723
19724 // Test that the ScalarizeVecAndMatConstructorArgs workaround works correctly with constructors that
19725 // have no precision. Regression test for a bug where the generated helper has no precision
19726 // specified on the parameters and return value.
TEST_P(GLSLTest,ScalarizeVectorWorkaroundVsPrecisionlessConstructor)19727 TEST_P(GLSLTest, ScalarizeVectorWorkaroundVsPrecisionlessConstructor)
19728 {
19729 constexpr char kFS[] = R"(precision highp float;
19730 void main() {
19731 bool b1 = true;
19732 float f1 = dot(vec4(b1 ? 1.0 : 0.0, 0.0, 0.0, 0.0), vec4(1.0));
19733 gl_FragColor = vec4(f1,0.0,0.0, 1.0);
19734 })";
19735
19736 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19737 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19738 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19739 }
19740
19741 // Test that Metal compiler doesn't inline non-const globals
TEST_P(WebGLGLSLTest,InvalidGlobalsNotInlined)19742 TEST_P(WebGLGLSLTest, InvalidGlobalsNotInlined)
19743 {
19744 constexpr char kFS[] = R"(#version 100
19745 precision highp float;
19746 float v1 = 0.5;
19747 float v2 = v1;
19748
19749 float f1() {
19750 return v2;
19751 }
19752
19753 void main() {
19754 gl_FragColor = vec4(v1 + f1(),0.0,0.0, 1.0);
19755 })";
19756 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19757 ASSERT_GL_NO_ERROR();
19758 }
19759
19760 // Test that a struct can have lots of fields. Regression test for an inefficient O(n^2) check for
19761 // fields having unique names.
TEST_P(GLSLTest_ES3,LotsOfFieldsInStruct)19762 TEST_P(GLSLTest_ES3, LotsOfFieldsInStruct)
19763 {
19764 std::ostringstream fs;
19765 fs << R"(#version 300 es
19766 precision highp float;
19767 struct LotsOfFields
19768 {
19769 )";
19770 // Note: 16383 is the SPIR-V limit for struct member count.
19771 for (uint32_t i = 0; i < 16383; ++i)
19772 {
19773 fs << " float field" << i << ";\n";
19774 }
19775 fs << R"(};
19776 uniform B { LotsOfFields s; };
19777 out vec4 color;
19778 void main() {
19779 color = vec4(s.field0, 0.0, 0.0, 1.0);
19780 })";
19781
19782 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.str().c_str());
19783 }
19784
19785 // Test that structs with too many fields are rejected. In SPIR-V, the instruction that defines the
19786 // struct lists the fields which means the length of the instruction is a function of the field
19787 // count. Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be
19788 // represented.
TEST_P(GLSLTest_ES3,TooManyFieldsInStruct)19789 TEST_P(GLSLTest_ES3, TooManyFieldsInStruct)
19790 {
19791 std::ostringstream fs;
19792 fs << R"(#version 300 es
19793 precision highp float;
19794 struct TooManyFields
19795 {
19796 )";
19797 for (uint32_t i = 0; i < (1 << 16); ++i)
19798 {
19799 fs << " float field" << i << ";\n";
19800 }
19801 fs << R"(};
19802 uniform B { TooManyFields s; };
19803 out vec4 color;
19804 void main() {
19805 color = vec4(s.field0, 0.0, 0.0, 1.0);
19806 })";
19807
19808 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19809 EXPECT_EQ(0u, shader);
19810 }
19811
19812 // Same as TooManyFieldsInStruct, but with samplers in the struct.
TEST_P(GLSLTest_ES3,TooManySamplerFieldsInStruct)19813 TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct)
19814 {
19815 std::ostringstream fs;
19816 fs << R"(#version 300 es
19817 precision highp float;
19818 struct TooManyFields
19819 {
19820 )";
19821 for (uint32_t i = 0; i < (1 << 16); ++i)
19822 {
19823 fs << " sampler2D field" << i << ";\n";
19824 }
19825 fs << R"(};
19826 uniform TooManyFields s;
19827 out vec4 color;
19828 void main() {
19829 color = texture(s.field0, vec2(0));
19830 })";
19831
19832 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19833 EXPECT_EQ(0u, shader);
19834 }
19835
19836 // More complex variation of ManySamplerFieldsInStruct. This one compiles fine.
TEST_P(GLSLTest_ES3,ManySamplerFieldsInStructComplex)19837 TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex)
19838 {
19839 // D3D and OpenGL may be more restrictive about this many samplers.
19840 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19841
19842 std::ostringstream fs;
19843 fs << R"(#version 300 es
19844 precision highp float;
19845
19846 struct X {
19847 mediump sampler2D a[0xf00];
19848 mediump sampler2D b[0xf00];
19849 mediump sampler2D c[0xf000];
19850 mediump sampler2D d[0xf00];
19851 };
19852
19853 struct Y {
19854 X s1;
19855 mediump sampler2D a[0xf00];
19856 mediump sampler2D b[0xf000];
19857 mediump sampler2D c[0x14000];
19858 };
19859
19860 struct S {
19861 Y s1;
19862 };
19863
19864 struct structBuffer { S s; };
19865
19866 uniform structBuffer b;
19867
19868 out vec4 color;
19869 void main()
19870 {
19871 color = texture(b.s.s1.s1.c[0], vec2(0));
19872 })";
19873
19874 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19875 EXPECT_NE(0u, shader);
19876 }
19877
19878 // Make sure a large array of samplers works.
TEST_P(GLSLTest,ManySamplers)19879 TEST_P(GLSLTest, ManySamplers)
19880 {
19881 // D3D and OpenGL may be more restrictive about this many samplers.
19882 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19883
19884 std::ostringstream fs;
19885 fs << R"(precision highp float;
19886
19887 uniform mediump sampler2D c[0x12000];
19888
19889 void main()
19890 {
19891 gl_FragColor = texture2D(c[0], vec2(0));
19892 })";
19893
19894 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19895 EXPECT_NE(0u, shader);
19896 }
19897
19898 // Make sure a large array of samplers works when declared in a struct.
TEST_P(GLSLTest,ManySamplersInStruct)19899 TEST_P(GLSLTest, ManySamplersInStruct)
19900 {
19901 // D3D and OpenGL may be more restrictive about this many samplers.
19902 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19903
19904 std::ostringstream fs;
19905 fs << R"(precision highp float;
19906
19907 struct X {
19908 mediump sampler2D c[0x12000];
19909 };
19910
19911 uniform X x;
19912
19913 void main()
19914 {
19915 gl_FragColor = texture2D(x.c[0], vec2(0));
19916 })";
19917
19918 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19919 EXPECT_NE(0u, shader);
19920 }
19921
19922 // Test that passing large arrays to functions are compiled correctly. Regression test for the
19923 // SPIR-V generator that made a copy of the array to pass to the function, by decomposing and
19924 // reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a
19925 // length higher than can fit in SPIR-V.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayPassedToFunction)19926 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayPassedToFunction)
19927 {
19928 constexpr char kFS[] = R"(#version 300 es
19929 precision highp float;
19930 uniform Large { float a[65536]; };
19931 float f(float b[65536])
19932 {
19933 b[0] = 1.0;
19934 return b[0] + b[1];
19935 }
19936 out vec4 color;
19937 void main() {
19938 color = vec4(f(a), 0.0, 0.0, 1.0);
19939 })";
19940
19941 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19942 EXPECT_EQ(0u, shader);
19943 }
19944
19945 // Make sure the shader in LargeInterfaceBlockArrayPassedToFunction works if the large local is
19946 // avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArray)19947 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArray)
19948 {
19949 int maxUniformBlockSize = 0;
19950 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19951 ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19952
19953 constexpr char kFS[] = R"(#version 300 es
19954 precision highp float;
19955 uniform Large { float a[16384]; };
19956 out vec4 color;
19957 void main() {
19958 color = vec4(a[0], 0.0, 0.0, 1.0);
19959 })";
19960
19961 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19962 }
19963
19964 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayPassedToFunction)19965 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayPassedToFunction)
19966 {
19967 constexpr char kFS[] = R"(#version 300 es
19968 precision highp float;
19969 struct S { float a[65536]; };
19970 uniform Large { S s; };
19971 float f(float b[65536])
19972 {
19973 b[0] = 1.0;
19974 return b[0] + b[1];
19975 }
19976 out vec4 color;
19977 void main() {
19978 color = vec4(f(s.a), 0.0, 0.0, 1.0);
19979 })";
19980
19981 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19982 EXPECT_EQ(0u, shader);
19983 }
19984
19985 // Make sure the shader in LargeInterfaceBlockNestedArrayPassedToFunction works if the large local
19986 // is avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArray)19987 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArray)
19988 {
19989 int maxUniformBlockSize = 0;
19990 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19991 ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19992
19993 constexpr char kFS[] = R"(#version 300 es
19994 precision highp float;
19995 struct S { float a[16384]; };
19996 uniform Large { S s; };
19997 out vec4 color;
19998 void main() {
19999 color = vec4(s.a[0], 0.0, 0.0, 1.0);
20000 })";
20001
20002 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20003 }
20004
20005 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local
20006 // variable instead.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayCopiedToLocal)20007 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayCopiedToLocal)
20008 {
20009 constexpr char kFS[] = R"(#version 300 es
20010 precision highp float;
20011 uniform Large { float a[65536]; };
20012 out vec4 color;
20013 void main() {
20014 float b[65536] = a;
20015 color = vec4(b[0], 0.0, 0.0, 1.0);
20016 })";
20017
20018 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
20019 EXPECT_EQ(0u, shader);
20020 }
20021
20022 // Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayCopiedToLocal)20023 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayCopiedToLocal)
20024 {
20025 constexpr char kFS[] = R"(#version 300 es
20026 precision highp float;
20027 struct S { float a[65536]; };
20028 uniform Large { S s; };
20029 out vec4 color;
20030 void main() {
20031 S s2 = s;
20032 color = vec4(s2.a[0], 0.0, 0.0, 1.0);
20033 })";
20034
20035 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
20036 EXPECT_EQ(0u, shader);
20037 }
20038
20039 // Test that too large varyings are rejected.
TEST_P(GLSLTest_ES3,LargeArrayVarying)20040 TEST_P(GLSLTest_ES3, LargeArrayVarying)
20041 {
20042 constexpr char kFS[] = R"(#version 300 es
20043 precision highp float;
20044 in float a[65536];
20045 out vec4 color;
20046 void main() {
20047 color = vec4(a[0], 0.0, 0.0, 1.0);
20048 })";
20049
20050 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
20051 EXPECT_EQ(0u, shader);
20052 }
20053
20054 // Regression test for const globals losing const qualifiers during MSL
20055 // translation and exceeding available temporary registers on Apple GPUs.
TEST_P(GLSLTest_ES3,LargeConstGlobalArraysOfStructs)20056 TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs)
20057 {
20058 const int n = 128;
20059 std::stringstream fragmentShader;
20060 fragmentShader << "#version 300 es\n"
20061 << "precision mediump float;\n"
20062 << "uniform mediump int zero;\n"
20063 << "out vec4 color;\n"
20064 << "struct S { vec3 A; vec3 B; float C; };\n";
20065 for (int i = 0; i < 3; ++i)
20066 {
20067 fragmentShader << "const S s" << i << "[" << n << "] = S[" << n << "](\n";
20068 for (int j = 0; j < n; ++j)
20069 {
20070 fragmentShader << " S(vec3(0., 1., 0.), vec3(" << j << "), 0.)"
20071 << (j != n - 1 ? ",\n" : "\n");
20072 }
20073 fragmentShader << ");\n";
20074 }
20075 // To ensure that the array is not rescoped, it must be accessed from two functions.
20076 // To ensure that the array is not optimized out, it must be accessed with a dynamic index.
20077 fragmentShader << "vec4 foo() {\n"
20078 << " return vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
20079 << "}\n"
20080 << "void main() {\n"
20081 << " color = foo() * vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
20082 << "}\n";
20083 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader.str().c_str());
20084
20085 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20086 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20087 ASSERT_GL_NO_ERROR();
20088 }
20089
20090 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest,FramebufferFetchDoesNotAddUniforms)20091 TEST_P(GLSLTest, FramebufferFetchDoesNotAddUniforms)
20092 {
20093 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
20094 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers"));
20095
20096 static constexpr char kFS[] = R"(#version 100
20097 #extension GL_EXT_shader_framebuffer_fetch : require
20098 #extension GL_EXT_draw_buffers : require
20099 uniform highp vec4 u_color;
20100
20101 void main (void)
20102 {
20103 gl_FragData[0] = gl_LastFragData[0] + u_color;
20104 gl_FragData[1] = gl_LastFragData[1] + u_color;
20105 gl_FragData[2] = gl_LastFragData[2] + u_color;
20106 gl_FragData[3] = gl_LastFragData[3] + u_color;
20107 })";
20108
20109 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
20110 glUseProgram(program);
20111
20112 GLint activeUniforms = 0, uniformsMaxLength = 0;
20113 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20114 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20115
20116 // There should be only one active uniform
20117 EXPECT_EQ(activeUniforms, 1);
20118
20119 // And that is u_color
20120 GLsizei nameLen = uniformsMaxLength;
20121 std::vector<char> name(uniformsMaxLength);
20122
20123 GLint size;
20124 GLenum type;
20125
20126 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20127 EXPECT_EQ(std::string(name.data()), "u_color");
20128 EXPECT_EQ(size, 1);
20129 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20130 }
20131
20132 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,FramebufferFetchDoesNotAddUniforms)20133 TEST_P(GLSLTest_ES31, FramebufferFetchDoesNotAddUniforms)
20134 {
20135 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
20136
20137 static constexpr char kFS[] = R"(#version 310 es
20138 #extension GL_EXT_shader_framebuffer_fetch : require
20139 layout(location = 0) inout highp vec4 o_color;
20140
20141 layout(std140, binding = 0) buffer outBlock {
20142 highp vec4 data[256];
20143 };
20144
20145 uniform highp vec4 u_color;
20146 void main (void)
20147 {
20148 uint index = uint(gl_FragCoord.y) * 16u + uint(gl_FragCoord.x);
20149 data[index] = o_color;
20150 o_color += u_color;
20151 })";
20152
20153 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
20154 glUseProgram(program);
20155
20156 GLint activeUniforms = 0, uniformsMaxLength = 0;
20157 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20158 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20159
20160 // There should be only one active uniform
20161 EXPECT_EQ(activeUniforms, 1);
20162
20163 // And that is u_color
20164 GLsizei nameLen = uniformsMaxLength;
20165 std::vector<char> name(uniformsMaxLength);
20166
20167 GLint size;
20168 GLenum type;
20169
20170 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20171 EXPECT_EQ(std::string(name.data()), "u_color");
20172 EXPECT_EQ(size, 1);
20173 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20174 }
20175
20176 // Test that advanced blend emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,AdvancedBlendEquationsDoesNotAddUniforms)20177 TEST_P(GLSLTest_ES31, AdvancedBlendEquationsDoesNotAddUniforms)
20178 {
20179 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
20180
20181 static constexpr char kFS[] = R"(#version 310 es
20182 #extension GL_KHR_blend_equation_advanced : require
20183
20184 layout (blend_support_multiply) out;
20185
20186 out highp vec4 o_color;
20187
20188 layout(std140, binding = 0) buffer outBlock {
20189 highp vec4 data[256];
20190 };
20191
20192 uniform highp vec4 u_color;
20193 void main (void)
20194 {
20195 o_color = u_color;
20196 })";
20197
20198 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
20199 glUseProgram(program);
20200
20201 GLint activeUniforms = 0, uniformsMaxLength = 0;
20202 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20203 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20204
20205 // There should be only one active uniform
20206 EXPECT_EQ(activeUniforms, 1);
20207
20208 // And that is u_color
20209 GLsizei nameLen = uniformsMaxLength;
20210 std::vector<char> name(uniformsMaxLength);
20211
20212 GLint size;
20213 GLenum type;
20214
20215 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20216 EXPECT_EQ(std::string(name.data()), "u_color");
20217 EXPECT_EQ(size, 1);
20218 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20219 }
20220
20221 // Tests struct in function return type.
TEST_P(GLSLTest,StructInFunctionDefinition)20222 TEST_P(GLSLTest, StructInFunctionDefinition)
20223 {
20224 const char kFragmentShader[] = R"(precision mediump float;
20225 struct Foo
20226 {
20227 float v;
20228 };
20229
20230 Foo foo()
20231 {
20232 Foo f;
20233 f.v = 0.5;
20234 return f;
20235 }
20236
20237 void main()
20238 {
20239 gl_FragColor = vec4(1, 0, 0, 1);
20240 Foo f = foo();
20241 if (f.v == 0.5)
20242 {
20243 gl_FragColor = vec4(0, 1, 0, 1);
20244 }
20245 })";
20246
20247 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20248 glUseProgram(program);
20249
20250 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20251 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20252 }
20253
20254 // Tests struct definition in function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionDefinition)20255 TEST_P(GLSLTest, StructDefinitionInFunctionDefinition)
20256 {
20257 const char kFragmentShader[] = R"(precision mediump float;
20258 struct Foo { float v; } foo()
20259 {
20260 Foo f;
20261 f.v = 0.5;
20262 return f;
20263 }
20264
20265 void main()
20266 {
20267 gl_FragColor = vec4(1, 0, 0, 1);
20268 Foo f = foo();
20269 if (f.v == 0.5)
20270 {
20271 gl_FragColor = vec4(0, 1, 0, 1);
20272 }
20273 })";
20274
20275 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20276 glUseProgram(program);
20277
20278 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20279 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20280 }
20281
20282 // Test struct definition in forward declaration of function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototype)20283 TEST_P(GLSLTest, StructDefinitionInFunctionPrototype)
20284 {
20285 const char kFragmentShader[] = R"(precision mediump float;
20286 struct Foo { float v; } foo();
20287
20288 void main()
20289 {
20290 gl_FragColor = vec4(1, 0, 0, 1);
20291 Foo f = foo();
20292 if (f.v == 0.5)
20293 {
20294 gl_FragColor = vec4(0, 1, 0, 1);
20295 }
20296 }
20297
20298 Foo foo()
20299 {
20300 Foo f;
20301 f.v = 0.5;
20302 return f;
20303 })";
20304
20305 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20306 glUseProgram(program);
20307
20308 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20309 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20310 }
20311
20312 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototypeScope)20313 TEST_P(GLSLTest, StructDefinitionInFunctionPrototypeScope)
20314 {
20315 const char kFragmentShader[] = R"(precision mediump float;
20316
20317 struct Foo { float v; } foo()
20318 {
20319 Foo f;
20320 f.v = 0.5;
20321 return f;
20322 }
20323
20324 struct Bar { Foo f; } bar()
20325 {
20326 Bar b;
20327 b.f = foo();
20328 return b;
20329 }
20330
20331 void main()
20332 {
20333 gl_FragColor = vec4(1, 0, 0, 1);
20334 Bar b = bar();
20335 if (b.f.v == 0.5)
20336 {
20337 gl_FragColor = vec4(0, 1, 0, 1);
20338 }
20339 })";
20340
20341 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20342 glUseProgram(program);
20343
20344 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20345 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20346 }
20347
20348 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,NestedReturnedStructs)20349 TEST_P(GLSLTest, NestedReturnedStructs)
20350 {
20351 const char kFragmentShader[] = R"(precision mediump float;
20352 struct Foo { float v; } foo(float bar);
20353
20354 void main()
20355 {
20356 gl_FragColor = vec4(1, 0, 0, 1);
20357 float v = foo(foo(0.5).v).v;
20358 if (v == 0.5)
20359 {
20360 gl_FragColor = vec4(0, 1, 0, 1);
20361 }
20362 }
20363
20364 Foo foo(float bar)
20365 {
20366 Foo f;
20367 f.v = bar;
20368 return f;
20369 })";
20370
20371 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20372 glUseProgram(program);
20373
20374 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20375 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20376 }
20377
20378 // Test that vec equality works.
TEST_P(GLSLTest,VecEquality)20379 TEST_P(GLSLTest, VecEquality)
20380 {
20381 const char kFragmentShader[] = R"(precision mediump float;
20382 uniform vec4 u;
20383 void main()
20384 {
20385 gl_FragColor = vec4(0, 0, 0, 1);
20386 vec4 a = vec4(1.0, 2.0, 3.0, 4.0);
20387 if (a == u)
20388 gl_FragColor.g = 1.0;
20389
20390 vec4 b = vec4(1.0) + u;
20391 if (b == u)
20392 gl_FragColor.r = 1.0;
20393 }
20394 )";
20395
20396 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20397 glUseProgram(program);
20398 GLint u = glGetUniformLocation(program, "u");
20399 glUniform4f(u, 1, 2, 3, 4);
20400
20401 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20402 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20403 }
20404
20405 // Test that mat equality works.
TEST_P(GLSLTest,MatEquality)20406 TEST_P(GLSLTest, MatEquality)
20407 {
20408 const char kFragmentShader[] = R"(precision mediump float;
20409 uniform vec4 u;
20410 void main()
20411 {
20412 gl_FragColor = vec4(0, 0, 0, 1);
20413 mat4 a = mat4(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4);
20414 if (a == mat4(u, u, u, u))
20415 gl_FragColor.g = 1.0;
20416 mat4 b = mat4(1.0);
20417 if (b == mat4(u, u, u, u))
20418 gl_FragColor.r = 1.0;
20419 }
20420 )";
20421
20422 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20423 glUseProgram(program);
20424 GLint u = glGetUniformLocation(program, "u");
20425 glUniform4f(u, 1, 2, 3, 4);
20426
20427 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20428 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20429 }
20430
20431 // Test that struct equality works.
TEST_P(GLSLTest,StructEquality)20432 TEST_P(GLSLTest, StructEquality)
20433 {
20434 const char kFragmentShader[] = R"(precision mediump float;
20435 uniform vec4 u;
20436 struct A {
20437 vec4 i;
20438 };
20439 void main()
20440 {
20441 gl_FragColor = vec4(0, 0, 0, 1);
20442 A a, b;
20443 a.i = vec4(1,2,3,4);
20444 b.i = u;
20445 if (a == b)
20446 gl_FragColor.g = 1.0;
20447 b.i = vec4(1.0);
20448 if (a == b)
20449 gl_FragColor.r = 1.0;
20450 }
20451 )";
20452 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20453 glUseProgram(program);
20454 GLint u = glGetUniformLocation(program, "u");
20455 glUniform4f(u, 1, 2, 3, 4);
20456
20457 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20458 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20459 }
20460
20461 // Test that nested struct equality works.
TEST_P(GLSLTest,NestedStructEquality)20462 TEST_P(GLSLTest, NestedStructEquality)
20463 {
20464 const char kFragmentShader[] = R"(precision mediump float;
20465 uniform vec4 u;
20466 struct A {
20467 vec4 i;
20468 };
20469 struct B {
20470 A a;
20471 };
20472 void main()
20473 {
20474 gl_FragColor = vec4(0, 0, 0, 1);
20475 B a, b;
20476 a.a.i = vec4(1,2,3,4);
20477 b.a.i = u;
20478 if (a == b)
20479 gl_FragColor.g = 1.0;
20480 b.a.i = vec4(1.0);
20481 if (a == b)
20482 gl_FragColor.r = 1.0;
20483 }
20484 )";
20485 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20486 glUseProgram(program);
20487 GLint u = glGetUniformLocation(program, "u");
20488 glUniform4f(u, 1, 2, 3, 4);
20489
20490 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20491 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20492 }
20493
20494 // Test that double underscores user defined name is allowed
TEST_P(GLSLTest_ES3,DoubleUnderscoresName)20495 TEST_P(GLSLTest_ES3, DoubleUnderscoresName)
20496 {
20497 constexpr char kFS[] = R"(#version 300 es
20498 precision mediump float;
20499 out vec4 oColor;
20500 uniform struct __Data {float red;} data;
20501 void main() {oColor=vec4(data.red,0,1,1);})";
20502
20503 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20504 glUseProgram(program);
20505 // populate uniform
20506 GLint uniformLocation = glGetUniformLocation(program, "data.red");
20507 EXPECT_NE(uniformLocation, -1);
20508 glUniform1f(uniformLocation, 0);
20509
20510 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20511 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
20512 ASSERT_GL_NO_ERROR();
20513 }
20514
20515 // Test that user defined name starts with "ANGLE" or "ANGLE_"
TEST_P(GLSLTest_ES3,VariableNameStartsWithANGLE)20516 TEST_P(GLSLTest_ES3, VariableNameStartsWithANGLE)
20517 {
20518 constexpr char kFS[] = R"(#version 300 es
20519 precision mediump float;
20520 out vec4 oColor;
20521 uniform struct ANGLEData{float red;} data;
20522 uniform struct ANGLE_Data{float green;} _data;
20523 void main() {oColor=vec4(data.red,_data.green,1,1);})";
20524
20525 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20526 glUseProgram(program);
20527 // populate uniform
20528 GLint uniformRedLocation = glGetUniformLocation(program, "data.red");
20529 GLint uniformGreenLocation = glGetUniformLocation(program, "_data.green");
20530 EXPECT_NE(uniformRedLocation, -1);
20531 EXPECT_NE(uniformGreenLocation, -1);
20532 glUniform1f(uniformRedLocation, 0);
20533 glUniform1f(uniformGreenLocation, 0);
20534
20535 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20536 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
20537 ASSERT_GL_NO_ERROR();
20538 }
20539
20540 // Test that underscores in array names work with out arrays.
TEST_P(GLSLTest_ES3,UnderscoresWorkWithOutArrays)20541 TEST_P(GLSLTest_ES3, UnderscoresWorkWithOutArrays)
20542 {
20543 GLuint fbo;
20544 glGenFramebuffers(1, &fbo);
20545 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
20546
20547 GLuint textures[4];
20548 glGenTextures(4, textures);
20549
20550 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
20551 {
20552 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
20553 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
20554 GL_UNSIGNED_BYTE, nullptr);
20555 }
20556
20557 GLint maxDrawBuffers;
20558 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
20559 ASSERT_GE(maxDrawBuffers, 4);
20560
20561 GLuint readFramebuffer;
20562 glGenFramebuffers(1, &readFramebuffer);
20563 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
20564
20565 constexpr char kFS[] = R"(#version 300 es
20566 precision highp float;
20567 out vec4 _e[4];
20568 void main()
20569 {
20570 _e[0] = vec4(1.0, 0.0, 0.0, 1.0);
20571 _e[1] = vec4(0.0, 1.0, 0.0, 1.0);
20572 _e[2] = vec4(0.0, 0.0, 1.0, 1.0);
20573 _e[3] = vec4(1.0, 1.0, 1.0, 1.0);
20574 }
20575 )";
20576 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20577 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
20578 GL_COLOR_ATTACHMENT3};
20579 constexpr GLuint kMaxBuffers = 4;
20580 // Enable all draw buffers.
20581 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
20582 {
20583 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
20584 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
20585 textures[texIndex], 0);
20586 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
20587 textures[texIndex], 0);
20588 }
20589 glDrawBuffers(kMaxBuffers, allBufs);
20590
20591 // Draw with simple program.
20592 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20593 ASSERT_GL_NO_ERROR();
20594 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
20595 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
20596 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
20597 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
20598 }
20599
20600 // Fuzzer test involving struct samplers and comma operator
TEST_P(GLSLTest,StructSamplerVsComma)20601 TEST_P(GLSLTest, StructSamplerVsComma)
20602 {
20603 constexpr char kVS[] = R"(uniform struct S1
20604 {
20605 samplerCube ar;
20606 vec2 c;
20607 } a;
20608
20609 struct S2
20610 {
20611 vec3 c;
20612 } b[2];
20613
20614 void main (void)
20615 {
20616 ++b[0].c,a;
20617 })";
20618
20619 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
20620 EXPECT_NE(0u, shader);
20621 glDeleteShader(shader);
20622 }
20623
20624 // Make sure there is no name look up clash when initializing output variables
TEST_P(GLSLTest_ES3_InitShaderVariables,NameLookup)20625 TEST_P(GLSLTest_ES3_InitShaderVariables, NameLookup)
20626 {
20627 constexpr char kFS[] = R"(#version 300 es
20628 out highp vec4 color;
20629 void main()
20630 {
20631 highp vec4 color;
20632 color.x = 1.0;
20633 }
20634 )";
20635 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20636 drawQuad(program, essl3_shaders::PositionAttrib(), 0);
20637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
20638 ASSERT_GL_NO_ERROR();
20639 }
20640
20641 // Test that lowp and mediump varyings can be correctly matched between VS and FS.
TEST_P(GLSLTest,LowpMediumpVarying)20642 TEST_P(GLSLTest, LowpMediumpVarying)
20643 {
20644 const char kVS[] = R"(varying lowp float lowpVarying;
20645 attribute vec4 position;
20646 void main ()
20647 {
20648 lowpVarying = 1.;
20649 gl_Position = position;
20650 })";
20651
20652 const char kFS[] = R"(varying mediump float lowpVarying;
20653 void main ()
20654 {
20655 gl_FragColor = vec4(lowpVarying, 0, 0, 1);
20656 })";
20657
20658 ANGLE_GL_PROGRAM(program, kVS, kFS);
20659 drawQuad(program, "position", 0);
20660 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
20661 }
20662
20663 // Test that a mismatched varying that is unused in fragshader compiles.
TEST_P(GLSLTest,MismatchedInactiveVarying)20664 TEST_P(GLSLTest, MismatchedInactiveVarying)
20665 {
20666 const char kVS[] = R"(precision mediump float;
20667
20668 attribute vec2 a_position_0;
20669 attribute vec4 a_color_0;
20670
20671 varying vec4 vertexColor;
20672
20673 void main()
20674 {
20675 vertexColor = a_color_0;
20676 gl_Position = vec4(a_position_0, 0.0, 1.0);
20677 })";
20678
20679 const char kFS[] = R"(precision highp float;
20680
20681 uniform vec2 resolution;
20682 uniform vec2 fragOffset;
20683 uniform vec2 fragScale;
20684
20685 varying vec4 vertexColor;
20686 varying vec2 texCoord;
20687
20688 void main()
20689 {
20690 vec2 uv = (fragScale * gl_FragCoord.xy + fragOffset) / resolution;
20691 gl_FragColor = vec4(uv, 1.0, 1.0);
20692 })";
20693
20694 ANGLE_GL_PROGRAM(program, kVS, kFS);
20695 }
20696
20697 // Regression test for a bug where the sampler-in-struct rewrite transformation did not take a
20698 // specific pattern of side_effect,index_the_struct_to_write into account.
TEST_P(GLSLTest_ES3,StructWithSamplerRHSOfCommaWithSideEffect)20699 TEST_P(GLSLTest_ES3, StructWithSamplerRHSOfCommaWithSideEffect)
20700 {
20701 constexpr char kVS[] = R"(uniform struct S {
20702 sampler2D s;
20703 mat2 m;
20704 } u[2];
20705 void main()
20706 {
20707 ++gl_Position, u[0];
20708 })";
20709
20710 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
20711 EXPECT_NE(0u, shader);
20712 glDeleteShader(shader);
20713 }
20714 } // anonymous namespace
20715
20716 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
20717 GLSLTest,
20718 ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
20719 ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20720 ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20721 ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
20722 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20723 ES3_VULKAN().disable(Feature::SupportsSPIRV14),
20724 ES2_VULKAN().enable(Feature::VaryingsRequireMatchingPrecisionInSpirv));
20725
20726 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
20727
20728 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
20729 ANGLE_INSTANTIATE_TEST_ES3_AND(
20730 GLSLTest_ES3,
20731 ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
20732 ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20733 ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20734 ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
20735 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20736 ES3_VULKAN().disable(Feature::SupportsSPIRV14));
20737
20738 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
20739 ANGLE_INSTANTIATE_TEST_ES3(GLSLTestLoops);
20740
20741 ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
20742
20743 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
20744 ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest);
20745
20746 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
20747 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31,
20748 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
20749 ES31_VULKAN().disable(Feature::SupportsSPIRV14));
20750
20751 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3_InitShaderVariables);
20752 ANGLE_INSTANTIATE_TEST(
20753 GLSLTest_ES3_InitShaderVariables,
20754 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20755 ES3_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
20756
20757 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
20758 ANGLE_INSTANTIATE_TEST(
20759 GLSLTest_ES31_InitShaderVariables,
20760 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
20761 ES31_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
20762