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
17 class GLSLTest : public ANGLETest
18 {
19 protected:
GLSLTest()20 GLSLTest()
21 {
22 setWindowWidth(128);
23 setWindowHeight(128);
24 setConfigRedBits(8);
25 setConfigGreenBits(8);
26 setConfigBlueBits(8);
27 setConfigAlphaBits(8);
28 }
29
GenerateVaryingType(GLint vectorSize)30 std::string GenerateVaryingType(GLint vectorSize)
31 {
32 char varyingType[10];
33
34 if (vectorSize == 1)
35 {
36 sprintf(varyingType, "float");
37 }
38 else
39 {
40 sprintf(varyingType, "vec%d", vectorSize);
41 }
42
43 return std::string(varyingType);
44 }
45
GenerateVectorVaryingDeclaration(GLint vectorSize,GLint arraySize,GLint id)46 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
47 {
48 char buff[100];
49
50 if (arraySize == 1)
51 {
52 sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
53 }
54 else
55 {
56 sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id,
57 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 sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
71 returnString += buff;
72 }
73 else
74 {
75 for (int i = 0; i < arraySize; i++)
76 {
77 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i,
78 GenerateVaryingType(vectorSize).c_str());
79 returnString += buff;
80 }
81 }
82
83 return returnString;
84 }
85
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)86 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
87 {
88 if (arraySize == 1)
89 {
90 char buff[100];
91 sprintf(buff, "v%d + ", id);
92 return std::string(buff);
93 }
94 else
95 {
96 std::string returnString;
97 for (int i = 0; i < arraySize; i++)
98 {
99 char buff[100];
100 sprintf(buff, "v%d[%d] + ", id, i);
101 returnString += buff;
102 }
103 return returnString;
104 }
105 }
106
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)107 void GenerateGLSLWithVaryings(GLint floatCount,
108 GLint floatArrayCount,
109 GLint vec2Count,
110 GLint vec2ArrayCount,
111 GLint vec3Count,
112 GLint vec3ArrayCount,
113 GLint vec4Count,
114 GLint vec4ArrayCount,
115 bool useFragCoord,
116 bool usePointCoord,
117 bool usePointSize,
118 std::string *fragmentShader,
119 std::string *vertexShader)
120 {
121 // Generate a string declaring the varyings, to share between the fragment shader and the
122 // vertex shader.
123 std::string varyingDeclaration;
124
125 unsigned int varyingCount = 0;
126
127 for (GLint i = 0; i < floatCount; i++)
128 {
129 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
130 varyingCount += 1;
131 }
132
133 for (GLint i = 0; i < floatArrayCount; i++)
134 {
135 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
136 varyingCount += 1;
137 }
138
139 for (GLint i = 0; i < vec2Count; i++)
140 {
141 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
142 varyingCount += 1;
143 }
144
145 for (GLint i = 0; i < vec2ArrayCount; i++)
146 {
147 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
148 varyingCount += 1;
149 }
150
151 for (GLint i = 0; i < vec3Count; i++)
152 {
153 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
154 varyingCount += 1;
155 }
156
157 for (GLint i = 0; i < vec3ArrayCount; i++)
158 {
159 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
160 varyingCount += 1;
161 }
162
163 for (GLint i = 0; i < vec4Count; i++)
164 {
165 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
166 varyingCount += 1;
167 }
168
169 for (GLint i = 0; i < vec4ArrayCount; i++)
170 {
171 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
172 varyingCount += 1;
173 }
174
175 // Generate the vertex shader
176 vertexShader->clear();
177 vertexShader->append(varyingDeclaration);
178 vertexShader->append("\nvoid main()\n{\n");
179
180 unsigned int currentVSVarying = 0;
181
182 for (GLint i = 0; i < floatCount; i++)
183 {
184 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
185 currentVSVarying += 1;
186 }
187
188 for (GLint i = 0; i < floatArrayCount; i++)
189 {
190 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
191 currentVSVarying += 1;
192 }
193
194 for (GLint i = 0; i < vec2Count; i++)
195 {
196 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
197 currentVSVarying += 1;
198 }
199
200 for (GLint i = 0; i < vec2ArrayCount; i++)
201 {
202 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
203 currentVSVarying += 1;
204 }
205
206 for (GLint i = 0; i < vec3Count; i++)
207 {
208 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
209 currentVSVarying += 1;
210 }
211
212 for (GLint i = 0; i < vec3ArrayCount; i++)
213 {
214 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
215 currentVSVarying += 1;
216 }
217
218 for (GLint i = 0; i < vec4Count; i++)
219 {
220 vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
221 currentVSVarying += 1;
222 }
223
224 for (GLint i = 0; i < vec4ArrayCount; i++)
225 {
226 vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
227 currentVSVarying += 1;
228 }
229
230 if (usePointSize)
231 {
232 vertexShader->append("gl_PointSize = 1.0;\n");
233 }
234
235 vertexShader->append("}\n");
236
237 // Generate the fragment shader
238 fragmentShader->clear();
239 fragmentShader->append("precision highp float;\n");
240 fragmentShader->append(varyingDeclaration);
241 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
242
243 unsigned int currentFSVarying = 0;
244
245 // Make use of the float varyings
246 fragmentShader->append("\tretColor += vec4(");
247
248 for (GLint i = 0; i < floatCount; i++)
249 {
250 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
251 currentFSVarying += 1;
252 }
253
254 for (GLint i = 0; i < floatArrayCount; i++)
255 {
256 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
257 currentFSVarying += 1;
258 }
259
260 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
261
262 // Make use of the vec2 varyings
263 fragmentShader->append("\tretColor += vec4(");
264
265 for (GLint i = 0; i < vec2Count; i++)
266 {
267 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
268 currentFSVarying += 1;
269 }
270
271 for (GLint i = 0; i < vec2ArrayCount; i++)
272 {
273 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
274 currentFSVarying += 1;
275 }
276
277 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
278
279 // Make use of the vec3 varyings
280 fragmentShader->append("\tretColor += vec4(");
281
282 for (GLint i = 0; i < vec3Count; i++)
283 {
284 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
285 currentFSVarying += 1;
286 }
287
288 for (GLint i = 0; i < vec3ArrayCount; i++)
289 {
290 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
291 currentFSVarying += 1;
292 }
293
294 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
295
296 // Make use of the vec4 varyings
297 fragmentShader->append("\tretColor += ");
298
299 for (GLint i = 0; i < vec4Count; i++)
300 {
301 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
302 currentFSVarying += 1;
303 }
304
305 for (GLint i = 0; i < vec4ArrayCount; i++)
306 {
307 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
308 currentFSVarying += 1;
309 }
310
311 fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
312
313 // Set gl_FragColor, and use special variables if requested
314 fragmentShader->append("\tgl_FragColor = retColor");
315
316 if (useFragCoord)
317 {
318 fragmentShader->append(" + gl_FragCoord");
319 }
320
321 if (usePointCoord)
322 {
323 fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
324 }
325
326 fragmentShader->append(";\n}");
327 }
328
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)329 void VaryingTestBase(GLint floatCount,
330 GLint floatArrayCount,
331 GLint vec2Count,
332 GLint vec2ArrayCount,
333 GLint vec3Count,
334 GLint vec3ArrayCount,
335 GLint vec4Count,
336 GLint vec4ArrayCount,
337 bool useFragCoord,
338 bool usePointCoord,
339 bool usePointSize,
340 bool expectSuccess)
341 {
342 std::string fragmentShaderSource;
343 std::string vertexShaderSource;
344
345 GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
346 vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
347 usePointCoord, usePointSize, &fragmentShaderSource,
348 &vertexShaderSource);
349
350 GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
351
352 if (expectSuccess)
353 {
354 EXPECT_NE(0u, program);
355 }
356 else
357 {
358 EXPECT_EQ(0u, program);
359 }
360 }
361
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)362 void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
363 GLint fragmentUniformCount,
364 GLint vertexSamplersCount,
365 GLint fragmentSamplersCount,
366 bool expectSuccess)
367 {
368 std::stringstream vertexShader;
369 std::stringstream fragmentShader;
370
371 // Generate the vertex shader
372 vertexShader << "precision mediump float;\n";
373
374 for (int i = 0; i < vertexUniformCount; i++)
375 {
376 vertexShader << "uniform vec4 v" << i << ";\n";
377 }
378
379 for (int i = 0; i < vertexSamplersCount; i++)
380 {
381 vertexShader << "uniform sampler2D s" << i << ";\n";
382 }
383
384 vertexShader << "void main()\n{\n";
385
386 for (int i = 0; i < vertexUniformCount; i++)
387 {
388 vertexShader << " gl_Position += v" << i << ";\n";
389 }
390
391 for (int i = 0; i < vertexSamplersCount; i++)
392 {
393 vertexShader << " gl_Position += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
394 }
395
396 if (vertexUniformCount == 0 && vertexSamplersCount == 0)
397 {
398 vertexShader << " gl_Position = vec4(0.0);\n";
399 }
400
401 vertexShader << "}\n";
402
403 // Generate the fragment shader
404 fragmentShader << "precision mediump float;\n";
405
406 for (int i = 0; i < fragmentUniformCount; i++)
407 {
408 fragmentShader << "uniform vec4 v" << i << ";\n";
409 }
410
411 for (int i = 0; i < fragmentSamplersCount; i++)
412 {
413 fragmentShader << "uniform sampler2D s" << i << ";\n";
414 }
415
416 fragmentShader << "void main()\n{\n";
417
418 for (int i = 0; i < fragmentUniformCount; i++)
419 {
420 fragmentShader << " gl_FragColor += v" << i << ";\n";
421 }
422
423 for (int i = 0; i < fragmentSamplersCount; i++)
424 {
425 fragmentShader << " gl_FragColor += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
426 }
427
428 if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
429 {
430 fragmentShader << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
431 }
432
433 fragmentShader << "}\n";
434
435 GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
436
437 if (expectSuccess)
438 {
439 EXPECT_NE(0u, program);
440 }
441 else
442 {
443 EXPECT_EQ(0u, program);
444 }
445 }
446
QueryErrorMessage(GLuint program)447 std::string QueryErrorMessage(GLuint program)
448 {
449 GLint infoLogLength;
450 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
451 EXPECT_GL_NO_ERROR();
452
453 if (infoLogLength >= 1)
454 {
455 std::vector<GLchar> infoLog(infoLogLength);
456 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
457 infoLog.data());
458 EXPECT_GL_NO_ERROR();
459 return infoLog.data();
460 }
461
462 return "";
463 }
464
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)465 void validateComponentsInErrorMessage(const char *vertexShader,
466 const char *fragmentShader,
467 const char *expectedErrorType,
468 const char *expectedVariableFullName)
469 {
470 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
471 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
472
473 GLuint program = glCreateProgram();
474 glAttachShader(program, vs);
475 glAttachShader(program, fs);
476 glLinkProgram(program);
477
478 glDetachShader(program, vs);
479 glDetachShader(program, fs);
480 glDeleteShader(vs);
481 glDeleteShader(fs);
482
483 const std::string &errorMessage = QueryErrorMessage(program);
484 printf("%s\n", errorMessage.c_str());
485
486 EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
487 EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
488
489 glDeleteProgram(program);
490 ASSERT_GL_NO_ERROR();
491 }
492
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)493 void verifyAttachment2DColor(unsigned int index,
494 GLuint textureName,
495 GLenum target,
496 GLint level,
497 GLColor color)
498 {
499 glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
500 ASSERT_GL_NO_ERROR();
501
502 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
503 << "index " << index;
504 }
505 };
506
507 class GLSLTestNoValidation : public GLSLTest
508 {
509 public:
GLSLTestNoValidation()510 GLSLTestNoValidation() { setNoErrorEnabled(true); }
511 };
512
513 class GLSLTest_ES3 : public GLSLTest
514 {};
515
516 class GLSLTest_ES31 : public GLSLTest
517 {};
518
519 // Tests the "init output variables" ANGLE shader translator option.
520 class GLSLTest_ES31_InitShaderVariables : public GLSLTest
521 {};
522
BuildBigInitialStackShader(int length)523 std::string BuildBigInitialStackShader(int length)
524 {
525 std::string result;
526 result += "void main() { \n";
527 for (int i = 0; i < length; i++)
528 {
529 result += " if (true) { \n";
530 }
531 result += " int temp; \n";
532 for (int i = 0; i <= length; i++)
533 {
534 result += "} \n";
535 }
536 return result;
537 }
538
TEST_P(GLSLTest,NamelessScopedStructs)539 TEST_P(GLSLTest, NamelessScopedStructs)
540 {
541 constexpr char kFS[] = R"(precision mediump float;
542 void main()
543 {
544 struct
545 {
546 float q;
547 } b;
548
549 gl_FragColor = vec4(1, 0, 0, 1);
550 gl_FragColor.a += b.q;
551 })";
552
553 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
554 }
555
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)556 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
557 {
558 constexpr char kFS[] = R"(#version 300 es
559 precision mediump float;
560 out vec4 fragColor;
561 uniform vec3 a[3];
562 uniform vec3 b[3];
563 void main() {
564 bool same = a == b;
565 fragColor = vec4(0);
566 if (same) {
567 fragColor = vec4(1);
568 }
569 }
570 )";
571
572 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
573 glUseProgram(program);
574
575 GLint aLocation = glGetUniformLocation(program, "a");
576 GLint bLocation = glGetUniformLocation(program, "b");
577 EXPECT_NE(aLocation, -1);
578 EXPECT_NE(bLocation, -1);
579
580 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
581 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
582
583 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
584 glUniform3fv(bLocation, 9, almostZeros);
585
586 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
587 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
588
589 glUniform3fv(aLocation, 9, almostZeros);
590 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
591 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
592
593 ASSERT_GL_NO_ERROR();
594 }
595
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)596 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
597 {
598 constexpr char kFS[] = R"(#version 300 es
599 precision mediump float;
600 out vec4 fragColor;
601 uniform mat3 a[3];
602 uniform mat3 b[3];
603 void main() {
604 bool same = a == b;
605 fragColor = vec4(0);
606 if (same) {
607 fragColor = vec4(1);
608 }
609 }
610 )";
611
612 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
613 glUseProgram(program);
614
615 GLint aLocation = glGetUniformLocation(program, "a");
616 GLint bLocation = glGetUniformLocation(program, "b");
617 EXPECT_NE(aLocation, -1);
618 EXPECT_NE(bLocation, -1);
619
620 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
621 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
622
623 static float almostZeros[] = {
624 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,
625 };
626 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
627
628 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
629 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
630
631 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
632 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
633 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
634
635 ASSERT_GL_NO_ERROR();
636 }
637
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)638 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
639 {
640 constexpr char kFS[] = R"(#version 300 es
641 precision mediump float;
642 out vec4 fragColor;
643 uniform float a[3];
644 uniform float b[3];
645 void main() {
646 bool same = a == b;
647 fragColor = vec4(0);
648 if (same) {
649 fragColor = vec4(1);
650 }
651 }
652 )";
653
654 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
655 glUseProgram(program);
656
657 GLint aLocation = glGetUniformLocation(program, "a");
658 GLint bLocation = glGetUniformLocation(program, "b");
659 EXPECT_NE(aLocation, -1);
660 EXPECT_NE(bLocation, -1);
661
662 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
663 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
664
665 static float almostZeros[] = {
666 0,
667 0,
668 1,
669 };
670 glUniform1fv(bLocation, 3, almostZeros);
671
672 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
673 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
674
675 glUniform1fv(aLocation, 3, almostZeros);
676 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
678
679 ASSERT_GL_NO_ERROR();
680 }
681
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)682 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
683 {
684 constexpr char kFS[] = R"(#version 300 es
685 precision mediump float;
686 out vec4 fragColor;
687 uniform vec3 a[3];
688 uniform vec3 b[3];
689 void main() {
690 bool notSame = a != b;
691 fragColor = vec4(0);
692 if (notSame) {
693 fragColor = vec4(1);
694 }
695 }
696 )";
697
698 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
699 glUseProgram(program);
700
701 GLint aLocation = glGetUniformLocation(program, "a");
702 GLint bLocation = glGetUniformLocation(program, "b");
703 EXPECT_NE(aLocation, -1);
704 EXPECT_NE(bLocation, -1);
705
706 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
707 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
708
709 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
710 glUniform3fv(bLocation, 9, almostZeros);
711
712 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
714
715 glUniform3fv(aLocation, 9, almostZeros);
716 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
717 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
718
719 ASSERT_GL_NO_ERROR();
720 }
721
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)722 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
723 {
724 constexpr char kFS[] = R"(#version 300 es
725 precision mediump float;
726 out vec4 fragColor;
727 uniform mat3 a[3];
728 uniform mat3 b[3];
729 void main() {
730 bool notSame = a != b;
731 fragColor = vec4(0);
732 if (notSame) {
733 fragColor = vec4(1);
734 }
735 }
736 )";
737
738 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
739 glUseProgram(program);
740
741 GLint aLocation = glGetUniformLocation(program, "a");
742 GLint bLocation = glGetUniformLocation(program, "b");
743 EXPECT_NE(aLocation, -1);
744 EXPECT_NE(bLocation, -1);
745
746 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
747 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
748
749 static float almostZeros[] = {
750 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,
751 };
752 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
753
754 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
755 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
756
757 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
758 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
759 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
760
761 ASSERT_GL_NO_ERROR();
762 }
763
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)764 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
765 {
766 constexpr char kFS[] = R"(#version 300 es
767 precision mediump float;
768 out vec4 fragColor;
769 uniform float a[3];
770 uniform float b[3];
771 void main() {
772 bool notSame = a != b;
773 fragColor = vec4(0);
774 if (notSame) {
775 fragColor = vec4(1);
776 }
777 }
778 )";
779
780 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
781 glUseProgram(program);
782
783 GLint aLocation = glGetUniformLocation(program, "a");
784 GLint bLocation = glGetUniformLocation(program, "b");
785 EXPECT_NE(aLocation, -1);
786 EXPECT_NE(bLocation, -1);
787
788 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
789 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
790
791 static float almostZeros[] = {
792 0,
793 0,
794 1,
795 };
796 glUniform1fv(bLocation, 3, almostZeros);
797
798 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
799 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
800
801 glUniform1fv(aLocation, 3, almostZeros);
802 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
803 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
804
805 ASSERT_GL_NO_ERROR();
806 }
807
808 // Test that array of fragment shader outputs is processed properly and draws
809 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)810 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
811 {
812 GLuint fbo;
813 glGenFramebuffers(1, &fbo);
814 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
815
816 GLuint textures[4];
817 glGenTextures(4, textures);
818
819 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
820 {
821 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
822 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
823 GL_UNSIGNED_BYTE, nullptr);
824 }
825
826 GLint maxDrawBuffers;
827 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
828 ASSERT_GE(maxDrawBuffers, 4);
829
830 GLuint readFramebuffer;
831 glGenFramebuffers(1, &readFramebuffer);
832 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
833
834 constexpr char kFS[] = R"(#version 300 es
835 precision highp float;
836
837 out vec4 frag_color[4];
838
839 void main()
840 {
841 frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
842 frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
843 frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
844 frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
845 }
846 )";
847
848 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
849
850 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
851 GL_COLOR_ATTACHMENT3};
852
853 constexpr GLuint kMaxBuffers = 4;
854
855 // Enable all draw buffers.
856 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
857 {
858 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
859 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
860 textures[texIndex], 0);
861 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
862 textures[texIndex], 0);
863 }
864 glDrawBuffers(kMaxBuffers, allBufs);
865
866 // Draw with simple program.
867 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
868 ASSERT_GL_NO_ERROR();
869
870 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
871 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
872 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
873 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
874 }
875
876 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)877 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
878 {
879 constexpr char kFS[] = R"(#version 300 es
880 precision highp float;
881
882 // Make color0 inactive but specify color1 first. The Vulkan backend assigns bogus locations when
883 // compiling and fixes it up in SPIR-V. If color0's location is not fixed, it will return location
884 // 1 (aliasing color1). This will lead to a Vulkan validation warning about attachment 0 not being
885 // written to, which shouldn't be fatal.
886 layout(location = 1) out vec4 color1;
887 layout(location = 0) out vec4 color0;
888
889 void main()
890 {
891 color1 = vec4(0.0, 1.0, 0.0, 1.0);
892 }
893 )";
894
895 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
896
897 constexpr GLint kDrawBufferCount = 2;
898
899 GLint maxDrawBuffers;
900 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
901 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
902
903 GLTexture textures[kDrawBufferCount];
904
905 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
906 {
907 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
908 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
909 GL_UNSIGNED_BYTE, nullptr);
910 }
911
912 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
913
914 GLFramebuffer fbo;
915 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
916
917 // Enable all draw buffers.
918 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
919 {
920 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
921 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
922 textures[texIndex], 0);
923 }
924 glDrawBuffers(kDrawBufferCount, allBufs);
925
926 // Draw with simple program.
927 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
928 ASSERT_GL_NO_ERROR();
929 }
930
TEST_P(GLSLTest,ScopedStructsOrderBug)931 TEST_P(GLSLTest, ScopedStructsOrderBug)
932 {
933 constexpr char kFS[] = R"(precision mediump float;
934
935 struct T
936 {
937 float f;
938 };
939
940 void main()
941 {
942 T a;
943
944 struct T
945 {
946 float q;
947 };
948
949 T b;
950
951 gl_FragColor = vec4(1, 0, 0, 1);
952 gl_FragColor.a += a.f;
953 gl_FragColor.a += b.q;
954 })";
955
956 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
957 }
958
959 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
960 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)961 TEST_P(GLSLTest, ScopedStructsOrderBug2)
962 {
963 constexpr char kFS[] = R"(precision mediump float;
964
965 uniform struct T
966 {
967 float f;
968 } x;
969
970 void main()
971 {
972 T a;
973
974 struct T
975 {
976 float q;
977 };
978
979 T b;
980
981 gl_FragColor = vec4(1, 0, 0, 1);
982 gl_FragColor.a += a.f;
983 gl_FragColor.a += b.q;
984 })";
985
986 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
987 }
988
989 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)990 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
991 {
992 constexpr char kVS[] = R"(
993 struct S {
994 float member;
995 }, a;
996 void main() {
997 a.member = 0.0;
998 gl_Position = vec4(a.member);
999 })";
1000
1001 constexpr char kFS[] = R"(precision mediump float;
1002 precision mediump float;
1003 void main()
1004 {
1005 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1006 })";
1007
1008 ANGLE_GL_PROGRAM(program, kVS, kFS);
1009 }
1010
1011 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1012 TEST_P(GLSLTest, StructConstantFoldingBug)
1013 {
1014 constexpr char kVS[] = R"(
1015 void main()
1016 {
1017
1018 const struct s2 {
1019 int i;
1020 vec3 v3;
1021 bvec4 bv4;
1022 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1023
1024 struct s4 {
1025 int ii;
1026 vec4 v4;
1027 };
1028
1029 const struct s1 {
1030 s2 ss;
1031 int i;
1032 float f;
1033 mat4 m;
1034 s4 s44;
1035 } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1036
1037 const int field3 = s11.i * s11.ss.i; // constant folding (int * int)
1038 const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1039 // 49, 64, 81, 100
1040 const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]); // 10.0, 5.0, 16.0, 81.0
1041 gl_Position = v4;
1042 })";
1043
1044 constexpr char kFS[] = R"(precision mediump float;
1045 precision mediump float;
1046 void main()
1047 {
1048 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1049 })";
1050
1051 ANGLE_GL_PROGRAM(program, kVS, kFS);
1052 }
1053
1054 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1055 TEST_P(GLSLTest, StructConstantFoldingBug2)
1056 {
1057 constexpr char kVS[] = R"(
1058 uniform vec4 u;
1059
1060 void main()
1061 {
1062
1063 const struct s2 {
1064 int i;
1065 vec3 v3;
1066 bvec4 bv4;
1067 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1068
1069 s2 x;
1070 x.v3 = u.xyz;
1071
1072 gl_Position = vec4(x.v3, float(s22.i));
1073 })";
1074
1075 constexpr char kFS[] = R"(precision mediump float;
1076 precision mediump float;
1077 void main()
1078 {
1079 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1080 })";
1081
1082 ANGLE_GL_PROGRAM(program, kVS, kFS);
1083 }
1084
TEST_P(GLSLTest,ScopedStructsBug)1085 TEST_P(GLSLTest, ScopedStructsBug)
1086 {
1087 constexpr char kFS[] = R"(precision mediump float;
1088
1089 struct T_0
1090 {
1091 float f;
1092 };
1093
1094 void main()
1095 {
1096 gl_FragColor = vec4(1, 0, 0, 1);
1097
1098 struct T
1099 {
1100 vec2 v;
1101 };
1102
1103 T_0 a;
1104 T b;
1105
1106 gl_FragColor.a += a.f;
1107 gl_FragColor.a += b.v.x;
1108 })";
1109
1110 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1111 }
1112
TEST_P(GLSLTest,DxPositionBug)1113 TEST_P(GLSLTest, DxPositionBug)
1114 {
1115 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1116 varying float dx_Position;
1117 void main()
1118 {
1119 gl_Position = vec4(inputAttribute);
1120 dx_Position = 0.0;
1121 })";
1122
1123 constexpr char kFS[] = R"(precision mediump float;
1124
1125 varying float dx_Position;
1126
1127 void main()
1128 {
1129 gl_FragColor = vec4(dx_Position, 0, 0, 1);
1130 })";
1131
1132 ANGLE_GL_PROGRAM(program, kVS, kFS);
1133 }
1134
1135 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1136 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1137 {
1138 // http://anglebug.com/4092
1139 ANGLE_SKIP_TEST_IF(isSwiftshader());
1140 constexpr int kStartIndex = 0;
1141 constexpr int kArrayLength = 5;
1142 constexpr char kVS[] = R"(#version 300 es
1143 precision highp float;
1144 void main() {
1145 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1146 gl_PointSize = 3.0;
1147 })";
1148
1149 constexpr char kFS[] = R"(#version 300 es
1150 precision highp float;
1151 out vec4 outColor;
1152 void main() {
1153 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1154 })";
1155
1156 ANGLE_GL_PROGRAM(program, kVS, kFS);
1157
1158 glUseProgram(program);
1159 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1160
1161 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1162 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1163 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1164 {
1165 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1166 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1167 static_cast<int>(pointCenterY), GLColor::red);
1168 }
1169 }
1170
GetFirstIntPixelRedValue()1171 GLint GetFirstIntPixelRedValue()
1172 {
1173 GLint pixel[4];
1174 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1175 return pixel[0];
1176 }
1177
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1178 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1179 {
1180 constexpr char kVS[] = R"(#version 300 es
1181 flat out highp int vVertexID;
1182
1183 void main() {
1184 vVertexID = gl_VertexID;
1185 gl_PointSize = 1.0;
1186 gl_Position = vec4(0,0,0,1);
1187 })";
1188
1189 constexpr char kFS[] = R"(#version 300 es
1190 flat in highp int vVertexID;
1191 out highp int oVertexID;
1192 void main() {
1193 oVertexID = vVertexID;
1194 })";
1195
1196 ANGLE_GL_PROGRAM(program, kVS, kFS);
1197 glUseProgram(program);
1198 glViewport(0, 0, 1, 1);
1199
1200 GLTexture tex;
1201 glBindTexture(GL_TEXTURE_2D, tex);
1202 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1203 GLFramebuffer fb;
1204 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1205 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1206
1207 EXPECT_GL_NO_ERROR();
1208
1209 GLint clearData[4] = {42};
1210 glClearBufferiv(GL_COLOR, 0, clearData);
1211 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1212
1213 const int kIndexDataSize = 5;
1214 GLushort indexData[] = {1, 2, 5, 3, 10000};
1215 GLBuffer indexBuffer;
1216 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1217 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1218
1219 for (size_t first = 0; first < kIndexDataSize; ++first)
1220 {
1221 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1222 {
1223 glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1224 reinterpret_cast<const void *>(first * 2u));
1225 GLint expected = indexData[first + count - 1];
1226 GLint actual = GetFirstIntPixelRedValue();
1227 EXPECT_EQ(expected, actual);
1228 }
1229 }
1230 EXPECT_GL_NO_ERROR();
1231 }
1232
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1233 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1234 {
1235 constexpr char kVS[] = R"(#version 300 es
1236 flat out highp int vVertexID;
1237
1238 void main() {
1239 vVertexID = gl_VertexID;
1240 gl_PointSize = 1.0;
1241 gl_Position = vec4(0,0,0,1);
1242 })";
1243
1244 constexpr char kFS[] = R"(#version 300 es
1245 flat in highp int vVertexID;
1246 out highp int oVertexID;
1247 void main() {
1248 oVertexID = vVertexID;
1249 })";
1250
1251 ANGLE_GL_PROGRAM(program, kVS, kFS);
1252 glUseProgram(program);
1253 glViewport(0, 0, 1, 1);
1254
1255 GLTexture tex;
1256 glBindTexture(GL_TEXTURE_2D, tex);
1257 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1258 GLFramebuffer fb;
1259 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1260 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1261
1262 EXPECT_GL_NO_ERROR();
1263
1264 GLint clearData[4] = {42};
1265 glClearBufferiv(GL_COLOR, 0, clearData);
1266 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1267
1268 const int kIndexDataSize = 5;
1269 GLubyte indexData[] = {1, 2, 5, 3, 100};
1270 GLBuffer indexBuffer;
1271 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1272 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1273
1274 for (size_t first = 0; first < kIndexDataSize; ++first)
1275 {
1276 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1277 {
1278 glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1279 reinterpret_cast<const void *>(first));
1280 GLint expected = indexData[first + count - 1];
1281 GLint actual = GetFirstIntPixelRedValue();
1282 EXPECT_EQ(expected, actual);
1283 }
1284 }
1285 EXPECT_GL_NO_ERROR();
1286 }
1287
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1288 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1289 {
1290 glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1291
1292 GLint pixels[8];
1293 glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1294
1295 GLint expected = indices[first + 1];
1296 EXPECT_EQ(expected, pixels[0]);
1297 EXPECT_EQ(expected, pixels[4]);
1298 }
1299
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1300 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1301 {
1302 constexpr char kVS[] = R"(#version 300 es
1303 flat out highp int vVertexID;
1304 layout(location = 0) in vec4 position;
1305
1306 void main() {
1307 vVertexID = gl_VertexID;
1308 gl_Position = position;
1309 })";
1310
1311 constexpr char kFS[] = R"(#version 300 es
1312 flat in highp int vVertexID;
1313 out highp int oVertexID;
1314 void main() {
1315 oVertexID = vVertexID;
1316 })";
1317
1318 ANGLE_GL_PROGRAM(program, kVS, kFS);
1319 glUseProgram(program);
1320 glViewport(0, 0, 2, 1);
1321
1322 GLTexture tex;
1323 glBindTexture(GL_TEXTURE_2D, tex);
1324 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1325 GLFramebuffer fb;
1326 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1327 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1328
1329 EXPECT_GL_NO_ERROR();
1330
1331 struct LR
1332 {
1333 LR() : X0(-1.0f), X1(1.0f) {}
1334 float X0;
1335 float X1;
1336 };
1337 constexpr int kNumVertices = 100;
1338 LR vertData[kNumVertices];
1339 GLBuffer buf;
1340 glBindBuffer(GL_ARRAY_BUFFER, buf);
1341 glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1342 glEnableVertexAttribArray(0);
1343 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1344
1345 GLint clearData[4] = {42};
1346 glClearBufferiv(GL_COLOR, 0, clearData);
1347 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1348
1349 GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1350 GLBuffer indexBuffer;
1351 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1352 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1353
1354 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1355 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1356 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1357 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1358
1359 EXPECT_GL_NO_ERROR();
1360 }
1361
1362 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1363 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1364 {
1365 // Draws lines via indices (glDrawElements). Each pair of indices
1366 // draws the next consecutive pixel. For 2 points, because we're
1367 // using int attributes, they must be "flat" and so the spec
1368 // says for a given line the value should come from the second
1369 // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1370 // Each line is only 1 pixel long so every other pixel should
1371 // be the default value.
1372 constexpr char kVS[] = R"(#version 300 es
1373 flat out highp int vVertexID;
1374 layout(location = 0) in float position;
1375 uniform float width;
1376
1377 void main() {
1378 vVertexID = gl_VertexID;
1379 gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1380 })";
1381
1382 constexpr char kFS[] = R"(#version 300 es
1383 flat in highp int vVertexID;
1384 out highp int oVertexID;
1385 void main() {
1386 oVertexID = vVertexID;
1387 })";
1388
1389 GLubyte indexData[] = {1, 4, 5, 2, 50, 61, 32, 33};
1390 constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1391 GLBuffer indexBuffer;
1392 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1393 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1394
1395 ANGLE_GL_PROGRAM(program, kVS, kFS);
1396 glUseProgram(program);
1397 glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1398 glViewport(0, 0, kNumIndices, 1);
1399
1400 GLTexture tex;
1401 glBindTexture(GL_TEXTURE_2D, tex);
1402 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1403 GLFramebuffer fb;
1404 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1405 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1406
1407 constexpr int kNumVertices = 100;
1408 std::vector<float> vertData(kNumVertices, -1.0f);
1409 {
1410 int i = 0;
1411 for (GLubyte ndx : indexData)
1412 {
1413 vertData[ndx] = i++;
1414 }
1415 }
1416 GLBuffer buf;
1417 glBindBuffer(GL_ARRAY_BUFFER, buf);
1418 glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1419 glEnableVertexAttribArray(0);
1420 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1421
1422 GLint kDefaultValue = 42;
1423 GLint clearData[4] = {kDefaultValue};
1424 glClearBufferiv(GL_COLOR, 0, clearData);
1425 EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1426
1427 EXPECT_GL_NO_ERROR();
1428
1429 glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1430
1431 GLint pixels[kNumIndices * 4];
1432 glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1433
1434 for (size_t i = 0; i < kNumIndices; ++i)
1435 {
1436 const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1437 const int actual = pixels[i * 4];
1438 EXPECT_EQ(expected, actual);
1439 }
1440
1441 EXPECT_GL_NO_ERROR();
1442 }
1443
1444 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1445 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1446 {
1447 glDrawArrays(GL_POINTS, first, count);
1448
1449 int pixel[4];
1450 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1451 // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1452 // pixels.
1453 if (err == static_cast<GLenum>(GL_NO_ERROR))
1454 {
1455 EXPECT_GL_NO_ERROR();
1456 EXPECT_EQ(pixel[0], first + count - 1);
1457 }
1458 else
1459 {
1460 // If we call this function with err set, we will allow the error, but check the pixels if
1461 // the error hasn't occurred.
1462 GLenum glError = glGetError();
1463 if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1464 {
1465 EXPECT_EQ(pixel[0], first + count - 1);
1466 }
1467 }
1468 }
1469
1470 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1471 // is based off the WebGL test:
1472 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1473 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1474 {
1475 constexpr char kVS[] = R"(#version 300 es
1476 flat out highp int vVertexID;
1477 void main() {
1478 vVertexID = gl_VertexID;
1479 gl_Position = vec4(0,0,0,1);
1480 gl_PointSize = 1.0;
1481 })";
1482
1483 constexpr char kFS[] = R"(#version 300 es
1484 flat in highp int vVertexID;
1485 out highp int oVertexID;
1486 void main() {
1487 oVertexID = vVertexID;
1488 })";
1489
1490 ANGLE_GL_PROGRAM(program, kVS, kFS);
1491 glUseProgram(program);
1492 glViewport(0, 0, 1, 1);
1493
1494 GLTexture texture;
1495 glBindTexture(GL_TEXTURE_2D, texture);
1496 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1497 GLFramebuffer fbo;
1498 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1499 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1500 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1501 EXPECT_GL_NO_ERROR();
1502
1503 // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1504 GLint val[4] = {42};
1505 glClearBufferiv(GL_COLOR, 0, val);
1506 int pixel[4];
1507 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1508 EXPECT_EQ(pixel[0], val[0]);
1509
1510 GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1511 GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1512 GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1513 GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1514 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1515 GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1516 GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1517 GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1518 GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1519 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1520
1521 int32_t int32Max = 0x7FFFFFFF;
1522 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1523 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1524 }
1525
1526 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1527 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1528 {
1529 // http://anglebug.com/4092
1530 ANGLE_SKIP_TEST_IF(isSwiftshader());
1531 // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
1532 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1533
1534 constexpr int kStartIndex = 5;
1535 constexpr int kArrayLength = 5;
1536 constexpr char kVS[] = R"(#version 300 es
1537 precision highp float;
1538 void main() {
1539 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1540 gl_PointSize = 3.0;
1541 })";
1542
1543 constexpr char kFS[] = R"(#version 300 es
1544 precision highp float;
1545 out vec4 outColor;
1546 void main() {
1547 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1548 })";
1549
1550 ANGLE_GL_PROGRAM(program, kVS, kFS);
1551
1552 glUseProgram(program);
1553 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1554
1555 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1556 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1557 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1558 {
1559 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1560 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1561 static_cast<int>(pointCenterY), GLColor::red);
1562 }
1563 }
1564
TEST_P(GLSLTest,ElseIfRewriting)1565 TEST_P(GLSLTest, ElseIfRewriting)
1566 {
1567 constexpr char kVS[] =
1568 "attribute vec4 a_position;\n"
1569 "varying float v;\n"
1570 "void main() {\n"
1571 " gl_Position = a_position;\n"
1572 " v = 1.0;\n"
1573 " if (a_position.x <= 0.5) {\n"
1574 " v = 0.0;\n"
1575 " } else if (a_position.x >= 0.5) {\n"
1576 " v = 2.0;\n"
1577 " }\n"
1578 "}\n";
1579
1580 constexpr char kFS[] =
1581 "precision highp float;\n"
1582 "varying float v;\n"
1583 "void main() {\n"
1584 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1585 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1586 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1587 " gl_FragColor = color;\n"
1588 "}\n";
1589
1590 ANGLE_GL_PROGRAM(program, kVS, kFS);
1591
1592 drawQuad(program, "a_position", 0.5f);
1593
1594 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1595 EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1596 }
1597
TEST_P(GLSLTest,TwoElseIfRewriting)1598 TEST_P(GLSLTest, TwoElseIfRewriting)
1599 {
1600 constexpr char kVS[] =
1601 "attribute vec4 a_position;\n"
1602 "varying float v;\n"
1603 "void main() {\n"
1604 " gl_Position = a_position;\n"
1605 " if (a_position.x == 0.0) {\n"
1606 " v = 1.0;\n"
1607 " } else if (a_position.x > 0.5) {\n"
1608 " v = 0.0;\n"
1609 " } else if (a_position.x > 0.75) {\n"
1610 " v = 0.5;\n"
1611 " }\n"
1612 "}\n";
1613
1614 constexpr char kFS[] =
1615 "precision highp float;\n"
1616 "varying float v;\n"
1617 "void main() {\n"
1618 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1619 "}\n";
1620
1621 ANGLE_GL_PROGRAM(program, kVS, kFS);
1622 }
1623
TEST_P(GLSLTest,FrontFacingAndVarying)1624 TEST_P(GLSLTest, FrontFacingAndVarying)
1625 {
1626 EGLPlatformParameters platform = GetParam().eglParameters;
1627
1628 constexpr char kVS[] = R"(attribute vec4 a_position;
1629 varying float v_varying;
1630 void main()
1631 {
1632 v_varying = a_position.x;
1633 gl_Position = a_position;
1634 })";
1635
1636 constexpr char kFS[] = R"(precision mediump float;
1637 varying float v_varying;
1638 void main()
1639 {
1640 vec4 c;
1641
1642 if (gl_FrontFacing)
1643 {
1644 c = vec4(v_varying, 0, 0, 1.0);
1645 }
1646 else
1647 {
1648 c = vec4(0, v_varying, 0, 1.0);
1649 }
1650 gl_FragColor = c;
1651 })";
1652
1653 GLuint program = CompileProgram(kVS, kFS);
1654
1655 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1656 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1657 {
1658 if (platform.majorVersion == 9 && platform.minorVersion == 3)
1659 {
1660 EXPECT_EQ(0u, program);
1661 return;
1662 }
1663 }
1664
1665 // Otherwise, compilation should succeed
1666 EXPECT_NE(0u, program);
1667 }
1668
1669 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1670 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1671 {
1672 // Draw with the first program.
1673 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1674 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1675 ASSERT_GL_NO_ERROR();
1676 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1677
1678 // Clear and release shader compiler.
1679 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1680 glClear(GL_COLOR_BUFFER_BIT);
1681 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1682 glReleaseShaderCompiler();
1683 ASSERT_GL_NO_ERROR();
1684
1685 // Draw with a second program.
1686 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1687 drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1688 ASSERT_GL_NO_ERROR();
1689 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1690 }
1691
1692 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1693 TEST_P(GLSLTest_ES3, VersionMismatch)
1694 {
1695 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1696 EXPECT_EQ(0u, program);
1697
1698 program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1699 EXPECT_EQ(0u, program);
1700 }
1701
1702 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1703 TEST_P(GLSLTest, InvariantVaryingOut)
1704 {
1705 constexpr char kFS[] =
1706 "precision mediump float;\n"
1707 "varying float v_varying;\n"
1708 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1709
1710 constexpr char kVS[] =
1711 "attribute vec4 a_position;\n"
1712 "invariant varying float v_varying;\n"
1713 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1714
1715 GLuint program = CompileProgram(kVS, kFS);
1716 EXPECT_EQ(0u, program);
1717 }
1718
1719 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1720 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1721 {
1722 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1723 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1724 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1725
1726 constexpr char kFS[] =
1727 "#version 300 es\n"
1728 "precision mediump float;\n"
1729 "in float v_varying;\n"
1730 "out vec4 my_FragColor;\n"
1731 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1732
1733 constexpr char kVS[] =
1734 "#version 300 es\n"
1735 "in vec4 a_position;\n"
1736 "invariant out float v_varying;\n"
1737 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1738
1739 GLuint program = CompileProgram(kVS, kFS);
1740 EXPECT_NE(0u, program);
1741 }
1742
1743 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1744 TEST_P(GLSLTest, InvariantVaryingIn)
1745 {
1746 constexpr char kFS[] =
1747 "precision mediump float;\n"
1748 "invariant varying float v_varying;\n"
1749 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1750
1751 constexpr char kVS[] =
1752 "attribute vec4 a_position;\n"
1753 "varying float v_varying;\n"
1754 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1755
1756 GLuint program = CompileProgram(kVS, kFS);
1757 EXPECT_EQ(0u, program);
1758 }
1759
1760 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1761 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1762 {
1763 constexpr char kFS[] =
1764 "#version 300 es\n"
1765 "precision mediump float;\n"
1766 "invariant in float v_varying;\n"
1767 "out vec4 my_FragColor;\n"
1768 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1769
1770 constexpr char kVS[] =
1771 "#version 300 es\n"
1772 "in vec4 a_position;\n"
1773 "out float v_varying;\n"
1774 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1775
1776 GLuint program = CompileProgram(kVS, kFS);
1777 EXPECT_EQ(0u, program);
1778 }
1779
1780 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1781 TEST_P(GLSLTest, InvariantVaryingBoth)
1782 {
1783 constexpr char kFS[] =
1784 "precision mediump float;\n"
1785 "invariant varying float v_varying;\n"
1786 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1787
1788 constexpr char kVS[] =
1789 "attribute vec4 a_position;\n"
1790 "invariant varying float v_varying;\n"
1791 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1792
1793 GLuint program = CompileProgram(kVS, kFS);
1794 EXPECT_NE(0u, program);
1795 }
1796
1797 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1798 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1799 {
1800 constexpr char kFS[] =
1801 "#version 300 es\n"
1802 "precision mediump float;\n"
1803 "invariant in float v_varying;\n"
1804 "out vec4 my_FragColor;\n"
1805 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1806
1807 constexpr char kVS[] =
1808 "#version 300 es\n"
1809 "in vec4 a_position;\n"
1810 "invariant out float v_varying;\n"
1811 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1812
1813 GLuint program = CompileProgram(kVS, kFS);
1814 EXPECT_EQ(0u, program);
1815 }
1816
1817 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1818 TEST_P(GLSLTest, InvariantGLPosition)
1819 {
1820 constexpr char kFS[] =
1821 "precision mediump float;\n"
1822 "varying float v_varying;\n"
1823 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1824
1825 constexpr char kVS[] =
1826 "attribute vec4 a_position;\n"
1827 "invariant gl_Position;\n"
1828 "varying float v_varying;\n"
1829 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1830
1831 GLuint program = CompileProgram(kVS, kFS);
1832 EXPECT_NE(0u, program);
1833 }
1834
1835 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1836 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1837 {
1838 constexpr char kFS[] =
1839 "#version 300 es\n"
1840 "precision mediump float;\n"
1841 "in float v_varying;\n"
1842 "out vec4 my_FragColor;\n"
1843 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1844
1845 constexpr char kVS[] =
1846 "#version 300 es\n"
1847 "in vec4 a_position;\n"
1848 "invariant gl_Position;\n"
1849 "out float v_varying;\n"
1850 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1851
1852 GLuint program = CompileProgram(kVS, kFS);
1853 EXPECT_NE(0u, program);
1854 }
1855
1856 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1857 TEST_P(GLSLTest, InvariantAllBoth)
1858 {
1859 constexpr char kFS[] =
1860 "#pragma STDGL invariant(all)\n"
1861 "precision mediump float;\n"
1862 "varying float v_varying;\n"
1863 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1864
1865 constexpr char kVS[] =
1866 "#pragma STDGL invariant(all)\n"
1867 "attribute vec4 a_position;\n"
1868 "varying float v_varying;\n"
1869 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1870
1871 GLuint program = CompileProgram(kVS, kFS);
1872 EXPECT_EQ(0u, program);
1873 }
1874
1875 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1876 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1877 {
1878 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1879
1880 constexpr char kVS[] = R"(#version 310 es
1881 #extension GL_EXT_shader_io_blocks : require
1882
1883 struct S
1884 {
1885 vec4 s;
1886 };
1887
1888 out Output
1889 {
1890 vec4 x;
1891 invariant S s;
1892 };
1893
1894 out S s2;
1895
1896 void main(){
1897 x = vec4(0);
1898 s.s = vec4(1);
1899 s2.s = vec4(2);
1900 S s3 = s;
1901 s.s = s3.s;
1902 })";
1903
1904 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1905 EXPECT_NE(0u, shader);
1906 glDeleteShader(shader);
1907 }
1908
1909 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)1910 TEST_P(GLSLTest, MissingReturnFloat)
1911 {
1912 constexpr char kVS[] =
1913 "varying float v_varying;\n"
1914 "float f() { if (v_varying > 0.0) return 1.0; }\n"
1915 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
1916
1917 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1918 EXPECT_NE(0u, program);
1919 }
1920
1921 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)1922 TEST_P(GLSLTest, MissingReturnVec2)
1923 {
1924 constexpr char kVS[] =
1925 "varying float v_varying;\n"
1926 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
1927 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1928
1929 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1930 EXPECT_NE(0u, program);
1931 }
1932
1933 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)1934 TEST_P(GLSLTest, MissingReturnVec3)
1935 {
1936 constexpr char kVS[] =
1937 "varying float v_varying;\n"
1938 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1939 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1940
1941 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1942 EXPECT_NE(0u, program);
1943 }
1944
1945 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)1946 TEST_P(GLSLTest, MissingReturnVec4)
1947 {
1948 constexpr char kVS[] =
1949 "varying float v_varying;\n"
1950 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1951 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1952
1953 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1954 EXPECT_NE(0u, program);
1955 }
1956
1957 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)1958 TEST_P(GLSLTest, MissingReturnIVec4)
1959 {
1960 constexpr char kVS[] =
1961 "varying float v_varying;\n"
1962 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1963 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1964
1965 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1966 EXPECT_NE(0u, program);
1967 }
1968
1969 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)1970 TEST_P(GLSLTest, MissingReturnMat4)
1971 {
1972 constexpr char kVS[] =
1973 "varying float v_varying;\n"
1974 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1975 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1976
1977 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1978 EXPECT_NE(0u, program);
1979 }
1980
1981 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)1982 TEST_P(GLSLTest, MissingReturnStruct)
1983 {
1984 constexpr char kVS[] =
1985 "varying float v_varying;\n"
1986 "struct s { float a; int b; vec2 c; };\n"
1987 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1988 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1989
1990 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1991 EXPECT_NE(0u, program);
1992 }
1993
1994 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)1995 TEST_P(GLSLTest_ES3, MissingReturnArray)
1996 {
1997 constexpr char kVS[] =
1998 "#version 300 es\n"
1999 "in float v_varying;\n"
2000 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2001 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2002
2003 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2004 EXPECT_NE(0u, program);
2005 }
2006
2007 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2008 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2009 {
2010 constexpr char kVS[] =
2011 "#version 300 es\n"
2012 "in float v_varying;\n"
2013 "struct s { float a; int b; vec2 c; };\n"
2014 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2015 "vec2(1.0, 1.0))); } }\n"
2016 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2017
2018 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2019 EXPECT_NE(0u, program);
2020 }
2021
2022 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2023 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2024 {
2025 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2026 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2027
2028 constexpr char kVS[] =
2029 "#version 300 es\n"
2030 "in float v_varying;\n"
2031 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2032 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2033 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2034 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2035
2036 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2037 EXPECT_NE(0u, program);
2038 }
2039
2040 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2041 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2042 {
2043 constexpr char kVS[] = R"(#version 300 es
2044 in float v_varying;
2045 struct s { float a; int b; vec2 c; };
2046 s[2] f()
2047 {
2048 return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2049 }
2050 void main()
2051 {
2052 gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2053 })";
2054
2055 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2056 EXPECT_NE(0u, program);
2057 }
2058
2059 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2060 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2061 {
2062 constexpr char kFS[] =
2063 "#version 300 es\n"
2064 "#pragma STDGL invariant(all)\n"
2065 "precision mediump float;\n"
2066 "in float v_varying;\n"
2067 "out vec4 my_FragColor;\n"
2068 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2069
2070 constexpr char kVS[] =
2071 "#version 300 es\n"
2072 "#pragma STDGL invariant(all)\n"
2073 "in vec4 a_position;\n"
2074 "out float v_varying;\n"
2075 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2076
2077 GLuint program = CompileProgram(kVS, kFS);
2078 EXPECT_EQ(0u, program);
2079 }
2080
2081 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2082 TEST_P(GLSLTest, InvariantAllIn)
2083 {
2084 constexpr char kFS[] =
2085 "#pragma STDGL invariant(all)\n"
2086 "precision mediump float;\n"
2087 "varying float v_varying;\n"
2088 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2089
2090 constexpr char kVS[] =
2091 "attribute vec4 a_position;\n"
2092 "varying float v_varying;\n"
2093 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2094
2095 GLuint program = CompileProgram(kVS, kFS);
2096 EXPECT_NE(0u, program);
2097 }
2098
2099 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2100 TEST_P(GLSLTest_ES3, InvariantAllIn)
2101 {
2102 constexpr char kFS[] =
2103 "#version 300 es\n"
2104 "#pragma STDGL invariant(all)\n"
2105 "precision mediump float;\n"
2106 "in float v_varying;\n"
2107 "out vec4 my_FragColor;\n"
2108 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2109
2110 constexpr char kVS[] =
2111 "#version 300 es\n"
2112 "in vec4 a_position;\n"
2113 "out float v_varying;\n"
2114 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2115
2116 GLuint program = CompileProgram(kVS, kFS);
2117 EXPECT_EQ(0u, program);
2118 }
2119
2120 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2121 TEST_P(GLSLTest, InvariantAllOut)
2122 {
2123 constexpr char kFS[] =
2124 "precision mediump float;\n"
2125 "varying float v_varying;\n"
2126 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2127
2128 constexpr char kVS[] =
2129 "#pragma STDGL invariant(all)\n"
2130 "attribute vec4 a_position;\n"
2131 "varying float v_varying;\n"
2132 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2133
2134 GLuint program = CompileProgram(kVS, kFS);
2135 EXPECT_EQ(0u, program);
2136 }
2137
2138 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2139 TEST_P(GLSLTest_ES3, InvariantAllOut)
2140 {
2141 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2142 // for varyings which are invariant in vertex shader,
2143 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
2144 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2145
2146 constexpr char kFS[] =
2147 "#version 300 es\n"
2148 "precision mediump float;\n"
2149 "in float v_varying;\n"
2150 "out vec4 my_FragColor;\n"
2151 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2152
2153 constexpr char kVS[] =
2154 "#version 300 es\n"
2155 "#pragma STDGL invariant(all)\n"
2156 "in vec4 a_position;\n"
2157 "out float v_varying;\n"
2158 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2159
2160 GLuint program = CompileProgram(kVS, kFS);
2161 EXPECT_NE(0u, program);
2162 }
2163
TEST_P(GLSLTest,MaxVaryingVec4)2164 TEST_P(GLSLTest, MaxVaryingVec4)
2165 {
2166 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2167 // (http://anglebug.com/1291)
2168 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
2169
2170 GLint maxVaryings = 0;
2171 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2172
2173 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2174 }
2175
2176 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2177 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2178 {
2179 GLint maxVaryings = 0;
2180 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2181
2182 // Generate shader code that uses gl_FragCoord.
2183 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2184 }
2185
2186 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2187 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2188 {
2189 GLint maxVaryings = 0;
2190 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2191
2192 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2193 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2194 }
2195
2196 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2197 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2198 {
2199 GLint maxVaryings = 0;
2200 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2201
2202 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2203 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2204 }
2205
2206 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2207 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2208 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2209 {
2210 ANGLE_SKIP_TEST_IF(!IsD3D9());
2211
2212 GLint maxVaryings = 0;
2213 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2214
2215 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2216 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2217 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2218
2219 // Special case for gl_PointSize: we get it for free on D3D9.
2220 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2221 }
2222
2223 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2224 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2225 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2226 {
2227 GLint maxVaryings = 0;
2228 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2229
2230 // Generate shader code that uses gl_FragCoord.
2231 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2232 }
2233
TEST_P(GLSLTest,MaxVaryingVec3)2234 TEST_P(GLSLTest, MaxVaryingVec3)
2235 {
2236 GLint maxVaryings = 0;
2237 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2238
2239 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2240 }
2241
TEST_P(GLSLTest,MaxVaryingVec3Array)2242 TEST_P(GLSLTest, MaxVaryingVec3Array)
2243 {
2244 GLint maxVaryings = 0;
2245 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2246
2247 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2248 }
2249
2250 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2251 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2252 {
2253 GLint maxVaryings = 0;
2254 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2255
2256 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2257 }
2258
2259 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2260 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2261 {
2262 GLint maxVaryings = 0;
2263 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2264
2265 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2266 }
2267
2268 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2269 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2270 {
2271 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2272 // (http://anglebug.com/3849)
2273 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2274
2275 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2276 // (http://anglebug.com/1291)
2277 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
2278
2279 GLint maxVaryings = 0;
2280 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2281
2282 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2283 }
2284
2285 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2286 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2287 {
2288 ANGLE_SKIP_TEST_IF(IsD3D9());
2289
2290 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2291 ANGLE_SKIP_TEST_IF(IsOpenGLES());
2292
2293 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2294 // (http://anglebug.com/1291)
2295 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
2296
2297 GLint maxVaryings = 0;
2298 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2299
2300 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2301 // we should be aware that when we're packing into an odd number of varying registers the
2302 // last row will be empty and can not fit the final vec2 arrary.
2303 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2304
2305 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2306 }
2307
2308 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2309 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2310 {
2311 // (http://anglebug.com/4439)
2312 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2313
2314 // http://anglebug.com/4446
2315 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
2316
2317 GLint maxVaryings = 0;
2318 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2319
2320 std::stringstream vertexShaderSource;
2321 std::stringstream fragmentShaderSource;
2322
2323 // substract 1 here for gl_PointSize
2324 const GLint vec4Count = maxVaryings - 1;
2325 unsigned int varyingCount = 0;
2326 std::string varyingDeclaration;
2327 for (GLint i = 0; i < vec4Count; i++)
2328 {
2329 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2330 varyingCount += 1;
2331 }
2332 // Generate the vertex shader
2333 vertexShaderSource.clear();
2334 vertexShaderSource << varyingDeclaration;
2335 vertexShaderSource << "\nattribute vec4 a_position;\n";
2336 vertexShaderSource << "\nvoid main()\n{\n";
2337 unsigned int currentVSVarying = 0;
2338 for (GLint i = 0; i < vec4Count; i++)
2339 {
2340 vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2341 currentVSVarying += 1;
2342 }
2343 vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2344 vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2345 vertexShaderSource << "}\n";
2346
2347 // Generate the fragment shader
2348 fragmentShaderSource.clear();
2349 fragmentShaderSource << "precision highp float;\n";
2350 fragmentShaderSource << varyingDeclaration;
2351 fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2352 unsigned int currentFSVarying = 0;
2353 // Make use of the vec4 varyings
2354 fragmentShaderSource << "\tretColor += ";
2355 for (GLint i = 0; i < vec4Count; i++)
2356 {
2357 fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2358 currentFSVarying += 1;
2359 }
2360 fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2361 constexpr GLuint testValue = 234;
2362 fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2363 << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2364 fragmentShaderSource << "}\n";
2365
2366 std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2367 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2368 fragmentShaderSource.str().c_str(), tfVaryings,
2369 GL_INTERLEAVED_ATTRIBS);
2370
2371 GLBuffer xfbBuffer;
2372 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2373 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2374 GL_STATIC_DRAW);
2375
2376 GLTransformFeedback xfb;
2377 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2378 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2379
2380 glUseProgram(program1);
2381
2382 const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2383 GLBuffer vertexBuffer;
2384 // need to shift half pixel to make sure the line covers the center of the pixel
2385 const Vector3 vertices[2] = {
2386 {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2387 {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2388 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2389 glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2390 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2391 glEnableVertexAttribArray(positionLocation);
2392
2393 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2394 glClear(GL_COLOR_BUFFER_BIT);
2395
2396 glBeginTransformFeedback(GL_LINES);
2397 glDrawArrays(GL_LINES, 0, 2);
2398 glEndTransformFeedback();
2399
2400 ASSERT_GL_NO_ERROR();
2401
2402 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2403 }
2404
2405 // Verify shader source with a fixed length that is less than the null-terminated length will
2406 // compile.
TEST_P(GLSLTest,FixedShaderLength)2407 TEST_P(GLSLTest, FixedShaderLength)
2408 {
2409 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2410
2411 const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2412 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2413 const char *sourceArray[1] = {source.c_str()};
2414 GLint lengths[1] = {static_cast<GLint>(source.length() - appendGarbage.length())};
2415 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2416 glCompileShader(shader);
2417
2418 GLint compileResult;
2419 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2420 EXPECT_NE(compileResult, 0);
2421 }
2422
2423 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2424 TEST_P(GLSLTest, NegativeShaderLength)
2425 {
2426 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2427
2428 const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2429 GLint lengths[1] = {-10};
2430 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2431 glCompileShader(shader);
2432
2433 GLint compileResult;
2434 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2435 EXPECT_NE(compileResult, 0);
2436 }
2437
2438 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2439 TEST_P(GLSLTest, InvalidFieldFirstChar)
2440 {
2441 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
2442 const char *source = "void main() {vec4 x; x.}";
2443 glShaderSource(shader, 1, &source, 0);
2444 glCompileShader(shader);
2445
2446 GLint compileResult;
2447 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2448 EXPECT_EQ(0, compileResult);
2449 }
2450
2451 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2452 TEST_P(GLSLTest, MixedShaderLengths)
2453 {
2454 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2455
2456 const char *sourceArray[] = {
2457 "void main()",
2458 "{",
2459 " gl_FragColor = vec4(0, 0, 0, 0);",
2460 "}",
2461 };
2462 GLint lengths[] = {
2463 -10,
2464 1,
2465 static_cast<GLint>(strlen(sourceArray[2])),
2466 -1,
2467 };
2468 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2469
2470 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2471 glCompileShader(shader);
2472
2473 GLint compileResult;
2474 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2475 EXPECT_NE(compileResult, 0);
2476 }
2477
2478 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2479 TEST_P(GLSLTest, ZeroShaderLength)
2480 {
2481 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2482
2483 const char *sourceArray[] = {
2484 "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2485 };
2486 GLint lengths[] = {
2487 0, 0, -1, 0, 0,
2488 };
2489 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2490
2491 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2492 glCompileShader(shader);
2493
2494 GLint compileResult;
2495 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2496 EXPECT_NE(compileResult, 0);
2497 }
2498
2499 // Tests that bad index expressions don't crash ANGLE's translator.
2500 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2501 TEST_P(GLSLTest, BadIndexBug)
2502 {
2503 constexpr char kFSSourceVec[] =
2504 "precision mediump float;\n"
2505 "uniform vec4 uniformVec;\n"
2506 "void main()\n"
2507 "{\n"
2508 " gl_FragColor = vec4(uniformVec[int()]);\n"
2509 "}";
2510
2511 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2512 EXPECT_EQ(0u, shader);
2513
2514 if (shader != 0)
2515 {
2516 glDeleteShader(shader);
2517 }
2518
2519 constexpr char kFSSourceMat[] =
2520 "precision mediump float;\n"
2521 "uniform mat4 uniformMat;\n"
2522 "void main()\n"
2523 "{\n"
2524 " gl_FragColor = vec4(uniformMat[int()]);\n"
2525 "}";
2526
2527 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2528 EXPECT_EQ(0u, shader);
2529
2530 if (shader != 0)
2531 {
2532 glDeleteShader(shader);
2533 }
2534
2535 constexpr char kFSSourceArray[] =
2536 "precision mediump float;\n"
2537 "uniform vec4 uniformArray;\n"
2538 "void main()\n"
2539 "{\n"
2540 " gl_FragColor = vec4(uniformArray[int()]);\n"
2541 "}";
2542
2543 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2544 EXPECT_EQ(0u, shader);
2545
2546 if (shader != 0)
2547 {
2548 glDeleteShader(shader);
2549 }
2550 }
2551
2552 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2553 TEST_P(GLSLTest, StructSpecifiersUniforms)
2554 {
2555 constexpr char kFS[] = R"(precision mediump float;
2556
2557 uniform struct S { float field; } s;
2558
2559 void main()
2560 {
2561 gl_FragColor = vec4(1, 0, 0, 1);
2562 gl_FragColor.a += s.field;
2563 })";
2564
2565 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2566 EXPECT_NE(0u, program);
2567 }
2568
2569 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2570 TEST_P(GLSLTest, StructWithInitializer)
2571 {
2572 constexpr char kFS[] = R"(precision mediump float;
2573
2574 struct S { float a; } s = S(1.0);
2575
2576 void main()
2577 {
2578 gl_FragColor = vec4(0, 0, 0, 1);
2579 gl_FragColor.r += s.a;
2580 })";
2581
2582 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2583 glUseProgram(program);
2584
2585 // Test drawing, should be red.
2586 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2587
2588 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2589 EXPECT_GL_NO_ERROR();
2590 }
2591
2592 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2593 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2594 {
2595 constexpr char kFS[] = R"(precision mediump float;
2596
2597 struct S { float a; };
2598 uniform S u_s;
2599
2600 void main()
2601 {
2602 gl_FragColor = vec4(u_s.a);
2603 })";
2604
2605 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2606 glUseProgram(program);
2607
2608 // Test drawing, should be red.
2609 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2610
2611 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2612 EXPECT_GL_NO_ERROR();
2613 }
2614
2615 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2616 TEST_P(GLSLTest, StructWithUniformInitializer)
2617 {
2618 constexpr char kFS[] = R"(precision mediump float;
2619
2620 struct S { float a; } s = S(1.0);
2621 uniform S us;
2622
2623 void main()
2624 {
2625 gl_FragColor = vec4(0, 0, 0, 1);
2626 gl_FragColor.r += s.a;
2627 gl_FragColor.g += us.a;
2628 })";
2629
2630 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2631 glUseProgram(program);
2632
2633 // Test drawing, should be red.
2634 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2635
2636 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2637 EXPECT_GL_NO_ERROR();
2638 }
2639
2640 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2641 // beginning with "gl_" are filtered out by our validation logic, we must
2642 // bypass the validation to test the behaviour of the implementation.
2643 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2644 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2645 {
2646 constexpr char kFS[] = R"(precision mediump float;
2647
2648 void main()
2649 {
2650 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2651 })";
2652
2653 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2654
2655 // We need to bypass validation for this call.
2656 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
2657 EXPECT_EQ(-1, nearIndex);
2658
2659 // Test drawing does not throw an exception.
2660 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2661
2662 EXPECT_GL_NO_ERROR();
2663 }
2664
GenerateSmallPowShader(double base,double exponent)2665 std::string GenerateSmallPowShader(double base, double exponent)
2666 {
2667 std::stringstream stream;
2668
2669 stream.precision(8);
2670
2671 double result = pow(base, exponent);
2672
2673 stream << "precision highp float;\n"
2674 << "float fun(float arg)\n"
2675 << "{\n"
2676 << " return pow(arg, " << std::fixed << exponent << ");\n"
2677 << "}\n"
2678 << "\n"
2679 << "void main()\n"
2680 << "{\n"
2681 << " const float a = " << std::scientific << base << ";\n"
2682 << " float b = fun(a);\n"
2683 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2684 << " {\n"
2685 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2686 << " }\n"
2687 << " else\n"
2688 << " {\n"
2689 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2690 << " }\n"
2691 << "}\n";
2692
2693 return stream.str();
2694 }
2695
2696 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2697 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)2698 TEST_P(GLSLTest, PowOfSmallConstant)
2699 {
2700 // Test with problematic exponents that are close to an integer.
2701 std::vector<double> testExponents;
2702 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2703 for (double epsilonMultiplier : epsilonMultipliers)
2704 {
2705 for (int i = -4; i <= 5; ++i)
2706 {
2707 if (i >= -1 && i <= 1)
2708 continue;
2709 const double epsilon = 1.0e-8;
2710 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
2711 testExponents.push_back(bad);
2712 }
2713 }
2714
2715 // Also test with a few exponents that are not close to an integer.
2716 testExponents.push_back(3.6);
2717 testExponents.push_back(3.4);
2718
2719 for (double testExponent : testExponents)
2720 {
2721 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2722
2723 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2724
2725 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2726
2727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2728 EXPECT_GL_NO_ERROR();
2729 }
2730 }
2731
2732 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2733 TEST_P(GLSLTest, LoopIndexingValidation)
2734 {
2735 constexpr char kFS[] = R"(precision mediump float;
2736
2737 uniform float loopMax;
2738
2739 void main()
2740 {
2741 gl_FragColor = vec4(1, 0, 0, 1);
2742 for (float l = 0.0; l < loopMax; l++)
2743 {
2744 if (loopMax > 3.0)
2745 {
2746 gl_FragColor.a += 0.1;
2747 }
2748 }
2749 })";
2750
2751 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2752
2753 const char *sourceArray[1] = {kFS};
2754 glShaderSource(shader, 1, sourceArray, nullptr);
2755 glCompileShader(shader);
2756
2757 GLint compileResult;
2758 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2759
2760 // If the test is configured to run limited to Feature Level 9_3, then it is
2761 // assumed that shader compilation will fail with an expected error message containing
2762 // "Loop index cannot be compared with non-constant expression"
2763 if (GetParam() == ES2_D3D9())
2764 {
2765 if (compileResult != 0)
2766 {
2767 FAIL() << "Shader compilation succeeded, expected failure";
2768 }
2769 else
2770 {
2771 GLint infoLogLength;
2772 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2773
2774 std::string infoLog;
2775 infoLog.resize(infoLogLength);
2776 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2777
2778 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2779 std::string::npos)
2780 {
2781 FAIL() << "Shader compilation failed with unexpected error message";
2782 }
2783 }
2784 }
2785 else
2786 {
2787 EXPECT_NE(0, compileResult);
2788 }
2789
2790 if (shader != 0)
2791 {
2792 glDeleteShader(shader);
2793 }
2794 }
2795
2796 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2797 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2798 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2799 {
2800 // crbug.com/680631
2801 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2802
2803 int maxUniforms = 10000;
2804 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2805 EXPECT_GL_NO_ERROR();
2806 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2807
2808 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2809 }
2810
2811 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2812 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2813 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2814 {
2815 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2816
2817 // Times out on D3D11 on test infra. http://anglebug.com/5076
2818 ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2819
2820 int maxUniforms = 10000;
2821 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2822 EXPECT_GL_NO_ERROR();
2823 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2824
2825 int maxTextureImageUnits = 0;
2826 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2827
2828 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2829 }
2830
2831 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2832 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2833 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2834 {
2835 int maxUniforms = 10000;
2836 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2837 EXPECT_GL_NO_ERROR();
2838 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2839
2840 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2841 }
2842
2843 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2844 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2845 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2846 {
2847 // crbug.com/680631
2848 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2849
2850 int maxUniforms = 10000;
2851 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2852 EXPECT_GL_NO_ERROR();
2853 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2854
2855 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2856 }
2857
2858 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2859 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2860 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2861 {
2862 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2863
2864 int maxUniforms = 10000;
2865 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2866 EXPECT_GL_NO_ERROR();
2867
2868 int maxTextureImageUnits = 0;
2869 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2870
2871 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2872 }
2873
2874 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2875 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2876 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2877 {
2878 int maxUniforms = 10000;
2879 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2880 EXPECT_GL_NO_ERROR();
2881 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2882 << std::endl;
2883
2884 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2885 }
2886
2887 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2888 TEST_P(GLSLTest, TextureLOD)
2889 {
2890 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2891
2892 constexpr char kFS[] =
2893 "#extension GL_EXT_shader_texture_lod : require\n"
2894 "uniform sampler2D u_texture;\n"
2895 "void main() {\n"
2896 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2897 "0.0));\n"
2898 "}\n";
2899
2900 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2901 ASSERT_NE(0u, shader);
2902 glDeleteShader(shader);
2903 }
2904
2905 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2906 // function calls to use them in vertex shaders. http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2907 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2908 {
2909 constexpr char kVS[] = R"(
2910 precision highp float;
2911 uniform int uni;
2912 uniform sampler2D texture;
2913
2914 vec4 A();
2915
2916 vec4 B() {
2917 vec4 a;
2918 for(int r=0; r<14; r++){
2919 if (r < uni) return vec4(0.0);
2920 a = A();
2921 }
2922 return a;
2923 }
2924
2925 vec4 A() {
2926 return texture2D(texture, vec2(0.0, 0.0));
2927 }
2928
2929 void main() {
2930 gl_Position = B();
2931 })";
2932
2933 constexpr char kFS[] = R"(
2934 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
2935 )";
2936
2937 ANGLE_GL_PROGRAM(program, kVS, kFS);
2938 }
2939
2940 // Test to verify the a shader can have a sampler unused in a vertex shader
2941 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)2942 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
2943 {
2944 constexpr char kVS[] = R"(
2945 attribute vec2 position;
2946 varying mediump vec2 texCoord;
2947 uniform sampler2D tex;
2948 void main()
2949 {
2950 gl_Position = vec4(position, 0, 1);
2951 texCoord = position * 0.5 + vec2(0.5);
2952 })";
2953
2954 constexpr char kFS[] = R"(
2955 varying mediump vec2 texCoord;
2956 uniform sampler2D tex;
2957 void main()
2958 {
2959 gl_FragColor = texture2D(tex, texCoord);
2960 })";
2961
2962 ANGLE_GL_PROGRAM(program, kVS, kFS);
2963
2964 // Initialize basic red texture.
2965 const std::vector<GLColor> redColors(4, GLColor::red);
2966 GLTexture texture;
2967 glBindTexture(GL_TEXTURE_2D, texture);
2968 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
2969 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2970 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2971 ASSERT_GL_NO_ERROR();
2972
2973 drawQuad(program, "position", 0.0f);
2974
2975 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
2976 }
2977
2978 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)2979 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
2980 {
2981 constexpr char kFS[] =
2982 "precision mediump float;\n"
2983 "struct Data { mediump sampler2D data[2]; };\n"
2984 "uniform Data test[2];\n"
2985 "void main() {\n"
2986 " gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
2987 " texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
2988 " texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
2989 " texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
2990 "}\n";
2991
2992 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2993 glUseProgram(program.get());
2994 GLTexture textures[4];
2995 GLColor expected = MakeGLColor(32, 64, 96, 255);
2996 GLubyte data[8] = {}; // 4 bytes of padding, so that texture can be initialized with 4 bytes
2997 memcpy(data, expected.data(), sizeof(expected));
2998 for (int i = 0; i < 4; i++)
2999 {
3000 int outerIdx = i % 2;
3001 int innerIdx = i / 2;
3002 glActiveTexture(GL_TEXTURE0 + i);
3003 glBindTexture(GL_TEXTURE_2D, textures[i]);
3004 // Each element provides two components.
3005 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3006 std::stringstream uniformName;
3007 uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3008 // Then send it as a uniform
3009 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3010 // The uniform should be active.
3011 EXPECT_NE(uniformLocation, -1);
3012
3013 glUniform1i(uniformLocation, 3 - i);
3014 }
3015 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
3016 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3017 }
3018
3019 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3020 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3021 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3022 {
3023 constexpr const char *kFS = R"(
3024 #if __VERSION__ >= 300
3025 inout mediump vec4 fragData;
3026 #else
3027 #extension GL_EXT_shader_texture_lod :enable
3028 #endif
3029
3030 void main()
3031 {
3032 }
3033 )";
3034
3035 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3036 EXPECT_NE(0u, shader);
3037 }
3038
3039 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3040 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3041 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3042 {
3043 constexpr char kVS[] =
3044 "#version 300 es\n"
3045 "precision highp float;\n"
3046 "in vec4 a_vec;\n"
3047 "in mat2 a_mat;\n"
3048 "void main()\n"
3049 "{\n"
3050 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3051 "}";
3052
3053 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3054 EXPECT_NE(0u, program);
3055 }
3056
3057 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3058 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3059 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3060 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3061 {
3062 constexpr char kVS[] =
3063 "#version 300 es\n"
3064 "precision highp float;\n"
3065 "in mat3x2 a_matA;\n"
3066 "in mat2x3 a_matB;\n"
3067 "void main()\n"
3068 "{\n"
3069 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3070 "}";
3071
3072 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3073 EXPECT_NE(0u, program);
3074 }
3075
3076 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3077 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3078 {
3079 constexpr char kVS[] =
3080 "#version 300 es\n"
3081 "precision highp float;\n"
3082 "in vec4 a_vec;\n"
3083 "in mat2 a_mat;\n"
3084 "vec4 foo(vec4 a)\n"
3085 "{\n"
3086 " return a;\n"
3087 "}\n"
3088 "vec4 foo(mat2 a)\n"
3089 "{\n"
3090 " return vec4(a[0][0]);\n"
3091 "}\n"
3092 "void main()\n"
3093 "{\n"
3094 " gl_Position = foo(a_vec) + foo(a_mat);\n"
3095 "}";
3096
3097 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3098 EXPECT_NE(0u, program);
3099 }
3100
3101 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3102 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3103 {
3104 constexpr char kFS[] = R"(#version 300 es
3105 precision highp float;
3106 out vec4 color;
3107
3108 uniform int i;
3109 uniform uint u;
3110 uniform bool b;
3111
3112 void main()
3113 {
3114 mat3x2 mi = mat3x2(i);
3115 mat4 mu = mat4(u);
3116 mat2x4 mb = mat2x4(b);
3117
3118 mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3119
3120 color = vec4(mi[0][0] == float(i) ? 1 : 0,
3121 mu[2][2] == float(u) ? 1 : 0,
3122 mb[1][1] == float(b) ? 1 : 0,
3123 m[0][1] == float(i) && m[1][0] == float(u) && m[2][0] == float(b) ? 1 : 0);
3124 })";
3125
3126 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3127 glUseProgram(program);
3128
3129 GLint iloc = glGetUniformLocation(program, "i");
3130 GLint uloc = glGetUniformLocation(program, "u");
3131 GLint bloc = glGetUniformLocation(program, "b");
3132 ASSERT_NE(iloc, -1);
3133 ASSERT_NE(uloc, -1);
3134 ASSERT_NE(bloc, -1);
3135 glUniform1i(iloc, -123);
3136 glUniform1ui(uloc, 456);
3137 glUniform1ui(bloc, 1);
3138
3139 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3140 EXPECT_GL_NO_ERROR();
3141
3142 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3143 }
3144
3145 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3146 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3147 {
3148 constexpr char kFS[] = R"(#version 300 es
3149 precision highp float;
3150 out vec4 color;
3151
3152 uniform ivec2 i;
3153 uniform uvec2 u;
3154 uniform bvec2 b;
3155
3156 void main()
3157 {
3158 vec2 v2 = vec2(i.x, b);
3159 vec3 v3 = vec3(b, u);
3160 vec4 v4 = vec4(i, u);
3161
3162 color = vec4(v2.x == float(i.x) && v2.y == float(b.x) ? 1 : 0,
3163 v3.x == float(b.x) && v3.y == float(b.y) && v3.z == float(u.x) ? 1 : 0,
3164 v4.x == float(i.x) && v4.y == float(i.y) && v4.z == float(u.x) && v4.w == float(u.y) ? 1 : 0,
3165 1);
3166 })";
3167
3168 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3169 glUseProgram(program);
3170
3171 GLint iloc = glGetUniformLocation(program, "i");
3172 GLint uloc = glGetUniformLocation(program, "u");
3173 GLint bloc = glGetUniformLocation(program, "b");
3174 ASSERT_NE(iloc, -1);
3175 ASSERT_NE(uloc, -1);
3176 ASSERT_NE(bloc, -1);
3177 glUniform2i(iloc, -123, -23);
3178 glUniform2ui(uloc, 456, 76);
3179 glUniform2ui(bloc, 1, 0);
3180
3181 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3182 EXPECT_GL_NO_ERROR();
3183
3184 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3185 }
3186
3187 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3188 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3189 {
3190 constexpr char kFS[] = R"(#version 300 es
3191 precision highp float;
3192 out vec4 color;
3193
3194 uniform float f;
3195
3196 void main()
3197 {
3198 mat4 m = mat4(f);
3199 ivec3 vi = ivec3(m);
3200 uvec2 vu = uvec2(m);
3201 bvec4 vb = bvec4(m);
3202 bvec2 vb2 = bvec2(vi.x, m);
3203
3204 color = vec4(vi.x == int(f) ? 1 : 0,
3205 vu.x == uint(f) ? 1 : 0,
3206 vb.x == bool(f) ? 1 : 0,
3207 vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3208 })";
3209
3210 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3211 glUseProgram(program);
3212
3213 GLint floc = glGetUniformLocation(program, "f");
3214 ASSERT_NE(floc, -1);
3215 glUniform1f(floc, 123);
3216
3217 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3218 EXPECT_GL_NO_ERROR();
3219
3220 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3221 }
3222
3223 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3224 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3225 {
3226 constexpr char kFS[] = R"(#version 300 es
3227 precision highp float;
3228 out vec4 color;
3229
3230 uniform float f;
3231 uniform int i;
3232 uniform uint u;
3233
3234 void main()
3235 {
3236 mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3237 mat3x2 m32_2 = mat3x2(m32_1);
3238 mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3239 mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3240 mat2x3 m23_2 = mat2x3(m23_1);
3241 mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3242 vec2 v2_1 = m32_1[0];
3243 vec2 v2_2 = m32_2[0];
3244 ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3245 ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3246 uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3247 uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3248
3249 color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3250 v2_1 == v2_2 ? 1 : 0,
3251 (v3_1 == v3_2 ? 0.5 : 0.0) +
3252 (v4_1 == v4_2 ? 0.5 : 0.0),
3253 (m32_1 != m32_3 ? 0.125 : 0.0) +
3254 (m23_1 != m23_3 ? 0.125 : 0.0) +
3255 (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3256 (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3257 (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3258 })";
3259
3260 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3261 glUseProgram(program);
3262
3263 GLint floc = glGetUniformLocation(program, "f");
3264 GLint iloc = glGetUniformLocation(program, "i");
3265 GLint uloc = glGetUniformLocation(program, "u");
3266 ASSERT_NE(floc, -1);
3267 ASSERT_NE(iloc, -1);
3268 ASSERT_NE(uloc, -1);
3269 glUniform1f(floc, 1.5);
3270 glUniform1i(iloc, -123);
3271 glUniform1ui(uloc, 456);
3272
3273 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3274 EXPECT_GL_NO_ERROR();
3275
3276 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3277 }
3278
3279 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3280 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3281 {
3282 constexpr char kFS[] = R"(#version 310 es
3283 precision highp float;
3284 out vec4 color;
3285
3286 uniform float f;
3287 uniform int i;
3288 uniform uint u;
3289
3290 struct S
3291 {
3292 float f;
3293 int i;
3294 uint u;
3295 vec4 v;
3296 ivec3 iv;
3297 uvec2 uv;
3298 mat3x2 m32;
3299 mat2x3 m23;
3300 float fa[3][4][5];
3301 int ia[4];
3302 uint ua[6][2];
3303 };
3304
3305 struct T
3306 {
3307 S s1;
3308 S s2[3][2];
3309 };
3310
3311 void main()
3312 {
3313 float fa[5] = float[5](f, f, f, f, f);
3314 int ia[4] = int[4](i, i, i, i);
3315 uint ua[2] = uint[2](u, u);
3316
3317 S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3318 mat3x2(vec2(f), vec2(i), vec2(u)),
3319 mat2x3(vec3(f), vec3(i)),
3320 float[3][4][5](
3321 float[4][5](fa, fa, fa, fa),
3322 float[4][5](fa, fa, fa, fa),
3323 float[4][5](fa, fa, fa, fa)),
3324 ia,
3325 uint[6][2](ua, ua, ua, ua, ua, ua));
3326
3327 S s2[2] = S[2](s1, s1);
3328 s2[1].fa[0][1][2] = float(i);
3329
3330 T t1 = T(s1, S[3][2](s2, s2, s2));
3331 T t2 = T(s2[1], S[3][2](s2, s2, s2));
3332
3333 T ta1[2] = T[2](t1, t2);
3334 T ta2[2] = T[2](t1, t2);
3335 T ta3[2] = T[2](t2, t1);
3336
3337 color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3338 (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3339 (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3340 (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3341 })";
3342
3343 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3344 glUseProgram(program);
3345
3346 GLint floc = glGetUniformLocation(program, "f");
3347 GLint iloc = glGetUniformLocation(program, "i");
3348 GLint uloc = glGetUniformLocation(program, "u");
3349 ASSERT_NE(floc, -1);
3350 ASSERT_NE(iloc, -1);
3351 ASSERT_NE(uloc, -1);
3352 glUniform1f(floc, 1.5);
3353 glUniform1i(iloc, -123);
3354 glUniform1ui(uloc, 456);
3355
3356 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3357 EXPECT_GL_NO_ERROR();
3358
3359 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3360 }
3361
3362 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3363 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3364 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3365 {
3366 std::stringstream vertexShaderStream;
3367 // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3368 const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3369
3370 vertexShaderStream << "#version 300 es\n"
3371 "precision highp float;\n"
3372 "in vec4 a_vec;\n"
3373 "vec4 lotsOfVec4Parameters(";
3374 for (unsigned int i = 0; i < paramCount - 1; ++i)
3375 {
3376 vertexShaderStream << "vec4 a" << i << ", ";
3377 }
3378 vertexShaderStream << "vec4 aLast)\n"
3379 "{\n"
3380 " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3381 for (unsigned int i = 0; i < paramCount - 1; ++i)
3382 {
3383 vertexShaderStream << " sum += a" << i << ";\n";
3384 }
3385 vertexShaderStream << " sum += aLast;\n"
3386 " return sum;\n "
3387 "}\n"
3388 "void main()\n"
3389 "{\n"
3390 " gl_Position = lotsOfVec4Parameters(";
3391 for (unsigned int i = 0; i < paramCount - 1; ++i)
3392 {
3393 vertexShaderStream << "a_vec, ";
3394 }
3395 vertexShaderStream << "a_vec);\n"
3396 "}";
3397
3398 GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3399 EXPECT_NE(0u, program);
3400 }
3401
3402 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3403 // Test a shader where a global constant array is initialized with an expression containing array
3404 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3405 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3406 // Also includes multiple array initializers in one declaration, where only the second one has
3407 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3408 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3409 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3410 {
3411 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
3412 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3413
3414 constexpr char kFS[] =
3415 "#version 300 es\n"
3416 "precision highp float;\n"
3417 "out vec4 my_FragColor;\n"
3418 "const highp float f[2] = float[2](0.1, 0.2);\n"
3419 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3420 "void main()\n"
3421 "{\n"
3422 " my_FragColor = vec4(h[1]);\n"
3423 "}";
3424
3425 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3426 EXPECT_NE(0u, program);
3427 }
3428
3429 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3430 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3431 {
3432 constexpr char kFS[] =
3433 "precision mediump float;\n"
3434 "uniform sampler2D uni[2];\n"
3435 "\n"
3436 "float zero(int x)\n"
3437 "{\n"
3438 " return float(x) - float(x);\n"
3439 "}\n"
3440 "\n"
3441 "void main()\n"
3442 "{\n"
3443 " vec4 c = vec4(0,0,0,0);\n"
3444 " for (int ii = 1; ii < 3; ++ii) {\n"
3445 " if (c.x > 255.0) {\n"
3446 " c.x = 255.0 + zero(ii);\n"
3447 " break;\n"
3448 " }\n"
3449 // Index the sampler array with a predictable loop index (index-constant) as opposed to
3450 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3451 // without an extension.
3452 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3453 " }\n"
3454 " gl_FragColor = c;\n"
3455 "}";
3456
3457 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3458 EXPECT_NE(0u, program);
3459 }
3460
3461 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3462 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3463 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3464 TEST_P(GLSLTest, PragmaDirective)
3465 {
3466 constexpr char kVS[] =
3467 "#pragma STDGL invariant(all)\n"
3468 "void main()\n"
3469 "{\n"
3470 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3471 "}\n";
3472
3473 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3474 EXPECT_NE(0u, program);
3475 }
3476
3477 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3478 // The function call that returns the array needs to be evaluated after ++j for the expression to
3479 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3480 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3481 {
3482 constexpr char kFS[] =
3483 "#version 300 es\n"
3484 "precision mediump float;\n"
3485 "out vec4 my_FragColor; \n"
3486 "int[2] func(int param) {\n"
3487 " return int[2](param, param);\n"
3488 "}\n"
3489 "void main() {\n"
3490 " int a[2]; \n"
3491 " for (int i = 0; i < 2; ++i) {\n"
3492 " a[i] = 1;\n"
3493 " }\n"
3494 " int j = 0; \n"
3495 " bool result = ((++j), (a == func(j)));\n"
3496 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3497 "}\n";
3498
3499 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3500 ASSERT_NE(0u, program);
3501
3502 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3503
3504 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3505 }
3506
3507 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3508 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3509 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3510 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3511 {
3512 constexpr char kFS[] =
3513 "#version 300 es\n"
3514 "precision mediump float;\n"
3515 "out vec4 my_FragColor; \n"
3516 "void main() {\n"
3517 " int j = 0; \n"
3518 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3519 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3520 "}\n";
3521
3522 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3523 ASSERT_NE(0u, program);
3524
3525 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3526
3527 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3528 }
3529
3530 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3531 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3532 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3533 {
3534 constexpr char kFS[] =
3535 "#version 300 es\n"
3536 "precision mediump float;\n"
3537 "out vec4 my_FragColor;\n"
3538 "uniform int u_zero;\n"
3539 "int sideEffectCount = 0;\n"
3540 "float func() {\n"
3541 " ++sideEffectCount;\n"
3542 " return -1.0;\n"
3543 "}\n"
3544 "void main() {\n"
3545 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3546 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3547 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3548 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3549 "}\n";
3550
3551 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3552 ASSERT_NE(0u, program);
3553
3554 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3555
3556 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3557 }
3558
3559 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3560 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3561 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)3562 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3563 {
3564 constexpr char kVS[] =
3565 "attribute vec2 aPosition;\n"
3566 "void main()\n"
3567 "{\n"
3568 " gl_Position = vec4(aPosition, 0, 1);\n"
3569 " gl_PointSize = 1.0;\n"
3570 "}";
3571 constexpr char kFS[] =
3572 "void main()\n"
3573 "{\n"
3574 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3575 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3576 "}";
3577
3578 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3579 drawQuad(prog.get(), "aPosition", 0.5f);
3580 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3581 }
3582
3583 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3584 TEST_P(GLSLTest, NestedPowStatements)
3585 {
3586 // https://crbug.com/1127866 - possible NVIDIA driver issue
3587 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3588
3589 constexpr char kFS[] =
3590 "precision mediump float;\n"
3591 "float func(float v)\n"
3592 "{\n"
3593 " float f1 = pow(v, 2.0);\n"
3594 " return pow(f1 + v, 2.0);\n"
3595 "}\n"
3596 "void main()\n"
3597 "{\n"
3598 " float v = func(2.0);\n"
3599 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3600 "}";
3601
3602 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3603 drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3604 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3605 }
3606
3607 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3608 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3609 {
3610 constexpr char kFS[] =
3611 "#version 300 es\n"
3612 "out highp vec4 o_color;\n"
3613 "void main() {\n"
3614 " highp float f = -1.0;\n"
3615 " // atan(tan(0.5), -f) should be 0.5.\n"
3616 " highp float v = atan(tan(0.5), -f);\n"
3617 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3618 "}\n";
3619
3620 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3621 drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3622 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3623 }
3624
3625 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3626 TEST_P(GLSLTest_ES3, AtanVec2)
3627 {
3628 constexpr char kFS[] =
3629 "#version 300 es\n"
3630 "out highp vec4 o_color;\n"
3631 "void main() {\n"
3632 " highp float f = 1.0;\n"
3633 " // atan(tan(0.5), f) should be 0.5.\n"
3634 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3635 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3636 "vec4(1, 0, 0, 1);\n"
3637 "}\n";
3638
3639 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3640 drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3641 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3642 }
3643
3644 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3645 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3646 {
3647 constexpr char kVS[] =
3648 "#version 300 es\n"
3649 "in highp vec4 position;\n"
3650 "out mediump vec4 v_color;\n"
3651 "uniform int ui_one;\n"
3652 "uniform int ui_two;\n"
3653 "uniform int ui_three;\n"
3654 "void main() {\n"
3655 " int s[3];\n"
3656 " s[0] = ui_one;\n"
3657 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
3658 " s[2] = ui_three;\n"
3659 " int result = 0;\n"
3660 " for (int i = 0; i < ui_three; i++) {\n"
3661 " result += s[i];\n"
3662 " }\n"
3663 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3664 " gl_Position = position;\n"
3665 "}\n";
3666 constexpr char kFS[] =
3667 "#version 300 es\n"
3668 "in mediump vec4 v_color;\n"
3669 "layout(location=0) out mediump vec4 o_color;\n"
3670 "void main() {\n"
3671 " o_color = v_color;\n"
3672 "}\n";
3673
3674 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3675
3676 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3677 ASSERT_NE(-1, oneIndex);
3678 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3679 ASSERT_NE(-1, twoIndex);
3680 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3681 ASSERT_NE(-1, threeIndex);
3682 glUseProgram(prog.get());
3683 glUniform1i(oneIndex, 1);
3684 glUniform1i(twoIndex, 2);
3685 glUniform1i(threeIndex, 3);
3686
3687 drawQuad(prog.get(), "position", 0.5f);
3688 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3689 }
3690
3691 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3692 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3693 {
3694 constexpr char kVS[] =
3695 "#version 300 es\n"
3696 "in highp vec4 position;\n"
3697 "out mediump vec4 v_color;\n"
3698 "uniform uint ui_one;\n"
3699 "uniform uint ui_two;\n"
3700 "uniform uint ui_three;\n"
3701 "void main() {\n"
3702 " uint s[3];\n"
3703 " s[0] = ui_one;\n"
3704 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
3705 " s[2] = ui_three;\n"
3706 " uint result = 0u;\n"
3707 " for (uint i = 0u; i < ui_three; i++) {\n"
3708 " result += s[i];\n"
3709 " }\n"
3710 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3711 " gl_Position = position;\n"
3712 "}\n";
3713 constexpr char kFS[] =
3714 "#version 300 es\n"
3715 "in mediump vec4 v_color;\n"
3716 "layout(location=0) out mediump vec4 o_color;\n"
3717 "void main() {\n"
3718 " o_color = v_color;\n"
3719 "}\n";
3720
3721 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3722
3723 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3724 ASSERT_NE(-1, oneIndex);
3725 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3726 ASSERT_NE(-1, twoIndex);
3727 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3728 ASSERT_NE(-1, threeIndex);
3729 glUseProgram(prog.get());
3730 glUniform1ui(oneIndex, 1u);
3731 glUniform1ui(twoIndex, 2u);
3732 glUniform1ui(threeIndex, 3u);
3733
3734 drawQuad(prog.get(), "position", 0.5f);
3735 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3736 }
3737
3738 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3739 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3740 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3741 {
3742 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3743 // its default value false.
3744 constexpr char kFS[] =
3745 "precision mediump float;\n"
3746 "uniform bool keep_flop_positive;\n"
3747 "float flop;\n"
3748 "void main() {\n"
3749 " flop = -1.0,\n"
3750 " (flop *= -1.0,\n"
3751 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3752 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
3753 "}";
3754
3755 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3756 drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3757 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3758 }
3759
3760 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3761 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3762 {
3763 // Note that the uniform doesn't need to be set, and will contain the default value of false.
3764 constexpr char kFS[] = R"(
3765 precision mediump float;
3766 uniform bool u;
3767 void main()
3768 {
3769 int a = u ? 12345 : 2; // will be 2
3770 int b = u ? 12345 : 4; // will be 4
3771 int c = u ? 12345 : 0; // will be 0
3772
3773 if (a == 2 // true path is taken
3774 ? (b == 3 // false path is taken
3775 ? (a=0) != 0
3776 : b != 0 // true
3777 ) && ( // short-circuit evaluates RHS
3778 (a=7) == 7 // true, modifies a
3779 || // short-circuit doesn't evaluate RHS
3780 (b=8) == 8
3781 )
3782 : (a == 0 && b == 0
3783 ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3784 : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3785 {
3786 c += 15; // will execute
3787 }
3788
3789 // Verify that a is 7, b is 4 and c is 15.
3790 gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3791 })";
3792
3793 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3794 drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3795 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3796 }
3797
3798 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)3799 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
3800 {
3801 constexpr char kFS[] = R"(#version 300 es
3802 precision mediump float;
3803 uniform bvec4 u;
3804 out vec4 color;
3805
3806 bool f(bvec4 bv)
3807 {
3808 return all(bv.xz) && !any(bv.yw);
3809 }
3810
3811 void main() {
3812 color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3813 })";
3814
3815 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3816 glUseProgram(prog);
3817
3818 GLint uloc = glGetUniformLocation(prog, "u");
3819 ASSERT_NE(uloc, -1);
3820 glUniform4ui(uloc, true, false, true, false);
3821
3822 drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3823 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3824 }
3825
3826 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)3827 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
3828 {
3829 constexpr char kCS[] = R"(#version 310 es
3830 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3831 layout(binding = 0, std430) buffer Output {
3832 bvec4 b;
3833 bool valid;
3834 } outbuf;
3835
3836 bool f_in(bvec4 bv)
3837 {
3838 return all(bv.xz) && !any(bv.yw);
3839 }
3840
3841 bool f_inout(inout bvec4 bv)
3842 {
3843 bool ok = all(bv.xz) && !any(bv.yw);
3844 bv.xw = bvec2(false, true);
3845 return ok;
3846 }
3847
3848 void f_out(out bvec4 bv)
3849 {
3850 bv = bvec4(false, true, false, true);
3851 }
3852
3853 void main() {
3854 bool valid = f_in(outbuf.b);
3855 valid = f_inout(outbuf.b) && valid;
3856 f_out(outbuf.b);
3857 outbuf.valid = valid;
3858 })";
3859
3860 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3861 glUseProgram(program);
3862
3863 constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
3864 GLBuffer outputBuffer;
3865 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
3866 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
3867 GL_STATIC_DRAW);
3868 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
3869 EXPECT_GL_NO_ERROR();
3870
3871 glDispatchCompute(1, 1, 1);
3872 EXPECT_GL_NO_ERROR();
3873
3874 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3875
3876 const GLuint *ptr = reinterpret_cast<const GLuint *>(
3877 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
3878 fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
3879 EXPECT_FALSE(ptr[0]);
3880 EXPECT_TRUE(ptr[1]);
3881 EXPECT_FALSE(ptr[2]);
3882 EXPECT_TRUE(ptr[3]);
3883 EXPECT_TRUE(ptr[4]);
3884 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3885 }
3886
3887 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)3888 TEST_P(GLSLTest, ExternalAnd2DSampler)
3889 {
3890 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
3891
3892 constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
3893 precision mediump float;
3894 uniform samplerExternalOES tex0;
3895 uniform sampler2D tex1;
3896 void main(void)
3897 {
3898 vec2 uv = vec2(0.0, 0.0);
3899 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
3900 })";
3901
3902 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3903 }
3904
3905 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)3906 TEST_P(GLSLTest, VaryingMatrixArray)
3907 {
3908 constexpr char kVS[] =
3909 "uniform vec2 u_a1;\n"
3910 "uniform vec2 u_a2;\n"
3911 "attribute vec4 a_position;\n"
3912 "varying mat2 v_mat[2];\n"
3913 "void main() {\n"
3914 " v_mat[0] = mat2(u_a1, u_a2);\n"
3915 " v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
3916 " gl_Position = a_position;\n"
3917 "}";
3918
3919 constexpr char kFS[] =
3920 "precision mediump float;\n"
3921 "varying mat2 v_mat[2];\n"
3922 "void main(void)\n"
3923 "{\n"
3924 " gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
3925 "}";
3926
3927 ANGLE_GL_PROGRAM(program, kVS, kFS);
3928
3929 GLint oneIndex = glGetUniformLocation(program, "u_a1");
3930 ASSERT_NE(-1, oneIndex);
3931 GLint twoIndex = glGetUniformLocation(program, "u_a2");
3932 ASSERT_NE(-1, twoIndex);
3933 glUseProgram(program);
3934 glUniform2f(oneIndex, 1, 0.5f);
3935 glUniform2f(twoIndex, 0.25f, 0.125f);
3936
3937 drawQuad(program, "a_position", 0.5f);
3938 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3939 }
3940
3941 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)3942 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
3943 {
3944 // TODO(anglebug.com/5491): Skipping initial failures so we can set up a passing iOS test bot.
3945 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
3946
3947 constexpr char kVS[] =
3948 "#version 300 es\n"
3949 "uniform vec2 u_a1;\n"
3950 "uniform vec2 u_a2;\n"
3951 "in vec4 a_position;\n"
3952 "centroid out mat3x2 v_mat[2];\n"
3953 "void main() {\n"
3954 " v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
3955 " v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
3956 " gl_Position = a_position;\n"
3957 "}";
3958
3959 constexpr char kFS[] =
3960 "#version 300 es\n"
3961 "precision mediump float;\n"
3962 "centroid in mat3x2 v_mat[2];\n"
3963 "layout(location = 0) out vec4 out_color;\n"
3964 "void main(void)\n"
3965 "{\n"
3966 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
3967 "}";
3968
3969 ANGLE_GL_PROGRAM(program, kVS, kFS);
3970
3971 GLint oneIndex = glGetUniformLocation(program, "u_a1");
3972 ASSERT_NE(-1, oneIndex);
3973 GLint twoIndex = glGetUniformLocation(program, "u_a2");
3974 ASSERT_NE(-1, twoIndex);
3975 glUseProgram(program);
3976 glUniform2f(oneIndex, 1, 0.5f);
3977 glUniform2f(twoIndex, 0.25f, 0.125f);
3978
3979 drawQuad(program, "a_position", 0.5f);
3980 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3981 }
3982
3983 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)3984 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
3985 {
3986 constexpr char kVS[] =
3987 "#version 300 es\n"
3988 "uniform vec2 u_a1;\n"
3989 "uniform vec2 u_a2;\n"
3990 "in vec4 a_position;\n"
3991 "flat out mat2 v_mat[2];\n"
3992 "void main() {\n"
3993 " v_mat[0] = mat2(u_a1, u_a2);\n"
3994 " v_mat[1] = mat2(u_a2, u_a1);\n"
3995 " gl_Position = a_position;\n"
3996 "}";
3997
3998 constexpr char kFS[] =
3999 "#version 300 es\n"
4000 "precision mediump float;\n"
4001 "flat in mat2 v_mat[2];\n"
4002 "layout(location = 0) out vec4 out_color;\n"
4003 "void main(void)\n"
4004 "{\n"
4005 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4006 "}";
4007
4008 ANGLE_GL_PROGRAM(program, kVS, kFS);
4009
4010 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4011 ASSERT_NE(-1, oneIndex);
4012 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4013 ASSERT_NE(-1, twoIndex);
4014 glUseProgram(program);
4015 glUniform2f(oneIndex, 1, 0.5f);
4016 glUniform2f(twoIndex, 0.25f, 0.125f);
4017
4018 drawQuad(program, "a_position", 0.5f);
4019 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4020 }
4021
4022 // Test that literal infinity can be written out from the shader translator.
4023 // 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)4024 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4025 {
4026 constexpr char kFS[] =
4027 "#version 300 es\n"
4028 "precision highp float;\n"
4029 "out vec4 out_color;\n"
4030 "uniform float u;\n"
4031 "void main()\n"
4032 "{\n"
4033 " float infVar = 1.0e40 - u;\n"
4034 " bool correct = isinf(infVar) && infVar > 0.0;\n"
4035 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4036 "}\n";
4037
4038 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4039 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4040 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4041 }
4042
4043 // Test that literal negative infinity can be written out from the shader translator.
4044 // 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)4045 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4046 {
4047 constexpr char kFS[] =
4048 "#version 300 es\n"
4049 "precision highp float;\n"
4050 "out vec4 out_color;\n"
4051 "uniform float u;\n"
4052 "void main()\n"
4053 "{\n"
4054 " float infVar = -1.0e40 + u;\n"
4055 " bool correct = isinf(infVar) && infVar < 0.0;\n"
4056 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4057 "}\n";
4058
4059 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4060 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4061 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4062 }
4063
4064 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4065 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4066 // a unittest for them. Instead we add the tests as end2end so will in particular test
4067 // TranslatorHLSL when run on Windows.
4068
4069 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4070 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4071 {
4072 constexpr char kFS[] = R"(#version 300 es
4073 precision mediump float;
4074 out vec4 color;
4075
4076 uniform float u;
4077 float c = 0.0;
4078 float sideEffect()
4079 {
4080 c = u;
4081 return c;
4082 }
4083
4084 void main(void)
4085 {
4086 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4087 color = vec4(b + c);
4088 })";
4089
4090 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4091 }
4092
4093 // Test that passes splitting multiple declarations and comma operators and for loops are
4094 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4095 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4096 {
4097 constexpr char kFS[] = R"(#version 300 es
4098 precision mediump float;
4099 out vec4 color;
4100
4101 uniform float u;
4102 float c = 0.0;
4103 float sideEffect()
4104 {
4105 c = u;
4106 return c;
4107 }
4108
4109 void main(void)
4110 {
4111 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4112 {
4113 b += 1.0;
4114 color = vec4(b);
4115 }
4116 })";
4117
4118 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4119 }
4120
4121 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4122 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4123 {
4124 constexpr char kFS[] =
4125 "#version 300 es\n"
4126 "precision mediump float;\n"
4127 "out vec4 color;\n"
4128 "void main(void)\n"
4129 "{\n"
4130 " for(float a = 0.0, b = 1.0;; a++)\n"
4131 " {\n"
4132 " b += 1.0;\n"
4133 " if (a > 10.0) {break;}\n"
4134 " color = vec4(b);\n"
4135 " }\n"
4136 "}\n";
4137
4138 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4139 }
4140
4141 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4142 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4143 {
4144 constexpr char kFS[] =
4145 "#version 300 es\n"
4146 "precision mediump float;\n"
4147 "out vec4 color;\n"
4148 "void main(void)\n"
4149 "{\n"
4150 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4151 " {\n"
4152 " b += 1.0;\n"
4153 " a += 1.0;\n"
4154 " color = vec4(b);\n"
4155 " }\n"
4156 "}\n";
4157
4158 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4159 }
4160
4161 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4162 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4163 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4164 {
4165 constexpr char kFS[] =
4166 "#version 300 es\n"
4167 "precision mediump float;\n"
4168 "out vec4 my_FragColor;\n"
4169 "uniform int u_zero;\n"
4170 "void main() {\n"
4171 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4172 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4173 " float f = m[1][1];\n"
4174 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4175 "}\n";
4176
4177 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4178 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4179 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4180 }
4181
4182 class WebGLGLSLTest : public GLSLTest
4183 {
4184 protected:
WebGLGLSLTest()4185 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4186 };
4187
4188 class WebGL2GLSLTest : public GLSLTest
4189 {
4190 protected:
WebGL2GLSLTest()4191 WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4192 };
4193
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4194 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4195 {
4196 GLint maxVaryings = 0;
4197 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4198
4199 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4200 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4201 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4202 }
4203
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4204 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4205 {
4206 GLint maxVaryings = 0;
4207 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4208
4209 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4210 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4211 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4212 }
4213
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4214 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4215 {
4216 GLint maxVaryings = 0;
4217 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4218
4219 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4220 }
4221
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4222 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4223 {
4224 GLint maxVaryings = 0;
4225 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4226
4227 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4228 }
4229
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4230 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4231 {
4232 GLint maxVaryings = 0;
4233 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4234
4235 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4236 }
4237
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4238 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4239 {
4240 GLint maxVaryings = 0;
4241 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4242
4243 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4244 }
4245
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4246 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4247 {
4248 GLint maxVaryings = 0;
4249 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4250
4251 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4252 false);
4253 }
4254
4255 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4256 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4257 {
4258 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4259 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4260
4261 // Failing on N5X Oreo http://anglebug.com/2304
4262 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4263
4264 constexpr char kFS[] =
4265 "#version 310 es\n"
4266 "precision mediump float;\n"
4267 "out vec4 my_FragColor;\n"
4268 "uniform int u_zero;\n"
4269 "void main() {\n"
4270 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4271 " {\n"
4272 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4273 " }\n"
4274 " else\n"
4275 " {\n"
4276 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4277 " }\n"
4278 "}\n";
4279
4280 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4281 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4282 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4283 }
4284
4285 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4286 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4287 {
4288 // http://anglebug.com/1924
4289 ANGLE_SKIP_TEST_IF(IsOpenGL());
4290
4291 // The shader first assigns v.x to v.z (1.0)
4292 // Then v.y to v.y (2.0)
4293 // Then v.z to v.x (1.0)
4294 constexpr char kFS[] =
4295 "#version 300 es\n"
4296 "precision highp float;\n"
4297 "out vec4 my_FragColor;\n"
4298 "void main() {\n"
4299 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
4300 " for (int i = 0; i < 3; i++) {\n"
4301 " v.zyx[i] = v[i];\n"
4302 " }\n"
4303 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4304 "0, 0, 1);\n"
4305 "}\n";
4306
4307 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4308 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4309 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4310 }
4311
4312 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4313 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4314 {
4315 // Crashes on an assertion. The driver reports no atomic counter buffers when queried from the
4316 // program, but ANGLE believes there to be one.
4317 //
4318 // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4319 // the code on which .length() is being called:
4320 //
4321 // _uac1[(_uvalue = _utestSideEffectValue)];
4322 //
4323 // The driver is optimizing the subscription out, and calling the atomic counter inactive. This
4324 // was observed on nvidia, mesa and amd/windows.
4325 //
4326 // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4327 // driver says don't.
4328 //
4329 // http://anglebug.com/3782
4330 ANGLE_SKIP_TEST_IF(IsOpenGL());
4331
4332 constexpr char kCS[] = R"(#version 310 es
4333 precision mediump float;
4334 layout(local_size_x=1) in;
4335
4336 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4337 uniform uint testSideEffectValue;
4338
4339 layout(binding = 1, std140) buffer Result
4340 {
4341 uint value;
4342 } result;
4343
4344 void main() {
4345 bool passed = true;
4346 if (ac1.length() != 2)
4347 {
4348 passed = false;
4349 }
4350 uint value = 0u;
4351 if (ac1[value = testSideEffectValue].length() != 3)
4352 {
4353 passed = false;
4354 }
4355 if (value != testSideEffectValue)
4356 {
4357 passed = false;
4358 }
4359 if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4360 {
4361 passed = false;
4362 }
4363 if (value != testSideEffectValue + 1u)
4364 {
4365 passed = false;
4366 }
4367 result.value = passed ? 255u : 127u;
4368 })";
4369
4370 constexpr unsigned int kUniformTestValue = 17;
4371 constexpr unsigned int kExpectedSuccessValue = 255;
4372 constexpr unsigned int kAtomicCounterRows = 2;
4373 constexpr unsigned int kAtomicCounterCols = 3;
4374
4375 GLint maxAtomicCounters = 0;
4376 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4377 EXPECT_GL_NO_ERROR();
4378
4379 // Required minimum is 8 by the spec
4380 EXPECT_GE(maxAtomicCounters, 8);
4381 ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4382 kAtomicCounterRows * kAtomicCounterCols);
4383
4384 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4385 glUseProgram(program.get());
4386
4387 constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4388 GLBuffer atomicCounterBuffer;
4389 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4390 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4391 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4392
4393 constexpr unsigned int kOutputInitValue = 0;
4394 GLBuffer shaderStorageBuffer;
4395 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4396 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4397 GL_STATIC_DRAW);
4398 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4399
4400 GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4401 EXPECT_NE(uniformLocation, -1);
4402 glUniform1ui(uniformLocation, kUniformTestValue);
4403 EXPECT_GL_NO_ERROR();
4404
4405 glDispatchCompute(1, 1, 1);
4406
4407 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4408
4409 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4410 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4411 EXPECT_EQ(*ptr, kExpectedSuccessValue);
4412 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4413 }
4414
4415 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4416 TEST_P(GLSLTest_ES31, InactiveImages)
4417 {
4418 ANGLE_SKIP_TEST_IF(IsD3D11());
4419
4420 constexpr char kCS[] = R"(#version 310 es
4421 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4422 layout(rgba32ui) uniform highp readonly uimage2D image1;
4423 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4424 void main()
4425 {
4426 })";
4427
4428 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4429
4430 glUseProgram(program.get());
4431 glDispatchCompute(1, 1, 1);
4432 EXPECT_GL_NO_ERROR();
4433
4434 // Verify that the images are indeed inactive.
4435 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4436 EXPECT_GL_NO_ERROR();
4437 EXPECT_EQ(GL_INVALID_INDEX, index);
4438
4439 index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4440 EXPECT_GL_NO_ERROR();
4441 EXPECT_EQ(GL_INVALID_INDEX, index);
4442 }
4443
4444 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4445 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4446 {
4447 constexpr char kCS[] = R"(#version 310 es
4448 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4449 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4450 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4451 void main()
4452 {
4453 })";
4454
4455 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4456
4457 glUseProgram(program.get());
4458 glDispatchCompute(1, 1, 1);
4459 EXPECT_GL_NO_ERROR();
4460
4461 // Verify that the atomic counters are indeed inactive.
4462 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4463 EXPECT_GL_NO_ERROR();
4464 EXPECT_EQ(GL_INVALID_INDEX, index);
4465
4466 index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4467 EXPECT_GL_NO_ERROR();
4468 EXPECT_EQ(GL_INVALID_INDEX, index);
4469 }
4470
4471 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4472 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4473 {
4474 constexpr char kCS[] = R"(#version 310 es
4475 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4476 struct S
4477 {
4478 vec4 v;
4479 sampler2D t[10];
4480 };
4481 uniform S s;
4482 void main()
4483 {
4484 })";
4485
4486 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4487
4488 glUseProgram(program.get());
4489 glDispatchCompute(1, 1, 1);
4490 EXPECT_GL_NO_ERROR();
4491 }
4492
4493 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4494 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4495 {
4496 constexpr char kFS[] =
4497 "#version 310 es\n"
4498 "precision mediump float;\n"
4499 "out vec4 my_FragColor;\n"
4500 "uniform ivec2 test[2][2];\n"
4501 "void main() {\n"
4502 " bool passed = true;\n"
4503 " for (int i = 0; i < 2; i++) {\n"
4504 " for (int j = 0; j < 2; j++) {\n"
4505 " if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4506 " passed = false;\n"
4507 " }\n"
4508 " }\n"
4509 " }\n"
4510 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4511 "}\n";
4512
4513 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4514 glUseProgram(program.get());
4515 for (int i = 0; i < 2; i++)
4516 {
4517 for (int j = 0; j < 2; j++)
4518 {
4519 std::stringstream uniformName;
4520 uniformName << "test[" << i << "][" << j << "]";
4521 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4522 // All array indices should be used.
4523 EXPECT_NE(uniformLocation, -1);
4524 glUniform2i(uniformLocation, i + 1, j + 1);
4525 }
4526 }
4527 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4528 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4529 }
4530
4531 // Test that array indices for arrays of arrays of basic types work as expected
4532 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4533 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4534 {
4535 // anglebug.com/3821 - fails on AMD Windows
4536 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4537 constexpr char kFS[] =
4538 "#version 310 es\n"
4539 "precision mediump float;\n"
4540 "out vec4 my_FragColor;\n"
4541 "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4542 "void main() {\n"
4543 " bool passed = true;\n"
4544 " for (int i = 0; i < 2; i++) {\n"
4545 " for (int j = 0; j < 2; j++) {\n"
4546 " if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4547 " passed = false;\n"
4548 " }\n"
4549 " }\n"
4550 " }\n"
4551 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4552 "}\n";
4553
4554 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4555 glUseProgram(program.get());
4556 // Use interface queries to determine buffer size and offset
4557 GLuint uboBlockIndex = glGetProgramResourceIndex(program.get(), GL_UNIFORM_BLOCK, "UBO");
4558 GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4559 GLint uboDataSize;
4560 glGetProgramResourceiv(program.get(), GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4561 nullptr, &uboDataSize);
4562 std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4563 for (int i = 0; i < 2; i++)
4564 {
4565 std::stringstream resourceName;
4566 resourceName << "UBO.test[" << i << "][0]";
4567 GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4568 struct
4569 {
4570 GLint stride;
4571 GLint offset;
4572 } values;
4573 GLuint resourceIndex =
4574 glGetProgramResourceIndex(program.get(), GL_UNIFORM, resourceName.str().c_str());
4575 ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4576 glGetProgramResourceiv(program.get(), GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2,
4577 nullptr, &values.stride);
4578 for (int j = 0; j < 2; j++)
4579 {
4580 GLint(&dataPtr)[2] =
4581 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4582 dataPtr[0] = i + 1;
4583 dataPtr[1] = j + 1;
4584 }
4585 }
4586 GLBuffer ubo;
4587 glBindBuffer(GL_UNIFORM_BUFFER, ubo.get());
4588 glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4589 GLuint ubo_index = glGetUniformBlockIndex(program.get(), "UBO");
4590 ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4591 glUniformBlockBinding(program.get(), ubo_index, 5);
4592 glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo.get());
4593 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4594 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4595 }
4596
4597 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4598 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4599 {
4600 constexpr char kFS[] =
4601 "#version 310 es\n"
4602 "precision mediump float;\n"
4603 "out vec4 my_FragColor;\n"
4604 "uniform mediump isampler2D test[2][2];\n"
4605 "void main() {\n"
4606 " bool passed = true;\n"
4607 "#define DO_CHECK(i,j) \\\n"
4608 " if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4609 " passed = false; \\\n"
4610 " }\n"
4611 " DO_CHECK(0, 0)\n"
4612 " DO_CHECK(0, 1)\n"
4613 " DO_CHECK(1, 0)\n"
4614 " DO_CHECK(1, 1)\n"
4615 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4616 "}\n";
4617
4618 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4619 glUseProgram(program.get());
4620 GLTexture textures[2][2];
4621 for (int i = 0; i < 2; i++)
4622 {
4623 for (int j = 0; j < 2; j++)
4624 {
4625 // First generate the texture
4626 int textureUnit = i * 2 + j;
4627 glActiveTexture(GL_TEXTURE0 + textureUnit);
4628 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4629 GLint texData[2] = {i + 1, j + 1};
4630 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4631 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4632 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4633 // Then send it as a uniform
4634 std::stringstream uniformName;
4635 uniformName << "test[" << i << "][" << j << "]";
4636 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4637 // All array indices should be used.
4638 EXPECT_NE(uniformLocation, -1);
4639 glUniform1i(uniformLocation, textureUnit);
4640 }
4641 }
4642 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4643 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4644 }
4645
4646 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4647 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4648 {
4649 // http://anglebug.com/5072
4650 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4651
4652 // Fails on D3D due to mistranslation.
4653 ANGLE_SKIP_TEST_IF(IsD3D());
4654
4655 // Fails on Android on GLES.
4656 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4657
4658 GLint maxTextures, maxComputeImageUniforms;
4659 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4660 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4661 ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
4662 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
4663
4664 constexpr char kComputeShader[] = R"(#version 310 es
4665 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4666 layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
4667 layout(binding = 1, std430) buffer Output {
4668 uint image_value;
4669 } outbuf;
4670
4671 void main(void)
4672 {
4673 outbuf.image_value = uint(0.0);
4674 outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
4675 outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
4676 outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
4677 outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
4678 outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
4679 outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
4680 })";
4681 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4682 EXPECT_GL_NO_ERROR();
4683
4684 glUseProgram(program);
4685
4686 GLuint outputInitData[1] = {10};
4687 GLBuffer outputBuffer;
4688 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4689 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
4690 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
4691 EXPECT_GL_NO_ERROR();
4692
4693 GLuint imageData = 200u;
4694 GLTexture images[1][2][3];
4695 for (int i = 0; i < 1; i++)
4696 {
4697 for (int j = 0; j < 2; j++)
4698 {
4699 for (int k = 0; k < 3; k++)
4700 {
4701 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
4702 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4703 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4704 &imageData);
4705 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
4706 GL_R32UI);
4707 EXPECT_GL_NO_ERROR();
4708 }
4709 }
4710 }
4711
4712 glDispatchCompute(1, 1, 1);
4713 EXPECT_GL_NO_ERROR();
4714
4715 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4716
4717 // read back
4718 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4719 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
4720 memcpy(outputInitData, ptr, sizeof(outputInitData));
4721 EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
4722 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4723 }
4724
4725 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)4726 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
4727 {
4728 // http://anglebug.com/5072
4729 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4730
4731 // Fails on D3D due to mistranslation.
4732 ANGLE_SKIP_TEST_IF(IsD3D());
4733
4734 constexpr GLsizei kImage1Layers = 3;
4735 constexpr GLsizei kImage1Rows = 2;
4736 constexpr GLsizei kImage1Cols = 1;
4737 constexpr GLsizei kImage2Rows = 2;
4738 constexpr GLsizei kImage2Cols = 4;
4739
4740 constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
4741 constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
4742 constexpr GLsizei kImage3Units = 1;
4743
4744 constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
4745
4746 GLint maxTextures, maxComputeImageUniforms;
4747 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4748 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4749 ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
4750 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
4751
4752 constexpr char kComputeShader[] = R"(#version 310 es
4753 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4754 layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
4755 layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
4756 layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
4757 layout(binding = 0, std430) buffer Output {
4758 uint image_value;
4759 } outbuf;
4760
4761 void main(void)
4762 {
4763 outbuf.image_value = uint(0.0);
4764
4765 outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
4766 outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
4767 outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
4768 outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
4769 outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
4770 outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
4771
4772 outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
4773 outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
4774 outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
4775 outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
4776 outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
4777 outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
4778 outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
4779 outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
4780
4781 outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
4782 })";
4783 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4784 EXPECT_GL_NO_ERROR();
4785
4786 glUseProgram(program);
4787
4788 constexpr GLuint kOutputInitData = 10;
4789 GLBuffer outputBuffer;
4790 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4791 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
4792 GL_STATIC_DRAW);
4793 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4794 EXPECT_GL_NO_ERROR();
4795
4796 constexpr GLsizei kImage1Binding = 0;
4797 constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
4798 constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
4799
4800 constexpr GLuint kImage1Data = 13;
4801 GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
4802 for (int layer = 0; layer < kImage1Layers; layer++)
4803 {
4804 for (int row = 0; row < kImage1Rows; row++)
4805 {
4806 for (int col = 0; col < kImage1Cols; col++)
4807 {
4808 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
4809 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4810 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4811 &kImage1Data);
4812 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
4813 images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
4814 GL_R32UI);
4815 EXPECT_GL_NO_ERROR();
4816 }
4817 }
4818 }
4819
4820 constexpr GLuint kImage2Data = 17;
4821 GLTexture images2[kImage2Rows][kImage2Cols];
4822 for (int row = 0; row < kImage2Rows; row++)
4823 {
4824 for (int col = 0; col < kImage2Cols; col++)
4825 {
4826 glBindTexture(GL_TEXTURE_2D, images2[row][col]);
4827 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4828 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4829 &kImage2Data);
4830 glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
4831 GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4832 EXPECT_GL_NO_ERROR();
4833 }
4834 }
4835
4836 constexpr GLuint kImage3Data = 19;
4837 GLTexture image3;
4838 glBindTexture(GL_TEXTURE_2D, image3);
4839 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4840 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
4841 glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4842 EXPECT_GL_NO_ERROR();
4843
4844 glDispatchCompute(1, 1, 1);
4845 EXPECT_GL_NO_ERROR();
4846
4847 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4848
4849 // read back
4850 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4851 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4852 EXPECT_EQ(*ptr,
4853 kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
4854 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4855 }
4856
4857 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)4858 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
4859 {
4860 // Skip if GL_OES_shader_image_atomic is not enabled.
4861 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
4862
4863 // http://anglebug.com/5072
4864 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4865
4866 // Fails on D3D due to mistranslation.
4867 ANGLE_SKIP_TEST_IF(IsD3D());
4868
4869 // Fails on Android on GLES.
4870 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4871
4872 // http://anglebug.com/5353
4873 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
4874
4875 GLint maxComputeImageUniforms;
4876 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4877 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
4878
4879 constexpr char kComputeShader[] = R"(#version 310 es
4880 #extension GL_OES_shader_image_atomic : require
4881
4882 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4883 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
4884 layout(binding = 6, r32f) uniform highp image2D image2;
4885
4886 void testFunction(highp image2D imageOut[2][3])
4887 {
4888 // image1 is an array of 1x1 images.
4889 // image2 is a 1x4 image with the following data:
4890 //
4891 // (0, 0): 234.5
4892 // (0, 1): 4.0
4893 // (0, 2): 456.0
4894 // (0, 3): 987.0
4895
4896
4897 // Write to [0][0]
4898 imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
4899
4900 // Write to [0][1]
4901 imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
4902
4903 // Write to [0][2]
4904 imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
4905
4906 // Write to [1][0]
4907 imageStore(imageOut[1][0], ivec2(0,
4908 imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
4909 ), vec4(678.0));
4910
4911 // Write to [1][1]
4912 imageStore(imageOut[1][1], ivec2(0, 0),
4913 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
4914
4915 // Write to [1][2]
4916 imageStore(imageOut[1][2], ivec2(0, 0),
4917 imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
4918 }
4919
4920 void main(void)
4921 {
4922 testFunction(image1);
4923 })";
4924 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4925 EXPECT_GL_NO_ERROR();
4926
4927 glUseProgram(program);
4928
4929 constexpr GLsizei kImageRows = 2;
4930 constexpr GLsizei kImageCols = 3;
4931 constexpr GLfloat kImageData = 0;
4932 GLTexture images[kImageRows][kImageCols];
4933 for (size_t row = 0; row < kImageRows; row++)
4934 {
4935 for (size_t col = 0; col < kImageCols; col++)
4936 {
4937 glBindTexture(GL_TEXTURE_2D, images[row][col]);
4938 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
4939 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
4940 glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
4941 GL_READ_WRITE, GL_R32F);
4942 EXPECT_GL_NO_ERROR();
4943 }
4944 }
4945
4946 constexpr GLsizei kImage2Size = 4;
4947 constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
4948 234.5f,
4949 4.0f,
4950 456.0f,
4951 987.0f,
4952 };
4953 GLTexture image2;
4954 glBindTexture(GL_TEXTURE_2D, image2);
4955 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
4956 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
4957 glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4958 EXPECT_GL_NO_ERROR();
4959
4960 glDispatchCompute(1, 1, 1);
4961 EXPECT_GL_NO_ERROR();
4962
4963 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4964
4965 // Verify the previous dispatch with another dispatch
4966 constexpr char kVerifyShader[] = R"(#version 310 es
4967 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4968 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
4969 layout(binding = 6, r32f) uniform highp readonly image2D image2;
4970 layout(binding = 0, std430) buffer Output {
4971 float image2Data[4];
4972 float image1Data[6];
4973 } outbuf;
4974
4975 void main(void)
4976 {
4977 for (int i = 0; i < 4; ++i)
4978 {
4979 outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
4980 }
4981 outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
4982 outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
4983 outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
4984 outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
4985 outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
4986 outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
4987 })";
4988 ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
4989 EXPECT_GL_NO_ERROR();
4990
4991 glUseProgram(verifyProgram);
4992
4993 constexpr std::array<GLfloat, kImage2Size + kImageRows *kImageCols> kOutputInitData = {};
4994 GLBuffer outputBuffer;
4995 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4996 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4997 GL_STATIC_DRAW);
4998 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4999 EXPECT_GL_NO_ERROR();
5000
5001 glDispatchCompute(1, 1, 1);
5002 EXPECT_GL_NO_ERROR();
5003
5004 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5005
5006 // Verify
5007 const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5008 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5009
5010 EXPECT_EQ(ptr[0], kImage2Data[0]);
5011 EXPECT_EQ(ptr[1], kImage2Data[1]);
5012 EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5013 EXPECT_EQ(ptr[3], kImage2Data[3]);
5014
5015 EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5016 EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5017 EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5018 EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5019 EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5020 EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5021
5022 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5023 }
5024
5025 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5026 TEST_P(GLSLTest_ES31, StructArraySampler)
5027 {
5028 constexpr char kFS[] =
5029 "#version 310 es\n"
5030 "precision mediump float;\n"
5031 "out vec4 my_FragColor;\n"
5032 "struct Data { mediump sampler2D data[2]; };\n"
5033 "uniform Data test;\n"
5034 "void main() {\n"
5035 " my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5036 " texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5037 "}\n";
5038
5039 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5040 glUseProgram(program.get());
5041 GLTexture textures[2];
5042 GLColor expected = MakeGLColor(32, 64, 96, 255);
5043 GLubyte data[6] = {}; // Two bytes of padding, so that texture can be initialized with 4 bytes
5044 memcpy(data, expected.data(), sizeof(expected));
5045 for (int i = 0; i < 2; i++)
5046 {
5047 glActiveTexture(GL_TEXTURE0 + i);
5048 glBindTexture(GL_TEXTURE_2D, textures[i]);
5049 // Each element provides two components.
5050 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5051 std::stringstream uniformName;
5052 uniformName << "test.data[" << i << "]";
5053 // Then send it as a uniform
5054 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5055 // The uniform should be active.
5056 EXPECT_NE(uniformLocation, -1);
5057 glUniform1i(uniformLocation, i);
5058 }
5059 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5060 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5061 }
5062
5063 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5064 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5065 {
5066 constexpr char kFS[] =
5067 "#version 310 es\n"
5068 "precision mediump float;\n"
5069 "out vec4 my_FragColor;\n"
5070 "struct Data { mediump isampler2D data[2][2]; };\n"
5071 "uniform Data test;\n"
5072 "void main() {\n"
5073 " bool passed = true;\n"
5074 "#define DO_CHECK(i,j) \\\n"
5075 " if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5076 " passed = false; \\\n"
5077 " }\n"
5078 " DO_CHECK(0, 0)\n"
5079 " DO_CHECK(0, 1)\n"
5080 " DO_CHECK(1, 0)\n"
5081 " DO_CHECK(1, 1)\n"
5082 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5083 "}\n";
5084
5085 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5086 glUseProgram(program.get());
5087 GLTexture textures[2][2];
5088 for (int i = 0; i < 2; i++)
5089 {
5090 for (int j = 0; j < 2; j++)
5091 {
5092 // First generate the texture
5093 int textureUnit = i * 2 + j;
5094 glActiveTexture(GL_TEXTURE0 + textureUnit);
5095 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5096 GLint texData[2] = {i + 1, j + 1};
5097 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5098 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5099 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5100 // Then send it as a uniform
5101 std::stringstream uniformName;
5102 uniformName << "test.data[" << i << "][" << j << "]";
5103 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5104 // All array indices should be used.
5105 EXPECT_NE(uniformLocation, -1);
5106 glUniform1i(uniformLocation, textureUnit);
5107 }
5108 }
5109 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5110 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5111 }
5112
5113 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5114 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5115 {
5116 GLint numTextures;
5117 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5118 ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5119 constexpr char kFS[] =
5120 "#version 310 es\n"
5121 "precision mediump float;\n"
5122 "out vec4 my_FragColor;\n"
5123 "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5124 "uniform Data test[2];\n"
5125 "void main() {\n"
5126 " bool passed = true;\n"
5127 "#define DO_CHECK_ikl(i,k,l) \\\n"
5128 " if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5129 " passed = false; \\\n"
5130 " } \\\n"
5131 " if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5132 " passed = false; \\\n"
5133 " }\n"
5134 "#define DO_CHECK_ik(i,k) \\\n"
5135 " DO_CHECK_ikl(i, k, 0) \\\n"
5136 " DO_CHECK_ikl(i, k, 1)\n"
5137 "#define DO_CHECK_i(i) \\\n"
5138 " DO_CHECK_ik(i, 0) \\\n"
5139 " DO_CHECK_ik(i, 1)\n"
5140 " DO_CHECK_i(0)\n"
5141 " DO_CHECK_i(1)\n"
5142 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5143 "}\n";
5144
5145 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5146 glUseProgram(program.get());
5147 GLTexture textures[2][2][2][2];
5148 for (int i = 0; i < 2; i++)
5149 {
5150 for (int j = 0; j < 2; j++)
5151 {
5152 for (int k = 0; k < 2; k++)
5153 {
5154 for (int l = 0; l < 2; l++)
5155 {
5156 // First generate the texture
5157 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5158 glActiveTexture(GL_TEXTURE0 + textureUnit);
5159 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5160 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5161 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5162 &texData[0]);
5163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5165 // Then send it as a uniform
5166 std::stringstream uniformName;
5167 uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5168 GLint uniformLocation =
5169 glGetUniformLocation(program.get(), uniformName.str().c_str());
5170 // All array indices should be used.
5171 EXPECT_NE(uniformLocation, -1);
5172 glUniform1i(uniformLocation, textureUnit);
5173 }
5174 }
5175 }
5176 }
5177 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5178 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5179 }
5180
5181 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5182 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5183 {
5184 GLint numTextures;
5185 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5186 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5187 constexpr char kFS[] =
5188 "#version 310 es\n"
5189 "precision mediump float;\n"
5190 "out vec4 my_FragColor;\n"
5191 "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5192 "uniform Data test[2][3];\n"
5193 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5194 "void main() {\n"
5195 " bool passed = true;\n"
5196 "#define DO_CHECK_INNER0(i,j,l) \\\n"
5197 " if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5198 " passed = false; \\\n"
5199 " }\n"
5200 "#define DO_CHECK_INNER1(i,j,l) \\\n"
5201 " if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5202 " passed = false; \\\n"
5203 " }\n"
5204 "#define DO_CHECK(i,j) \\\n"
5205 " DO_CHECK_INNER0(i, j, 0) \\\n"
5206 " DO_CHECK_INNER0(i, j, 1) \\\n"
5207 " DO_CHECK_INNER1(i, j, 0) \\\n"
5208 " DO_CHECK_INNER1(i, j, 1) \\\n"
5209 " DO_CHECK_INNER1(i, j, 2)\n"
5210 " DO_CHECK(0, 0)\n"
5211 " DO_CHECK(0, 1)\n"
5212 " DO_CHECK(0, 2)\n"
5213 " DO_CHECK(1, 0)\n"
5214 " DO_CHECK(1, 1)\n"
5215 " DO_CHECK(1, 2)\n"
5216 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5217 "}\n";
5218
5219 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5220 glUseProgram(program.get());
5221 struct Data
5222 {
5223 GLTexture data1[2];
5224 GLTexture data2[3];
5225 };
5226 Data textures[2][3];
5227 for (int i = 0; i < 2; i++)
5228 {
5229 for (int j = 0; j < 3; j++)
5230 {
5231 GLTexture *arrays[] = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5232 size_t arrayLengths[] = {2, 3};
5233 size_t arrayOffsets[] = {0, 2};
5234 size_t totalArrayLength = 5;
5235 for (int k = 0; k < 2; k++)
5236 {
5237 GLTexture *array = arrays[k];
5238 size_t arrayLength = arrayLengths[k];
5239 size_t arrayOffset = arrayOffsets[k];
5240 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5241 {
5242 // First generate the texture
5243 int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5244 glActiveTexture(GL_TEXTURE0 + textureUnit);
5245 glBindTexture(GL_TEXTURE_2D, array[l]);
5246 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5247 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5248 &texData[0]);
5249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5251 // Then send it as a uniform
5252 std::stringstream uniformName;
5253 uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5254 GLint uniformLocation =
5255 glGetUniformLocation(program.get(), uniformName.str().c_str());
5256 // All array indices should be used.
5257 EXPECT_NE(uniformLocation, -1);
5258 glUniform1i(uniformLocation, textureUnit);
5259 }
5260 }
5261 }
5262 }
5263 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5264 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5265 }
5266
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5267 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5268 {
5269 GLint numTextures;
5270 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5271 ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5272 constexpr char kFS[] =
5273 "#version 310 es\n"
5274 "precision mediump float;\n"
5275 "out vec4 my_FragColor;\n"
5276 "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5277 "uniform Data test[3];\n"
5278 "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5279 "void main() {\n"
5280 " bool passed = true;\n"
5281 "#define DO_CHECK_ik(i,k) \\\n"
5282 " if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5283 " passed = false; \\\n"
5284 " } \\\n"
5285 " if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5286 " passed = false; \\\n"
5287 " }\n"
5288 "#define DO_CHECK_i(i) \\\n"
5289 " DO_CHECK_ik(i, 0) \\\n"
5290 " DO_CHECK_ik(i, 1)\n"
5291 " DO_CHECK_i(0)\n"
5292 " DO_CHECK_i(1)\n"
5293 " DO_CHECK_i(2)\n"
5294 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5295 "}\n";
5296
5297 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5298 glUseProgram(program.get());
5299 GLTexture textures[3][2][2];
5300 for (int i = 0; i < 3; i++)
5301 {
5302 for (int j = 0; j < 2; j++)
5303 {
5304 for (int k = 0; k < 2; k++)
5305 {
5306 // First generate the texture
5307 int textureUnit = k + 2 * (j + 2 * i);
5308 glActiveTexture(GL_TEXTURE0 + textureUnit);
5309 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5310 GLint texData[4] = {i + 1, j + 1, k + 1, 1};
5311 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5312 static_cast<GLubyte>((j + 1) * 64 - 1),
5313 static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5314 if (j == 0)
5315 {
5316 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5317 &texData[0]);
5318 }
5319 else
5320 {
5321 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5322 &texDataFloat[0]);
5323 }
5324 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5326 // Then send it as a uniform
5327 std::stringstream uniformName;
5328 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5329 GLint uniformLocation =
5330 glGetUniformLocation(program.get(), uniformName.str().c_str());
5331 // All array indices should be used.
5332 EXPECT_NE(uniformLocation, -1);
5333 glUniform1i(uniformLocation, textureUnit);
5334 }
5335 }
5336 }
5337 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5338 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5339 }
5340
5341 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5342 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5343 {
5344 // anglebug.com/3832 - no sampler array params on Android
5345 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5346
5347 constexpr char kFS[] =
5348 "#version 310 es\n"
5349 "precision mediump float;\n"
5350 "out vec4 my_FragColor;\n"
5351 "uniform mediump isampler2D test[2][3];\n"
5352 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5353 "\n"
5354 "bool check(mediump isampler2D data[2][3]);\n"
5355 "bool check(mediump isampler2D data[2][3]) {\n"
5356 "#define DO_CHECK(i,j) \\\n"
5357 " if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5358 " return false; \\\n"
5359 " }\n"
5360 " DO_CHECK(0, 0)\n"
5361 " DO_CHECK(0, 1)\n"
5362 " DO_CHECK(0, 2)\n"
5363 " DO_CHECK(1, 0)\n"
5364 " DO_CHECK(1, 1)\n"
5365 " DO_CHECK(1, 2)\n"
5366 " return true;\n"
5367 "}\n"
5368 "void main() {\n"
5369 " bool passed = check(test);\n"
5370 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5371 "}\n";
5372
5373 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5374 glUseProgram(program.get());
5375 GLTexture textures[2][3];
5376 for (int i = 0; i < 2; i++)
5377 {
5378 for (int j = 0; j < 3; j++)
5379 {
5380 // First generate the texture
5381 int textureUnit = i * 3 + j;
5382 glActiveTexture(GL_TEXTURE0 + textureUnit);
5383 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5384 GLint texData[2] = {i + 1, j + 1};
5385 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5387 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5388 // Then send it as a uniform
5389 std::stringstream uniformName;
5390 uniformName << "test[" << i << "][" << j << "]";
5391 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5392 // All array indices should be used.
5393 EXPECT_NE(uniformLocation, -1);
5394 glUniform1i(uniformLocation, textureUnit);
5395 }
5396 }
5397 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5398 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5399 }
5400
5401 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)5402 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
5403 {
5404 // anglebug.com/3832 - no sampler array params on Android
5405 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5406
5407 constexpr char kFS[] =
5408 "#version 310 es\n"
5409 "precision mediump float;\n"
5410 "out vec4 my_FragColor;\n"
5411 "struct Data { mediump isampler2D data[2][3]; };\n"
5412 "uniform Data test;\n"
5413 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5414 "\n"
5415 "bool check(Data data) {\n"
5416 "#define DO_CHECK(i,j) \\\n"
5417 " if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5418 " return false; \\\n"
5419 " }\n"
5420 " DO_CHECK(0, 0)\n"
5421 " DO_CHECK(0, 1)\n"
5422 " DO_CHECK(0, 2)\n"
5423 " DO_CHECK(1, 0)\n"
5424 " DO_CHECK(1, 1)\n"
5425 " DO_CHECK(1, 2)\n"
5426 " return true;\n"
5427 "}\n"
5428 "void main() {\n"
5429 " bool passed = check(test);\n"
5430 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5431 "}\n";
5432
5433 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5434 glUseProgram(program.get());
5435 GLTexture textures[2][3];
5436 for (int i = 0; i < 2; i++)
5437 {
5438 for (int j = 0; j < 3; j++)
5439 {
5440 // First generate the texture
5441 int textureUnit = i * 3 + j;
5442 glActiveTexture(GL_TEXTURE0 + textureUnit);
5443 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5444 GLint texData[2] = {i + 1, j + 1};
5445 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5447 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5448 // Then send it as a uniform
5449 std::stringstream uniformName;
5450 uniformName << "test.data[" << i << "][" << j << "]";
5451 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5452 // All array indices should be used.
5453 EXPECT_NE(uniformLocation, -1);
5454 glUniform1i(uniformLocation, textureUnit);
5455 }
5456 }
5457 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5458 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5459 }
5460
5461 // Test that arrays of arrays of structs with arrays of arrays of samplers
5462 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)5463 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
5464 {
5465 // anglebug.com/3832 - no sampler array params on Android
5466 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5467
5468 GLint numTextures;
5469 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5470 ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
5471 constexpr char kFS[] =
5472 "#version 310 es\n"
5473 "precision mediump float;\n"
5474 "out vec4 my_FragColor;\n"
5475 "struct Data { mediump isampler2D data[2][2]; };\n"
5476 "uniform Data test[3][2];\n"
5477 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5478 "\n"
5479 "bool check(Data data[3][2]) {\n"
5480 "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
5481 " if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
5482 " return false; \\\n"
5483 " }\n"
5484 "#define DO_CHECK_ij(i,j) \\\n"
5485 " DO_CHECK_ijkl(i, j, 0, 0) \\\n"
5486 " DO_CHECK_ijkl(i, j, 0, 1) \\\n"
5487 " DO_CHECK_ijkl(i, j, 1, 0) \\\n"
5488 " DO_CHECK_ijkl(i, j, 1, 1)\n"
5489 " DO_CHECK_ij(0, 0)\n"
5490 " DO_CHECK_ij(1, 0)\n"
5491 " DO_CHECK_ij(2, 0)\n"
5492 " DO_CHECK_ij(0, 1)\n"
5493 " DO_CHECK_ij(1, 1)\n"
5494 " DO_CHECK_ij(2, 1)\n"
5495 " return true;\n"
5496 "}\n"
5497 "void main() {\n"
5498 " bool passed = check(test);\n"
5499 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5500 "}\n";
5501
5502 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5503 glUseProgram(program.get());
5504 GLTexture textures[3][2][2][2];
5505 for (int i = 0; i < 3; i++)
5506 {
5507 for (int j = 0; j < 2; j++)
5508 {
5509 for (int k = 0; k < 2; k++)
5510 {
5511 for (int l = 0; l < 2; l++)
5512 {
5513 // First generate the texture
5514 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5515 glActiveTexture(GL_TEXTURE0 + textureUnit);
5516 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5517 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5518 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5519 &texData[0]);
5520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5521 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5522 // Then send it as a uniform
5523 std::stringstream uniformName;
5524 uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
5525 GLint uniformLocation =
5526 glGetUniformLocation(program.get(), uniformName.str().c_str());
5527 // All array indices should be used.
5528 EXPECT_NE(uniformLocation, -1);
5529 glUniform1i(uniformLocation, textureUnit);
5530 }
5531 }
5532 }
5533 }
5534 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5535 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5536 }
5537
5538 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)5539 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
5540 {
5541 GLint numTextures;
5542 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5543 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
5544
5545 // anglebug.com/3832 - no sampler array params on Android
5546 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5547
5548 // http://anglebug.com/5546
5549 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
5550
5551 constexpr char kFS[] =
5552 "#version 310 es\n"
5553 "precision mediump float;\n"
5554 "out vec4 my_FragColor;\n"
5555 "uniform mediump isampler2D test[2][3][4];\n"
5556 "uniform mediump isampler2D test2[4];\n"
5557 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5558 "\n"
5559 "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
5560 " if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
5561 " if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
5562 " if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
5563 " if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
5564 " return true;\n"
5565 "}\n"
5566 "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
5567 " if (!check1D(arr[0], x, 0)) return false;\n"
5568 " if (!check1D(arr[1], x, 1)) return false;\n"
5569 " if (!check1D(arr[2], x, 2)) return false;\n"
5570 " return true;\n"
5571 "}\n"
5572 "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
5573 " if (!check2D(arr[0], 0)) return false;\n"
5574 " if (!check2D(arr[1], 1)) return false;\n"
5575 " return true;\n"
5576 "}\n"
5577 "void main() {\n"
5578 " bool passed = check3D(test) && check1D(test2, 7, 8);\n"
5579 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5580 "}\n";
5581
5582 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5583 glUseProgram(program.get());
5584 GLTexture textures1[2][3][4];
5585 GLTexture textures2[4];
5586 for (int i = 0; i < 2; i++)
5587 {
5588 for (int j = 0; j < 3; j++)
5589 {
5590 for (int k = 0; k < 4; k++)
5591 {
5592 // First generate the texture
5593 int textureUnit = k + 4 * (j + 3 * i);
5594 glActiveTexture(GL_TEXTURE0 + textureUnit);
5595 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
5596 GLint texData[3] = {i + 1, j + 1, k + 1};
5597 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
5598 &texData[0]);
5599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5600 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5601 // Then send it as a uniform
5602 std::stringstream uniformName;
5603 uniformName << "test[" << i << "][" << j << "][" << k << "]";
5604 GLint uniformLocation =
5605 glGetUniformLocation(program.get(), uniformName.str().c_str());
5606 // All array indices should be used.
5607 EXPECT_NE(uniformLocation, -1);
5608 glUniform1i(uniformLocation, textureUnit);
5609 }
5610 }
5611 }
5612 for (int k = 0; k < 4; k++)
5613 {
5614 // First generate the texture
5615 int textureUnit = 2 * 3 * 4 + k;
5616 glActiveTexture(GL_TEXTURE0 + textureUnit);
5617 glBindTexture(GL_TEXTURE_2D, textures2[k]);
5618 GLint texData[3] = {7 + 1, 8 + 1, k + 1};
5619 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
5620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5621 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5622 // Then send it as a uniform
5623 std::stringstream uniformName;
5624 uniformName << "test2[" << k << "]";
5625 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5626 // All array indices should be used.
5627 EXPECT_NE(uniformLocation, -1);
5628 glUniform1i(uniformLocation, textureUnit);
5629 }
5630 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5631 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5632 }
5633
5634 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)5635 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
5636 {
5637 ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/3604 - rewriter can create name collisions
5638 GLint numTextures;
5639 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5640 ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
5641 // anglebug.com/3832 - no sampler array params on Android
5642 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5643 constexpr char kFS[] =
5644 "#version 310 es\n"
5645 "precision mediump sampler2D;\n"
5646 "precision mediump float;\n"
5647 "uniform sampler2D test_field1_field2[2][2];\n"
5648 "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
5649 "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
5650 "vec4 func1(sampler2D param_field1_field2[2][2],\n"
5651 " int param_field1_field2_offset,\n"
5652 " S1 param_field1,\n"
5653 " S2 param) {\n"
5654 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
5655 "}\n"
5656 "out vec4 my_FragColor;\n"
5657 "void main() {\n"
5658 " my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
5659 " my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
5660 " vec2 uv = vec2(0.0);\n"
5661 " my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
5662 " texture(test_field1.field2[0][0], uv) +\n"
5663 " texture(test.field1_field2[0][0], uv);\n"
5664 "}\n";
5665 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5666 glActiveTexture(GL_TEXTURE0);
5667 GLTexture tex;
5668 glBindTexture(GL_TEXTURE_2D, tex);
5669 GLint zero = 0;
5670 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
5671 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5672 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5673 }
5674
5675 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)5676 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
5677 {
5678 constexpr char kFS[] =
5679 "#version 310 es\n"
5680 "precision mediump sampler2D;\n"
5681 "precision mediump float;\n"
5682 "uniform sampler2D sampler_array[2][2];\n"
5683 "uniform int array[3][2];\n"
5684 "vec4 func1(int param[2],\n"
5685 " int param2[3]) {\n"
5686 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
5687 "}\n"
5688 "out vec4 my_FragColor;\n"
5689 "void main() {\n"
5690 " my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
5691 " my_FragColor += func1(array[1], int[](1, 2, 3));\n"
5692 "}\n";
5693 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5694 glActiveTexture(GL_TEXTURE0);
5695 GLTexture tex;
5696 glBindTexture(GL_TEXTURE_2D, tex);
5697 GLint zero = 0;
5698 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
5699 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5700 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5701 }
5702
5703 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
5704 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)5705 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
5706 {
5707 // This seems to be bugged on some version of Android. Might not affect the newest versions.
5708 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
5709 // Test skipped on Android because of bug with Nexus 5X.
5710 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5711
5712 constexpr char kVS[] =
5713 "#version 300 es\n"
5714 "out vec2 texCoord;\n"
5715 "in vec2 position;\n"
5716 "void main()\n"
5717 "{\n"
5718 " gl_Position = vec4(position, 0, 1);\n"
5719 " texCoord = position * 0.5 + vec2(0.5);\n"
5720 "}\n";
5721
5722 constexpr char kSimpleFS[] =
5723 "#version 300 es\n"
5724 "in mediump vec2 texCoord;\n"
5725 "out mediump vec4 fragColor;\n"
5726 "void main()\n"
5727 "{\n"
5728 " fragColor = vec4(texCoord, 0, 1);\n"
5729 "}\n";
5730
5731 constexpr char kNestedFS[] =
5732 "#version 300 es\n"
5733 "uniform mediump sampler2D samplerA;\n"
5734 "uniform mediump sampler2D samplerB;\n"
5735 "in mediump vec2 texCoord;\n"
5736 "out mediump vec4 fragColor;\n"
5737 "void main ()\n"
5738 "{\n"
5739 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
5740 "}\n";
5741
5742 ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
5743 ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
5744
5745 // Initialize a first texture with default texCoord data.
5746 GLTexture texA;
5747 glActiveTexture(GL_TEXTURE0);
5748 glBindTexture(GL_TEXTURE_2D, texA);
5749 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
5750 GL_UNSIGNED_BYTE, nullptr);
5751 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5752 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5753
5754 GLFramebuffer fbo;
5755 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5756 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
5757
5758 drawQuad(initProg, "position", 0.5f);
5759 ASSERT_GL_NO_ERROR();
5760
5761 // Initialize a second texture with a simple color pattern.
5762 GLTexture texB;
5763 glActiveTexture(GL_TEXTURE1);
5764 glBindTexture(GL_TEXTURE_2D, texB);
5765
5766 std::array<GLColor, 4> simpleColors = {
5767 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5768 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5769 simpleColors.data());
5770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5771 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5772
5773 // Draw with the nested program, using the first texture to index the second.
5774 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5775 glUseProgram(nestedProg);
5776 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
5777 ASSERT_NE(-1, samplerALoc);
5778 glUniform1i(samplerALoc, 0);
5779 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
5780 ASSERT_NE(-1, samplerBLoc);
5781 glUniform1i(samplerBLoc, 1);
5782
5783 drawQuad(nestedProg, "position", 0.5f);
5784 ASSERT_GL_NO_ERROR();
5785
5786 // Compute four texel centers.
5787 Vector2 windowSize(getWindowWidth(), getWindowHeight());
5788 Vector2 quarterWindowSize = windowSize / 4;
5789 Vector2 ul = quarterWindowSize;
5790 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
5791 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
5792 Vector2 lr = windowSize - quarterWindowSize;
5793
5794 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
5795 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
5796 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
5797 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
5798 }
5799
5800 // Tests that using a constant declaration as the only statement in a for loop without curly braces
5801 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)5802 TEST_P(GLSLTest, ConstantStatementInForLoop)
5803 {
5804 constexpr char kVS[] =
5805 "void main()\n"
5806 "{\n"
5807 " for (int i = 0; i < 10; ++i)\n"
5808 " const int b = 0;\n"
5809 "}\n";
5810
5811 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5812 EXPECT_NE(0u, shader);
5813 glDeleteShader(shader);
5814 }
5815
5816 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
5817 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)5818 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
5819 {
5820 constexpr char kVS[] =
5821 "void main()\n"
5822 "{\n"
5823 " for (const int i = 0; i < 0;) {}\n"
5824 "}\n";
5825
5826 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5827 EXPECT_NE(0u, shader);
5828 glDeleteShader(shader);
5829 }
5830
5831 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)5832 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
5833 {
5834 // Test skipped on Android GLES because local variable initialization is disabled.
5835 // http://anglebug.com/2046
5836 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5837
5838 constexpr char kFS[] =
5839 "#version 300 es\n"
5840 "precision mediump float;\n"
5841 "out vec4 my_FragColor;\n"
5842 "int result = 0;\n"
5843 "void main()\n"
5844 "{\n"
5845 " int u;\n"
5846 " result += u;\n"
5847 " int k = 0;\n"
5848 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
5849 " {\n"
5850 " result += j;\n"
5851 " }\n"
5852 " if (result == 2)\n"
5853 " {\n"
5854 " my_FragColor = vec4(0, 1, 0, 1);\n"
5855 " }\n"
5856 " else\n"
5857 " {\n"
5858 " my_FragColor = vec4(1, 0, 0, 1);\n"
5859 " }\n"
5860 "}\n";
5861
5862 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5863
5864 // [WebGL 1.0]
5865 // DrawArrays or drawElements will generate an INVALID_OPERATION error
5866 // if a vertex attribute is enabled as an array via enableVertexAttribArray
5867 // but no buffer is bound to that attribute.
5868 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5869 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5870 }
5871
5872 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
5873 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)5874 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
5875 {
5876 // Test skipped on Android GLES because local variable initialization is disabled.
5877 // http://anglebug.com/2046
5878 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5879
5880 constexpr char kFS[] =
5881 "precision mediump float;\n"
5882 "struct T\n"
5883 "{\n"
5884 " int a[2];\n"
5885 "};\n"
5886 "struct S\n"
5887 "{\n"
5888 " T t[2];\n"
5889 "};\n"
5890 "void main()\n"
5891 "{\n"
5892 " S s;\n"
5893 " S s2;\n"
5894 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
5895 " {\n"
5896 " gl_FragColor = vec4(0, 1, 0, 1);\n"
5897 " }\n"
5898 " else\n"
5899 " {\n"
5900 " gl_FragColor = vec4(1, 0, 0, 1);\n"
5901 " }\n"
5902 "}\n";
5903
5904 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5905 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5906 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5907 }
5908
5909 // Verify that two shaders with the same uniform name and members but different structure names will
5910 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)5911 TEST_P(GLSLTest, StructureNameMatchingTest)
5912 {
5913 const char *vsSource =
5914 "// Structures must have the same name, sequence of type names, and\n"
5915 "// type definitions, and field names to be considered the same type.\n"
5916 "// GLSL 1.017 4.2.4\n"
5917 "precision mediump float;\n"
5918 "struct info {\n"
5919 " vec4 pos;\n"
5920 " vec4 color;\n"
5921 "};\n"
5922 "\n"
5923 "uniform info uni;\n"
5924 "void main()\n"
5925 "{\n"
5926 " gl_Position = uni.pos;\n"
5927 "}\n";
5928
5929 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
5930 ASSERT_NE(0u, vs);
5931 glDeleteShader(vs);
5932
5933 const char *fsSource =
5934 "// Structures must have the same name, sequence of type names, and\n"
5935 "// type definitions, and field names to be considered the same type.\n"
5936 "// GLSL 1.017 4.2.4\n"
5937 "precision mediump float;\n"
5938 "struct info1 {\n"
5939 " vec4 pos;\n"
5940 " vec4 color;\n"
5941 "};\n"
5942 "\n"
5943 "uniform info1 uni;\n"
5944 "void main()\n"
5945 "{\n"
5946 " gl_FragColor = uni.color;\n"
5947 "}\n";
5948
5949 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
5950 ASSERT_NE(0u, fs);
5951 glDeleteShader(fs);
5952
5953 GLuint program = CompileProgram(vsSource, fsSource);
5954 EXPECT_EQ(0u, program);
5955 }
5956
5957 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)5958 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
5959 {
5960 // Test skipped on Android GLES because local variable initialization is disabled.
5961 // http://anglebug.com/2046
5962 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5963
5964 constexpr char kFS[] =
5965 "#version 300 es\n"
5966 "precision highp float;\n"
5967 "out vec4 my_FragColor;\n"
5968 "void main()\n"
5969 "{\n"
5970 " my_FragColor = vec4(1, 0, 0, 1);\n"
5971 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
5972 " my_FragColor = vec4(0, 1, 0, 1);\n"
5973 " }\n"
5974 "}\n";
5975
5976 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5977 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5978 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5979 }
5980
5981 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)5982 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
5983 {
5984 // http://anglebug.com/2862
5985 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
5986
5987 constexpr char kFS[] =
5988 "precision mediump float;\n"
5989 "int result;\n"
5990 "int i[2], j = i[0] + 1;\n"
5991 "void main()\n"
5992 "{\n"
5993 " result += j;\n"
5994 " if (result == 1)\n"
5995 " {\n"
5996 " gl_FragColor = vec4(0, 1, 0, 1);\n"
5997 " }\n"
5998 " else\n"
5999 " {\n"
6000 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6001 " }\n"
6002 "}\n";
6003
6004 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6005 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6006 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6007 }
6008
6009 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6010 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6011 {
6012 constexpr char kFS[] =
6013 "precision mediump float;\n"
6014 "struct { float q; } b;\n"
6015 "void main()\n"
6016 "{\n"
6017 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6018 " if (b.q == 0.0)\n"
6019 " {\n"
6020 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6021 " }\n"
6022 "}\n";
6023
6024 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6025 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6026 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6027 }
6028
6029 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6030 TEST_P(GLSLTest, EmbeddedStructUniform)
6031 {
6032 const char kFragmentShader[] = R"(precision mediump float;
6033 uniform struct { float q; } b;
6034 void main()
6035 {
6036 gl_FragColor = vec4(1, 0, 0, 1);
6037 if (b.q == 0.5)
6038 {
6039 gl_FragColor = vec4(0, 1, 0, 1);
6040 }
6041 })";
6042
6043 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6044 glUseProgram(program);
6045 GLint uniLoc = glGetUniformLocation(program, "b.q");
6046 ASSERT_NE(-1, uniLoc);
6047 glUniform1f(uniLoc, 0.5f);
6048
6049 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6050 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6051 }
6052
6053 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6054 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6055 {
6056 const char kFragmentShader[] = R"(precision mediump float;
6057 uniform struct { float q; } b[2];
6058 void main()
6059 {
6060 gl_FragColor = vec4(1, 0, 0, 1);
6061 if (b[0].q == 0.5)
6062 {
6063 gl_FragColor = vec4(0, 1, 0, 1);
6064 }
6065 })";
6066
6067 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6068 glUseProgram(program);
6069 GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6070 ASSERT_NE(-1, uniLoc);
6071 glUniform1f(uniLoc, 0.5f);
6072
6073 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6074 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6075 }
6076
6077 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6078 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6079 {
6080 const char kVertexShader[] = R"(attribute vec2 position;
6081 varying vec2 texCoord;
6082 void main()
6083 {
6084 gl_Position = vec4(position, 0, 1);
6085 texCoord = position * 0.5 + vec2(0.5);
6086 })";
6087
6088 const char kFragmentShader[] = R"(precision mediump float;
6089 struct S { sampler2D samp; bool b; };
6090 uniform S uni;
6091 varying vec2 texCoord;
6092 void main()
6093 {
6094 if (uni.b)
6095 {
6096 gl_FragColor = texture2D(uni.samp, texCoord);
6097 }
6098 else
6099 {
6100 gl_FragColor = vec4(1, 0, 0, 1);
6101 }
6102 })";
6103
6104 ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6105 glUseProgram(program);
6106
6107 GLint bLoc = glGetUniformLocation(program, "uni.b");
6108 ASSERT_NE(-1, bLoc);
6109 GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6110 ASSERT_NE(-1, sampLoc);
6111
6112 glUniform1i(bLoc, 1);
6113
6114 std::array<GLColor, 4> kGreenPixels = {
6115 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6116
6117 GLTexture tex;
6118 glBindTexture(GL_TEXTURE_2D, tex);
6119 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6120 kGreenPixels.data());
6121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6123 ASSERT_GL_NO_ERROR();
6124
6125 drawQuad(program, "position", 0.5f);
6126 ASSERT_GL_NO_ERROR();
6127
6128 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6129 }
6130
6131 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6132 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6133 {
6134 const char kFragmentShader[] = R"(precision mediump float;
6135 uniform struct { float q; } b, c;
6136 void main()
6137 {
6138 gl_FragColor = vec4(1, 0, 0, 1);
6139 if (b.q == 0.5 && c.q == 1.0)
6140 {
6141 gl_FragColor = vec4(0, 1, 0, 1);
6142 }
6143 })";
6144
6145 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6146 glUseProgram(program);
6147
6148 GLint uniLocB = glGetUniformLocation(program, "b.q");
6149 ASSERT_NE(-1, uniLocB);
6150 glUniform1f(uniLocB, 0.5f);
6151
6152 GLint uniLocC = glGetUniformLocation(program, "c.q");
6153 ASSERT_NE(-1, uniLocC);
6154 glUniform1f(uniLocC, 1.0f);
6155
6156 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6157 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6158 }
6159
6160 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6161 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6162 {
6163 constexpr char kFS[] =
6164 "#version 300 es\n"
6165 "precision highp float;\n"
6166 "out vec4 my_FragColor;\n"
6167 "void main()\n"
6168 "{\n"
6169 " float i = 0.0;\n"
6170 " while (bool foo = (i < 1.5))\n"
6171 " {\n"
6172 " if (!foo)\n"
6173 " {\n"
6174 " ++i;\n"
6175 " }\n"
6176 " if (i > 3.5)\n"
6177 " {\n"
6178 " break;\n"
6179 " }\n"
6180 " ++i;\n"
6181 " }\n"
6182 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6183 "}\n";
6184
6185 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6186 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6187 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6188 }
6189
6190 // Test that a variable hides a user-defined function with the same name after its initializer.
6191 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6192 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6193 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6194 {
6195 constexpr char kFS[] =
6196 "precision mediump float;\n"
6197 "uniform vec4 u;\n"
6198 "vec4 foo()\n"
6199 "{\n"
6200 " return u;\n"
6201 "}\n"
6202 "void main()\n"
6203 "{\n"
6204 " vec4 foo = foo();\n"
6205 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6206 "}\n";
6207
6208 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6209 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
6210 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6211 }
6212
6213 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6214 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6215 {
6216 constexpr char kFS[] =
6217 "precision mediump float;\n"
6218 "uniform float u_zero;\n"
6219 "struct S { float foo; };\n"
6220 "struct S2 { float foo; };\n"
6221 "float get(S s) { return s.foo + u_zero; }\n"
6222 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
6223 "void main()\n"
6224 "{\n"
6225 " S s;\n"
6226 " s.foo = 0.5;\n"
6227 " S2 s2;\n"
6228 " s2.foo = 0.25;\n"
6229 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
6230 "}\n";
6231
6232 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6233 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
6234 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6235 }
6236
6237 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
6238 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)6239 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
6240 {
6241 // http://anglebug.com/4820
6242 ANGLE_SKIP_TEST_IF((IsOSX() && IsOpenGL()) || (IsIOS() && IsOpenGLES()));
6243
6244 constexpr char kVS[] =
6245 "attribute vec4 inputAttribute;\n"
6246 "varying vec4 varColor;\n"
6247 "void main()\n"
6248 "{\n"
6249 " gl_Position = inputAttribute;\n"
6250 "}\n";
6251
6252 constexpr char kFS[] =
6253 "precision mediump float;\n"
6254 "varying vec4 varColor;\n"
6255 "void main()\n"
6256 "{\n"
6257 " gl_FragColor = varColor;\n"
6258 "}\n";
6259
6260 ANGLE_GL_PROGRAM(program, kVS, kFS);
6261 drawQuad(program.get(), "inputAttribute", 0.5f);
6262 ASSERT_GL_NO_ERROR();
6263 }
6264
6265 // Test that a varying struct that's not statically used in the fragment shader works.
6266 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)6267 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
6268 {
6269 constexpr char kVS[] =
6270 "#version 300 es\n"
6271 "struct S {\n"
6272 " vec4 field;\n"
6273 "};\n"
6274 "out S varStruct;\n"
6275 "void main()\n"
6276 "{\n"
6277 " gl_Position = vec4(1.0);\n"
6278 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
6279 "}\n";
6280
6281 constexpr char kFS[] =
6282 "#version 300 es\n"
6283 "precision mediump float;\n"
6284 "struct S {\n"
6285 " vec4 field;\n"
6286 "};\n"
6287 "in S varStruct;\n"
6288 "out vec4 col;\n"
6289 "void main()\n"
6290 "{\n"
6291 " col = vec4(1.0);\n"
6292 "}\n";
6293
6294 ANGLE_GL_PROGRAM(program, kVS, kFS);
6295 }
6296
6297 // Test that a shader IO block varying that's not declared in the fragment shader links
6298 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)6299 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
6300 {
6301 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
6302
6303 constexpr char kVS[] =
6304 R"(#version 310 es
6305 #extension GL_EXT_shader_io_blocks : require
6306
6307 precision highp float;
6308 in vec4 inputAttribute;
6309 out Block_inout { vec4 value; } user_out;
6310
6311 void main()
6312 {
6313 gl_Position = inputAttribute;
6314 user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
6315 })";
6316
6317 constexpr char kFS[] =
6318 R"(#version 310 es
6319 #extension GL_EXT_shader_io_blocks : require
6320
6321 precision highp float;
6322 layout(location = 0) out mediump vec4 color;
6323 void main()
6324 {
6325 color = vec4(1, 0, 0, 1);
6326 })";
6327
6328 ANGLE_GL_PROGRAM(program, kVS, kFS);
6329 drawQuad(program.get(), "inputAttribute", 0.5f);
6330 ASSERT_GL_NO_ERROR();
6331
6332 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6333 }
6334
6335 // Test that a shader IO block varying that's not declared in the vertex shader links
6336 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)6337 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
6338 {
6339 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
6340
6341 constexpr char kVS[] =
6342 R"(#version 310 es
6343 #extension GL_EXT_shader_io_blocks : require
6344
6345 precision highp float;
6346 in vec4 inputAttribute;
6347
6348 void main()
6349 {
6350 gl_Position = inputAttribute;
6351 })";
6352
6353 constexpr char kFS[] =
6354 R"(#version 310 es
6355 #extension GL_EXT_shader_io_blocks : require
6356
6357 precision highp float;
6358 in Block_inout { vec4 value; } user_in;
6359 layout(location = 0) out mediump vec4 color;
6360
6361 void main()
6362 {
6363 color = vec4(1, 0, 0, 1);
6364 })";
6365
6366 ANGLE_GL_PROGRAM(program, kVS, kFS);
6367 drawQuad(program.get(), "inputAttribute", 0.5f);
6368 ASSERT_GL_NO_ERROR();
6369
6370 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6371 }
6372
6373 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)6374 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
6375 {
6376 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
6377 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
6378
6379 constexpr char kVS[] =
6380 R"(#version 310 es
6381 #extension GL_OES_shader_multisample_interpolation : require
6382
6383 precision highp float;
6384 in vec4 inputAttribute;
6385
6386 sample out mediump float tc_in;
6387 void main()
6388 {
6389 tc_in = inputAttribute[0];
6390 gl_Position = inputAttribute;
6391 })";
6392
6393 constexpr char kTCS[] =
6394 R"(#version 310 es
6395 #extension GL_EXT_tessellation_shader : require
6396 #extension GL_OES_shader_multisample_interpolation : require
6397 layout (vertices=3) out;
6398
6399 sample in mediump float tc_in[];
6400 sample out mediump float tc_out[];
6401 void main()
6402 {
6403 tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
6404 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
6405 gl_TessLevelInner[0] = 2.0;
6406 gl_TessLevelInner[1] = 2.0;
6407 gl_TessLevelOuter[0] = 2.0;
6408 gl_TessLevelOuter[1] = 2.0;
6409 gl_TessLevelOuter[2] = 2.0;
6410 gl_TessLevelOuter[3] = 2.0;
6411 })";
6412
6413 constexpr char kTES[] =
6414 R"(#version 310 es
6415 #extension GL_EXT_tessellation_shader : require
6416 #extension GL_OES_shader_multisample_interpolation : require
6417 layout (triangles) in;
6418
6419 sample in mediump float tc_out[];
6420 sample out mediump float te_out;
6421 void main()
6422 {
6423 te_out = tc_out[2];
6424 gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
6425 })";
6426
6427 constexpr char kFS[] =
6428 R"(#version 310 es
6429 #extension GL_OES_shader_multisample_interpolation : require
6430
6431 precision highp float;
6432 sample in mediump float te_out;
6433 layout(location = 0) out mediump vec4 color;
6434
6435 void main()
6436 {
6437 float out0 = te_out;
6438 color = vec4(1, 0, 0, 1);
6439 })";
6440
6441 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
6442 drawPatches(program.get(), "inputAttribute", 0.5f, 1.0f, GL_FALSE);
6443 ASSERT_GL_NO_ERROR();
6444 }
6445
6446 // Test that a shader with sample in / sample out can be used successfully when the varying
6447 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)6448 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
6449 {
6450 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
6451
6452 constexpr char kVS[] =
6453 R"(#version 310 es
6454 #extension GL_OES_shader_multisample_interpolation : require
6455
6456 precision highp float;
6457 in vec4 inputAttribute;
6458
6459 sample out highp float v;
6460 void main()
6461 {
6462 v = inputAttribute[0];
6463 gl_Position = inputAttribute;
6464 })";
6465
6466 constexpr char kFS[] =
6467 R"(#version 310 es
6468 #extension GL_OES_shader_multisample_interpolation : require
6469
6470 precision highp float;
6471 sample in mediump float v;
6472 layout(location = 0) out mediump vec4 color;
6473
6474 void main()
6475 {
6476 color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
6477 })";
6478
6479 ANGLE_GL_PROGRAM(program, kVS, kFS);
6480 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, GL_FALSE);
6481 ASSERT_GL_NO_ERROR();
6482
6483 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
6484 }
6485
6486 // Test that a varying struct that's not declared in the fragment shader links successfully.
6487 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)6488 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
6489 {
6490 constexpr char kVS[] =
6491 "#version 300 es\n"
6492 "struct S {\n"
6493 " vec4 field;\n"
6494 "};\n"
6495 "out S varStruct;\n"
6496 "void main()\n"
6497 "{\n"
6498 " gl_Position = vec4(1.0);\n"
6499 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
6500 "}\n";
6501
6502 constexpr char kFS[] =
6503 "#version 300 es\n"
6504 "precision mediump float;\n"
6505 "out vec4 col;\n"
6506 "void main()\n"
6507 "{\n"
6508 " col = vec4(1.0);\n"
6509 "}\n";
6510
6511 ANGLE_GL_PROGRAM(program, kVS, kFS);
6512 }
6513
6514 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
6515 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)6516 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
6517 {
6518 // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
6519 // going to use it. See section 9.1 in
6520 // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
6521 // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
6522 //
6523 // However, nvidia OpenGL ES drivers fail to link this program.
6524 //
6525 // http://anglebug.com/3413
6526 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
6527
6528 constexpr char kVS[] =
6529 "#version 300 es\n"
6530 "void main()\n"
6531 "{\n"
6532 " gl_Position = vec4(1.0);\n"
6533 "}\n";
6534
6535 constexpr char kFS[] =
6536 "#version 300 es\n"
6537 "precision mediump float;\n"
6538 "out vec4 col;\n"
6539 "struct S {\n"
6540 " vec4 field;\n"
6541 "};\n"
6542 "in S varStruct;\n"
6543 "void main()\n"
6544 "{\n"
6545 " col = vec4(1.0);\n"
6546 "}\n";
6547
6548 ANGLE_GL_PROGRAM(program, kVS, kFS);
6549 }
6550
6551 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)6552 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
6553 {
6554 // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
6555 // specification that the varying values are undefined in the fragment stage). See section 9.1
6556 // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
6557 // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
6558 //
6559 // However, windows and mac OpenGL drivers fail to link this program. With a message like:
6560 //
6561 // > Input of fragment shader 'varStruct' not written by vertex shader
6562 //
6563 // http://anglebug.com/3413
6564 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || (IsWindows() && !IsNVIDIA())));
6565 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
6566 // struct member. Not sure if it's being overly strict.
6567 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6568
6569 constexpr char kVS[] =
6570 "#version 300 es\n"
6571 "struct S {\n"
6572 " vec4 field;\n"
6573 "};\n"
6574 "out S varStruct;\n"
6575 "void main()\n"
6576 "{\n"
6577 " gl_Position = vec4(1.0);\n"
6578 "}\n";
6579
6580 constexpr char kFS[] =
6581 "#version 300 es\n"
6582 "precision mediump float;\n"
6583 "out vec4 col;\n"
6584 "struct S {\n"
6585 " vec4 field;\n"
6586 "};\n"
6587 "in S varStruct;\n"
6588 "void main()\n"
6589 "{\n"
6590 " col = varStruct.field;\n"
6591 "}\n";
6592
6593 ANGLE_GL_PROGRAM(program, kVS, kFS);
6594 }
6595
6596 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)6597 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
6598 {
6599 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
6600 // struct member. Not sure if it's being overly strict.
6601 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6602 constexpr char kVS[] =
6603 "#version 300 es\n"
6604 "in vec4 inputAttribute;\n"
6605 "struct S {\n"
6606 " vec4 field;\n"
6607 "};\n"
6608 "out S varStruct;\n"
6609 "out S varStruct2;\n"
6610 "void main()\n"
6611 "{\n"
6612 " gl_Position = inputAttribute;\n"
6613 " varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
6614 " varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
6615 "}\n";
6616
6617 constexpr char kFS[] =
6618 "#version 300 es\n"
6619 "precision mediump float;\n"
6620 "out vec4 col;\n"
6621 "struct S {\n"
6622 " vec4 field;\n"
6623 "};\n"
6624 "in S varStruct;\n"
6625 "in S varStruct2;\n"
6626 "void main()\n"
6627 "{\n"
6628 " col = varStruct.field + varStruct2.field;\n"
6629 "}\n";
6630
6631 ANGLE_GL_PROGRAM(program, kVS, kFS);
6632 drawQuad(program.get(), "inputAttribute", 0.5f);
6633 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6634 }
6635
6636 // This is a regression test to make sure a red quad is rendered without issues
6637 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)6638 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
6639 {
6640 constexpr char kVS[] =
6641 "precision mediump float;\n"
6642 "attribute vec4 inputAttribute;\n"
6643 "varying mediump vec2 texCoord;\n"
6644 "void main() {\n"
6645 " texCoord = inputAttribute.xy;\n"
6646 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
6647 "}\n";
6648
6649 constexpr char kFS[] =
6650 "precision mediump float;\n"
6651 "varying mediump vec2 texCoord;\n"
6652 "uniform sampler2D testSampler;\n"
6653 "vec3 passthrough(vec3 c) {\n"
6654 " return c;\n"
6655 "}\n"
6656 "void main() {\n"
6657 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
6658 "}\n";
6659 ANGLE_GL_PROGRAM(program, kVS, kFS);
6660
6661 // Initialize basic red texture.
6662 GLTexture texture;
6663 glBindTexture(GL_TEXTURE_2D, texture);
6664 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6665 GLColor::red.data());
6666 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6668 ASSERT_GL_NO_ERROR();
6669
6670 drawQuad(program.get(), "inputAttribute", 0.5f);
6671 ASSERT_GL_NO_ERROR();
6672 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6673 }
6674
6675 // This is a regression test to make sure a red quad is rendered without issues
6676 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)6677 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
6678 {
6679 constexpr char kVS[] =
6680 "precision mediump float;\n"
6681 "attribute vec4 inputAttribute;\n"
6682 "varying mediump vec2 texCoord;\n"
6683 "void main() {\n"
6684 " texCoord = inputAttribute.xy;\n"
6685 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
6686 "}\n";
6687
6688 constexpr char kFS[] =
6689 "precision mediump float;\n"
6690 "varying mediump vec2 texCoord;\n"
6691 "uniform sampler2D testSampler;\n"
6692 "vec4 passthrough(vec4 c) {\n"
6693 " return c;\n"
6694 "}\n"
6695 "void main() {\n"
6696 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
6697 "}\n";
6698 ANGLE_GL_PROGRAM(program, kVS, kFS);
6699
6700 // Initialize basic red texture.
6701 GLTexture texture;
6702 glBindTexture(GL_TEXTURE_2D, texture);
6703 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6704 GLColor::red.data());
6705 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6706 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6707 ASSERT_GL_NO_ERROR();
6708
6709 drawQuad(program.get(), "inputAttribute", 0.5f);
6710 ASSERT_GL_NO_ERROR();
6711 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6712 }
6713
6714 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)6715 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
6716 {
6717 // TODO(syoussefi): fails on android with:
6718 //
6719 // > Internal Vulkan error: A return array was too small for the result
6720 //
6721 // http://anglebug.com/3220
6722 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
6723 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
6724 // struct members. Not sure if it's being overly strict.
6725 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6726
6727 constexpr char kVS[] =
6728 "#version 300 es\n"
6729 "in vec4 inputAttribute;\n"
6730 "struct S {\n"
6731 " vec4 field1;\n"
6732 " vec4 field2;\n"
6733 "};\n"
6734 "out S varStruct;\n"
6735 "out S varStruct2;\n"
6736 "void main()\n"
6737 "{\n"
6738 " gl_Position = inputAttribute;\n"
6739 " varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6740 " varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6741 " varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6742 " varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6743 "}\n";
6744
6745 constexpr char kFS[] =
6746 "#version 300 es\n"
6747 "precision mediump float;\n"
6748 "out vec4 col;\n"
6749 "struct S {\n"
6750 " vec4 field1;\n"
6751 " vec4 field2;\n"
6752 "};\n"
6753 "in S varStruct;\n"
6754 "in S varStruct2;\n"
6755 "void main()\n"
6756 "{\n"
6757 " col = varStruct.field1 + varStruct2.field2;\n"
6758 "}\n";
6759
6760 ANGLE_GL_PROGRAM(program, kVS, kFS);
6761 drawQuad(program.get(), "inputAttribute", 0.5f);
6762 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6763 }
6764
6765 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)6766 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
6767 {
6768 constexpr char kVS[] =
6769 "#version 300 es\n"
6770 "in vec4 inputAttribute;\n"
6771 "out vec4 varArray[4];\n"
6772 "void main()\n"
6773 "{\n"
6774 " gl_Position = inputAttribute;\n"
6775 " varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
6776 " varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
6777 " varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
6778 " varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
6779 "}\n";
6780
6781 constexpr char kFS[] =
6782 "#version 300 es\n"
6783 "precision mediump float;\n"
6784 "out vec4 col;\n"
6785 "void main()\n"
6786 "{\n"
6787 " col = vec4(0.0, 0.0, 0.0, 1.0);\n"
6788 "}\n";
6789
6790 ANGLE_GL_PROGRAM(program, kVS, kFS);
6791 drawQuad(program.get(), "inputAttribute", 0.5f);
6792 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6793 }
6794
6795 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)6796 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
6797 {
6798 constexpr char kVS[] =
6799 "#version 300 es\n"
6800 "in vec4 inputAttribute;\n"
6801 "struct S {\n"
6802 " vec4 field;\n"
6803 "};\n"
6804 "out S varStruct;\n"
6805 "out S varStruct2;\n"
6806 "void main()\n"
6807 "{\n"
6808 " gl_Position = inputAttribute;\n"
6809 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6810 " varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6811 "}\n";
6812
6813 constexpr char kFS[] =
6814 "#version 300 es\n"
6815 "precision mediump float;\n"
6816 "out vec4 col;\n"
6817 "struct S {\n"
6818 " vec4 field;\n"
6819 "};\n"
6820 "in S varStruct;\n"
6821 "in S varStruct2;\n"
6822 "void main()\n"
6823 "{\n"
6824 " col = varStruct.field;\n"
6825 "}\n";
6826
6827 ANGLE_GL_PROGRAM(program, kVS, kFS);
6828 drawQuad(program.get(), "inputAttribute", 0.5f);
6829 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6830 }
6831
6832 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)6833 TEST_P(GLSLTest_ES3, VaryingMatrices)
6834 {
6835 constexpr char kVS[] =
6836 "#version 300 es\n"
6837 "in vec4 inputAttribute;\n"
6838 "out mat2x2 varMat;\n"
6839 "out mat2x2 varMat2;\n"
6840 "out mat4x3 varMat3;\n"
6841 "void main()\n"
6842 "{\n"
6843 " gl_Position = inputAttribute;\n"
6844 " varMat[0] = vec2(1, 1);\n"
6845 " varMat[1] = vec2(1, 1);\n"
6846 " varMat2[0] = vec2(0.5, 0.5);\n"
6847 " varMat2[1] = vec2(0.5, 0.5);\n"
6848 " varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
6849 " varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
6850 " varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
6851 " varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
6852 "}\n";
6853
6854 constexpr char kFS[] =
6855 "#version 300 es\n"
6856 "precision mediump float;\n"
6857 "out vec4 col;\n"
6858 "in mat2x2 varMat;\n"
6859 "in mat2x2 varMat2;\n"
6860 "in mat4x3 varMat3;\n"
6861 "void main()\n"
6862 "{\n"
6863 " col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
6864 "}\n";
6865
6866 ANGLE_GL_PROGRAM(program, kVS, kFS);
6867 drawQuad(program.get(), "inputAttribute", 0.5f);
6868 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
6869 }
6870
6871 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)6872 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
6873 {
6874 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6875 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6876
6877 const char kFragmentShader[] = R"(precision mediump float;
6878 struct S { sampler2D samplerMember; };
6879 uniform S uStruct;
6880 uniform vec2 uTexCoord;
6881 vec4 foo(S structVar)
6882 {
6883 return texture2D(structVar.samplerMember, uTexCoord);
6884 }
6885 void main()
6886 {
6887 gl_FragColor = foo(uStruct);
6888 })";
6889
6890 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6891
6892 // Initialize the texture with green.
6893 GLTexture tex;
6894 glActiveTexture(GL_TEXTURE0);
6895 glBindTexture(GL_TEXTURE_2D, tex);
6896 GLubyte texData[] = {0u, 255u, 0u, 255u};
6897 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6900 ASSERT_GL_NO_ERROR();
6901
6902 // Draw
6903 glUseProgram(program);
6904 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6905 ASSERT_NE(-1, samplerMemberLoc);
6906 glUniform1i(samplerMemberLoc, 0);
6907 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6908 ASSERT_NE(-1, texCoordLoc);
6909 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6910
6911 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6912 ASSERT_GL_NO_ERROR();
6913
6914 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6915 }
6916
6917 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)6918 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
6919 {
6920 // Shader failed to compile on Android. http://anglebug.com/2114
6921 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6922
6923 const char kFragmentShader[] = R"(precision mediump float;
6924 struct S { sampler2D samplerMember; };
6925 uniform S uStruct;
6926 uniform vec2 uTexCoord;
6927 vec4 foo(S structVar);
6928 vec4 foo(S structVar)
6929 {
6930 return texture2D(structVar.samplerMember, uTexCoord);
6931 }
6932 void main()
6933 {
6934 gl_FragColor = foo(uStruct);
6935 })";
6936
6937 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6938
6939 // Initialize the texture with green.
6940 GLTexture tex;
6941 glActiveTexture(GL_TEXTURE0);
6942 glBindTexture(GL_TEXTURE_2D, tex);
6943 GLubyte texData[] = {0u, 255u, 0u, 255u};
6944 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6945 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6946 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6947 ASSERT_GL_NO_ERROR();
6948
6949 // Draw
6950 glUseProgram(program);
6951 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6952 ASSERT_NE(-1, samplerMemberLoc);
6953 glUniform1i(samplerMemberLoc, 0);
6954 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6955 ASSERT_NE(-1, texCoordLoc);
6956 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6957
6958 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6959 ASSERT_GL_NO_ERROR();
6960
6961 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6962 }
6963 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)6964 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
6965 {
6966 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6967 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6968
6969 constexpr char kFS[] =
6970 "precision mediump float;\n"
6971 "struct S\n"
6972 "{\n"
6973 " sampler2D samplerMember; \n"
6974 "};\n"
6975 "uniform S uStructs[2];\n"
6976 "uniform vec2 uTexCoord;\n"
6977 "\n"
6978 "vec4 foo(S[2] structs)\n"
6979 "{\n"
6980 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
6981 "}\n"
6982 "void main()\n"
6983 "{\n"
6984 " gl_FragColor = foo(uStructs);\n"
6985 "}\n";
6986
6987 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6988
6989 // Initialize the texture with green.
6990 GLTexture tex;
6991 glActiveTexture(GL_TEXTURE0);
6992 glBindTexture(GL_TEXTURE_2D, tex);
6993 GLubyte texData[] = {0u, 255u, 0u, 255u};
6994 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6997 ASSERT_GL_NO_ERROR();
6998
6999 // Draw
7000 glUseProgram(program);
7001 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
7002 ASSERT_NE(-1, samplerMemberLoc);
7003 glUniform1i(samplerMemberLoc, 0);
7004 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7005 ASSERT_NE(-1, texCoordLoc);
7006 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7007
7008 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7009 ASSERT_GL_NO_ERROR();
7010
7011 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7012 }
7013
7014 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)7015 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
7016 {
7017 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7018 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7019
7020 constexpr char kFS[] =
7021 "precision mediump float;\n"
7022 "struct S\n"
7023 "{\n"
7024 " sampler2D samplerMembers[2];\n"
7025 "};\n"
7026 "uniform S uStruct;\n"
7027 "uniform vec2 uTexCoord;\n"
7028 "\n"
7029 "vec4 foo(S str)\n"
7030 "{\n"
7031 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
7032 "}\n"
7033 "void main()\n"
7034 "{\n"
7035 " gl_FragColor = foo(uStruct);\n"
7036 "}\n";
7037
7038 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7039
7040 // Initialize the texture with green.
7041 GLTexture tex;
7042 glActiveTexture(GL_TEXTURE0);
7043 glBindTexture(GL_TEXTURE_2D, tex);
7044 GLubyte texData[] = {0u, 255u, 0u, 255u};
7045 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7046 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7047 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7048 ASSERT_GL_NO_ERROR();
7049
7050 // Draw
7051 glUseProgram(program);
7052 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
7053 ASSERT_NE(-1, samplerMemberLoc);
7054 glUniform1i(samplerMemberLoc, 0);
7055 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7056 ASSERT_NE(-1, texCoordLoc);
7057 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7058
7059 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7060 ASSERT_GL_NO_ERROR();
7061
7062 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7063 }
7064
7065 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)7066 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
7067 {
7068 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7069 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7070
7071 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
7072 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
7073
7074 const char kFragmentShader[] = R"(precision mediump float;
7075 struct S { sampler2D samplerMember; };
7076 struct T { S nest; };
7077 uniform T uStruct;
7078 uniform vec2 uTexCoord;
7079 vec4 foo2(S structVar)
7080 {
7081 return texture2D(structVar.samplerMember, uTexCoord);
7082 }
7083 vec4 foo(T structVar)
7084 {
7085 return foo2(structVar.nest);
7086 }
7087 void main()
7088 {
7089 gl_FragColor = foo(uStruct);
7090 })";
7091
7092 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7093
7094 // Initialize the texture with green.
7095 GLTexture tex;
7096 glActiveTexture(GL_TEXTURE0);
7097 glBindTexture(GL_TEXTURE_2D, tex);
7098 GLubyte texData[] = {0u, 255u, 0u, 255u};
7099 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7101 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7102 ASSERT_GL_NO_ERROR();
7103
7104 // Draw
7105 glUseProgram(program);
7106 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
7107 ASSERT_NE(-1, samplerMemberLoc);
7108 glUniform1i(samplerMemberLoc, 0);
7109 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7110 ASSERT_NE(-1, texCoordLoc);
7111 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7112
7113 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7114 ASSERT_GL_NO_ERROR();
7115
7116 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7117 }
7118
7119 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)7120 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
7121 {
7122 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7123 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7124
7125 const char kFragmentShader[] = R"(precision mediump float;
7126 struct S { sampler2D samplerMember; bool b; };
7127 uniform S uStruct;
7128 uniform vec2 uTexCoord;
7129 vec4 foo(S structVar)
7130 {
7131 if (structVar.b)
7132 return texture2D(structVar.samplerMember, uTexCoord);
7133 else
7134 return vec4(1, 0, 0, 1);
7135 }
7136 void main()
7137 {
7138 gl_FragColor = foo(uStruct);
7139 })";
7140
7141 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7142
7143 // Initialize the texture with green.
7144 GLTexture tex;
7145 glActiveTexture(GL_TEXTURE0);
7146 glBindTexture(GL_TEXTURE_2D, tex);
7147 GLubyte texData[] = {0u, 255u, 0u, 255u};
7148 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7151 ASSERT_GL_NO_ERROR();
7152
7153 // Draw
7154 glUseProgram(program);
7155 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
7156 ASSERT_NE(-1, samplerMemberLoc);
7157 glUniform1i(samplerMemberLoc, 0);
7158 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7159 ASSERT_NE(-1, texCoordLoc);
7160 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7161 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
7162 ASSERT_NE(-1, bLoc);
7163 glUniform1i(bLoc, 1);
7164
7165 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7166 ASSERT_GL_NO_ERROR();
7167
7168 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7169 }
7170
7171 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)7172 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
7173 {
7174 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7175 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7176
7177 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
7178 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
7179
7180 const char kFragmentShader[] = R"(precision mediump float;
7181 struct S { sampler2D samplerMember; bool b; };
7182 struct T { S nest; bool b; };
7183 uniform T uStruct;
7184 uniform vec2 uTexCoord;
7185 vec4 foo2(S structVar)
7186 {
7187 if (structVar.b)
7188 return texture2D(structVar.samplerMember, uTexCoord);
7189 else
7190 return vec4(1, 0, 0, 1);
7191 }
7192 vec4 foo(T structVar)
7193 {
7194 if (structVar.b)
7195 return foo2(structVar.nest);
7196 else
7197 return vec4(1, 0, 0, 1);
7198 }
7199 void main()
7200 {
7201 gl_FragColor = foo(uStruct);
7202 })";
7203
7204 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7205
7206 // Initialize the texture with green.
7207 GLTexture tex;
7208 glActiveTexture(GL_TEXTURE0);
7209 glBindTexture(GL_TEXTURE_2D, tex);
7210 GLubyte texData[] = {0u, 255u, 0u, 255u};
7211 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7214 ASSERT_GL_NO_ERROR();
7215
7216 // Draw
7217 glUseProgram(program);
7218 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
7219 ASSERT_NE(-1, samplerMemberLoc);
7220 glUniform1i(samplerMemberLoc, 0);
7221 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7222 ASSERT_NE(-1, texCoordLoc);
7223 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7224
7225 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
7226 ASSERT_NE(-1, bLoc);
7227 glUniform1i(bLoc, 1);
7228
7229 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
7230 ASSERT_NE(-1, nestbLoc);
7231 glUniform1i(nestbLoc, 1);
7232
7233 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7234 ASSERT_GL_NO_ERROR();
7235
7236 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7237 }
7238
7239 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)7240 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
7241 {
7242 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7243 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7244
7245 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
7246 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
7247
7248 const char kFragmentShader[] = R"(precision mediump float;
7249 struct S { bool b; sampler2D samplerMember; };
7250 struct T { bool b; S nest; };
7251 uniform T uStruct;
7252 uniform vec2 uTexCoord;
7253 vec4 foo2(S structVar)
7254 {
7255 if (structVar.b)
7256 return texture2D(structVar.samplerMember, uTexCoord);
7257 else
7258 return vec4(1, 0, 0, 1);
7259 }
7260 vec4 foo(T structVar)
7261 {
7262 if (structVar.b)
7263 return foo2(structVar.nest);
7264 else
7265 return vec4(1, 0, 0, 1);
7266 }
7267 void main()
7268 {
7269 gl_FragColor = foo(uStruct);
7270 })";
7271
7272 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7273
7274 // Initialize the texture with green.
7275 GLTexture tex;
7276 glActiveTexture(GL_TEXTURE0);
7277 glBindTexture(GL_TEXTURE_2D, tex);
7278 GLubyte texData[] = {0u, 255u, 0u, 255u};
7279 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7282 ASSERT_GL_NO_ERROR();
7283
7284 // Draw
7285 glUseProgram(program);
7286 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
7287 ASSERT_NE(-1, samplerMemberLoc);
7288 glUniform1i(samplerMemberLoc, 0);
7289 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7290 ASSERT_NE(-1, texCoordLoc);
7291 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7292
7293 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
7294 ASSERT_NE(-1, bLoc);
7295 glUniform1i(bLoc, 1);
7296
7297 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
7298 ASSERT_NE(-1, nestbLoc);
7299 glUniform1i(nestbLoc, 1);
7300
7301 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7302 ASSERT_GL_NO_ERROR();
7303
7304 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7305 }
7306 // Test that a global variable declared after main() works. This is a regression test for an issue
7307 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)7308 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
7309 {
7310 constexpr char kFS[] =
7311 "precision mediump float;\n"
7312 "int getFoo();\n"
7313 "uniform int u_zero;\n"
7314 "void main()\n"
7315 "{\n"
7316 " gl_FragColor = vec4(1, 0, 0, 1);\n"
7317 " if (getFoo() == 0)\n"
7318 " {\n"
7319 " gl_FragColor = vec4(0, 1, 0, 1);\n"
7320 " }\n"
7321 "}\n"
7322 "int foo;\n"
7323 "int getFoo()\n"
7324 "{\n"
7325 " foo = u_zero;\n"
7326 " return foo;\n"
7327 "}\n";
7328
7329 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7330 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7331 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7332 }
7333
7334 // Test calling array length() with a "this" expression having side effects inside a loop condition.
7335 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)7336 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
7337 {
7338 // "a" gets doubled three times in the below program.
7339 constexpr char kFS[] = R"(#version 300 es
7340 precision highp float;
7341 out vec4 my_FragColor;
7342 uniform int u_zero;
7343 int a;
7344 int[2] doubleA()
7345 {
7346 a *= 2;
7347 return int[2](a, a);
7348 }
7349 void main()
7350 {
7351 a = u_zero + 1;
7352 for (int i = 0; i < doubleA().length(); ++i)
7353 {}
7354 if (a == 8)
7355 {
7356 my_FragColor = vec4(0, 1, 0, 1);
7357 }
7358 else
7359 {
7360 my_FragColor = vec4(1, 0, 0, 1);
7361 }
7362 })";
7363
7364 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7365 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7366 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7367 }
7368
7369 // Test calling array length() with a "this" expression having side effects that interact with side
7370 // effects of another operand of the same sequence operator. The spec says that sequence operator
7371 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)7372 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
7373 {
7374 constexpr char kFS[] = R"(#version 300 es
7375 precision highp float;
7376 out vec4 my_FragColor;
7377 uniform int u_zero;
7378 int a;
7379 int[3] doubleA()
7380 {
7381 a *= 2;
7382 return int[3](a, a, a);
7383 }
7384 void main()
7385 {
7386 a = u_zero;
7387 int b = (a++, doubleA().length());
7388 if (b == 3 && a == 2)
7389 {
7390 my_FragColor = vec4(0, 1, 0, 1);
7391 }
7392 else
7393 {
7394 my_FragColor = vec4(1, 0, 0, 1);
7395 }
7396 })";
7397
7398 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7399 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7400 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7401 }
7402
7403 // Test calling array length() with a "this" expression that also contains a call of array length().
7404 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)7405 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
7406 {
7407 constexpr char kFS[] = R"(#version 300 es
7408 precision highp float;
7409 out vec4 my_FragColor;
7410 uniform int u_zero;
7411 int a;
7412 int[3] multiplyA(int multiplier)
7413 {
7414 a *= multiplier;
7415 return int[3](a, a, a);
7416 }
7417 void main()
7418 {
7419 a = u_zero + 1;
7420 int b = multiplyA(multiplyA(2).length()).length();
7421 if (b == 3 && a == 6)
7422 {
7423 my_FragColor = vec4(0, 1, 0, 1);
7424 }
7425 else
7426 {
7427 my_FragColor = vec4(1, 0, 0, 1);
7428 }
7429 })";
7430
7431 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7432 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7433 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7434 }
7435
7436 // Test calling array length() with a "this" expression having side effects inside an if condition.
7437 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)7438 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
7439 {
7440 // Bug in the shader translator. http://anglebug.com/3829
7441 ANGLE_SKIP_TEST_IF(true);
7442
7443 // "a" shouldn't get modified by this shader.
7444 constexpr char kFS[] = R"(#version 300 es
7445 precision highp float;
7446 out vec4 my_FragColor;
7447 uniform int u_zero;
7448 int a;
7449 int[2] doubleA()
7450 {
7451 a *= 2;
7452 return int[2](a, a);
7453 }
7454 void main()
7455 {
7456 a = u_zero + 1;
7457 if (u_zero != 0 && doubleA().length() == 2)
7458 {
7459 ++a;
7460 }
7461 if (a == 1)
7462 {
7463 my_FragColor = vec4(0, 1, 0, 1);
7464 }
7465 else
7466 {
7467 my_FragColor = vec4(1, 0, 0, 1);
7468 }
7469 })";
7470
7471 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7472 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7474 }
7475
7476 // Test calling array length() with a "this" expression having side effects in a statement where the
7477 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)7478 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
7479 {
7480 // Bug in the shader translator. http://anglebug.com/3829
7481 ANGLE_SKIP_TEST_IF(true);
7482
7483 // "a" shouldn't get modified by this shader.
7484 constexpr char kFS[] = R"(#version 300 es
7485 precision highp float;
7486 out vec4 my_FragColor;
7487 uniform int u_zero;
7488 int a;
7489 int[2] doubleA()
7490 {
7491 a *= 2;
7492 return int[2](a, a);
7493 }
7494 void main()
7495 {
7496 a = u_zero + 1;
7497 bool test = u_zero != 0 && doubleA().length() == 2;
7498 if (a == 1)
7499 {
7500 my_FragColor = vec4(0, 1, 0, 1);
7501 }
7502 else
7503 {
7504 my_FragColor = vec4(1, 0, 0, 1);
7505 }
7506 })";
7507
7508 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7509 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7510 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7511 }
7512
7513 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)7514 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
7515 {
7516 constexpr char kFS[] = R"(#version 300 es
7517 precision highp float;
7518 uniform int u;
7519 void main()
7520 {
7521 switch (u)
7522 {
7523 case 0:
7524 ivec2 i;
7525 i.yx;
7526 }
7527 })";
7528
7529 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7530 }
7531
7532 // Test that switch fall-through works correctly.
7533 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)7534 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
7535 {
7536 constexpr char kFS[] = R"(#version 300 es
7537 precision highp float;
7538 out vec4 my_FragColor;
7539 uniform int u_zero;
7540
7541 void main()
7542 {
7543 int i = 0;
7544 // switch should fall through both cases.
7545 switch(u_zero)
7546 {
7547 case 0:
7548 i += 1;
7549 case 1:
7550 i += 2;
7551 }
7552 if (i == 3)
7553 {
7554 my_FragColor = vec4(0, 1, 0, 1);
7555 }
7556 else
7557 {
7558 my_FragColor = vec4(1, 0, 0, 1);
7559 }
7560 })";
7561
7562 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7563 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7564 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7565 }
7566
7567 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)7568 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
7569 {
7570 constexpr char kFS[] = R"(#version 300 es
7571
7572 precision highp float;
7573 out vec4 my_FragColor;
7574
7575 uniform int u_zero;
7576
7577 void main()
7578 {
7579 switch (u_zero)
7580 {
7581 case 1:
7582 my_FragColor = vec4(1, 0, 0, 1);
7583 break;
7584 default:
7585 my_FragColor = vec4(0, 1, 0, 1);
7586 }
7587 })";
7588
7589 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7590 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7591 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7592 }
7593
7594 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)7595 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
7596 {
7597 constexpr char kFS[] = R"(#version 300 es
7598
7599 precision mediump float;
7600 uniform int i;
7601 void main()
7602 {
7603 switch (i)
7604 {
7605 case 0:
7606 break;
7607 default:
7608 {}
7609 }
7610 })";
7611 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7612 }
7613
7614 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)7615 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
7616 {
7617 constexpr char kFS[] = R"(#version 300 es
7618
7619 precision mediump float;
7620 uniform int i;
7621 void main()
7622 {
7623 switch (i)
7624 {
7625 case 0:
7626 break;
7627 default:
7628 float;
7629 }
7630 })";
7631 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7632 }
7633
7634 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)7635 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
7636 {
7637 constexpr char kFS[] = R"(#version 300 es
7638
7639 precision highp float;
7640
7641 uniform int u_zero;
7642 out vec4 my_FragColor;
7643
7644 bool test(int n)
7645 {
7646 switch(n) {
7647 case 0:
7648 {
7649 {
7650 break;
7651 }
7652 }
7653 case 1:
7654 {
7655 return true;
7656 }
7657 case 2:
7658 {
7659 n++;
7660 }
7661 }
7662 return false;
7663 }
7664
7665 void main()
7666 {
7667 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7668 })";
7669
7670 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7671 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7672 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7673 }
7674
7675 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
7676 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)7677 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
7678 {
7679 constexpr char kFS[] = R"(#version 300 es
7680
7681 precision highp float;
7682 out vec4 my_FragColor;
7683
7684 uniform int u_zero;
7685
7686 void main()
7687 {
7688 my_FragColor = vec4(1, 0, 0, 1);
7689 switch (u_zero)
7690 {
7691 case 0:
7692 ivec2 i;
7693 i = ivec2(1, 0);
7694 default:
7695 my_FragColor = vec4(0, i[0], 0, 1);
7696 }
7697 })";
7698
7699 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7700 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7701 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7702 }
7703
7704 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
7705 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)7706 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
7707 {
7708 constexpr char kFS[] = R"(#version 300 es
7709
7710 precision highp float;
7711 out vec4 my_FragColor;
7712
7713 uniform int u_zero;
7714 uniform int u_zero2;
7715
7716 void main()
7717 {
7718 my_FragColor = vec4(1, 0, 0, 1);
7719 switch (u_zero)
7720 {
7721 case 0:
7722 ivec2 i;
7723 i = ivec2(1, 0);
7724 switch (u_zero2)
7725 {
7726 case 0:
7727 int j;
7728 default:
7729 j = 1;
7730 i *= j;
7731 }
7732 default:
7733 my_FragColor = vec4(0, i[0], 0, 1);
7734 }
7735 })";
7736
7737 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7738 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7739 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7740 }
7741
7742 // Test that an empty switch/case statement is translated in a way that compiles and executes the
7743 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)7744 TEST_P(GLSLTest_ES3, EmptySwitch)
7745 {
7746 constexpr char kFS[] = R"(#version 300 es
7747
7748 precision highp float;
7749
7750 uniform int u_zero;
7751 out vec4 my_FragColor;
7752
7753 void main()
7754 {
7755 int i = u_zero;
7756 switch(++i) {}
7757 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7758 })";
7759
7760 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7761 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7762 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7763 }
7764
7765 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)7766 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
7767 {
7768 // Incorrect output color was seen on Android. http://anglebug.com/2226
7769 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
7770
7771 constexpr char kFS[] = R"(#version 300 es
7772
7773 precision highp float;
7774 out vec4 my_FragColor;
7775
7776 uniform float u_zero;
7777
7778 struct S
7779 {
7780 float field;
7781 };
7782
7783 void main()
7784 {
7785 const S constS = S(1.0);
7786 S nonConstS = constS;
7787 nonConstS.field = u_zero;
7788 bool fail = (constS == nonConstS);
7789 my_FragColor = vec4(0, 1, 0, 1);
7790 if (fail)
7791 {
7792 my_FragColor = vec4(1, 0, 0, 1);
7793 }
7794 })";
7795
7796 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7797 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7798 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7799 }
7800
7801 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)7802 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
7803 {
7804 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7805 // struct member. Not sure if it's being overly strict.
7806 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7807 constexpr char kVS[] = R"(#version 300 es
7808 in vec4 inputAttribute;
7809
7810 flat out struct S
7811 {
7812 int field;
7813 } v_s;
7814
7815 void main()
7816 {
7817 v_s.field = 1;
7818 gl_Position = inputAttribute;
7819 })";
7820
7821 constexpr char kFS[] = R"(#version 300 es
7822
7823 precision highp float;
7824 out vec4 my_FragColor;
7825
7826 flat in struct S
7827 {
7828 int field;
7829 } v_s;
7830
7831 void main()
7832 {
7833 bool success = (v_s.field == 1);
7834 my_FragColor = vec4(1, 0, 0, 1);
7835 if (success)
7836 {
7837 my_FragColor = vec4(0, 1, 0, 1);
7838 }
7839 })";
7840
7841 ANGLE_GL_PROGRAM(program, kVS, kFS);
7842 drawQuad(program.get(), "inputAttribute", 0.5f);
7843 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7844 }
7845
7846 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)7847 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
7848 {
7849 constexpr char kVS[] = R"(#version 300 es
7850 in vec4 position;
7851 uniform highp float inVal;
7852 out highp float myVarying;
7853
7854 void main()
7855 {
7856 myVarying = inVal;
7857 gl_Position = position;
7858 })";
7859
7860 constexpr char kFS[] = R"(#version 300 es
7861 precision highp float;
7862 out vec4 my_FragColor;
7863 in mediump float myVarying;
7864
7865 void main()
7866 {
7867 my_FragColor = vec4(1, 0, 0, 1);
7868 if (myVarying > 1.0)
7869 {
7870 my_FragColor = vec4(0, 1, 0, 1);
7871 }
7872 })";
7873
7874 ANGLE_GL_PROGRAM(program, kVS, kFS);
7875
7876 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7877 glClear(GL_COLOR_BUFFER_BIT);
7878 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7879
7880 glUseProgram(program.get());
7881 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7882 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7883 for (Vector3 &vertex : quadVertices)
7884 {
7885 vertex.z() = 0.5f;
7886 }
7887 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7888 glEnableVertexAttribArray(positionLocation);
7889
7890 GLint inValLoc = glGetUniformLocation(program, "inVal");
7891 ASSERT_NE(-1, inValLoc);
7892 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7893
7894 glDrawArrays(GL_TRIANGLES, 0, 6);
7895 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7896 }
7897
7898 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)7899 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
7900 {
7901 // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
7902 // precision", thus this is the same test as MismatchPrecisionFloat but including it for
7903 // completeness in case something changes.
7904 constexpr char kVS[] = R"(#version 300 es
7905 in vec4 position;
7906 uniform highp float inVal;
7907 out highp float myVarying;
7908
7909 void main()
7910 {
7911 myVarying = inVal;
7912 gl_Position = position;
7913 })";
7914
7915 constexpr char kFS[] = R"(#version 300 es
7916 precision highp float;
7917 out vec4 my_FragColor;
7918 in lowp float myVarying;
7919
7920 void main()
7921 {
7922 my_FragColor = vec4(1, 0, 0, 1);
7923 if (myVarying > 1.0)
7924 {
7925 my_FragColor = vec4(0, 1, 0, 1);
7926 }
7927 })";
7928
7929 ANGLE_GL_PROGRAM(program, kVS, kFS);
7930
7931 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7932 glClear(GL_COLOR_BUFFER_BIT);
7933 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7934
7935 glUseProgram(program.get());
7936 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7937 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7938 for (Vector3 &vertex : quadVertices)
7939 {
7940 vertex.z() = 0.5f;
7941 }
7942 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7943 glEnableVertexAttribArray(positionLocation);
7944
7945 GLint inValLoc = glGetUniformLocation(program, "inVal");
7946 ASSERT_NE(-1, inValLoc);
7947 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7948
7949 glDrawArrays(GL_TRIANGLES, 0, 6);
7950 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7951 }
7952
7953 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)7954 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
7955 {
7956 constexpr char kVS[] = R"(#version 300 es
7957 in vec2 position;
7958 uniform highp float inVal;
7959 out highp float myVarying;
7960 out highp vec2 texCoord;
7961
7962 void main()
7963 {
7964 myVarying = inVal;
7965 gl_Position = vec4(position, 0, 1);
7966 texCoord = position * 0.5 + vec2(0.5);
7967 })";
7968
7969 constexpr char kFS[] = R"(#version 300 es
7970 precision highp float;
7971 out vec4 my_FragColor;
7972 in mediump float myVarying;
7973 in mediump vec2 texCoord;
7974
7975 void main()
7976 {
7977 my_FragColor = vec4(1, 0, 0, 1);
7978 if (myVarying > 1.0)
7979 {
7980 my_FragColor = vec4(0, 1, 0, 1);
7981 }
7982 })";
7983
7984 ANGLE_GL_PROGRAM(program, kVS, kFS);
7985
7986 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7987 glClear(GL_COLOR_BUFFER_BIT);
7988 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7989
7990 glUseProgram(program.get());
7991 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7992 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7993 for (Vector3 &vertex : quadVertices)
7994 {
7995 vertex.z() = 0.5f;
7996 }
7997 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7998 glEnableVertexAttribArray(positionLocation);
7999
8000 GLint inValLoc = glGetUniformLocation(program, "inVal");
8001 ASSERT_NE(-1, inValLoc);
8002 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
8003
8004 glDrawArrays(GL_TRIANGLES, 0, 6);
8005 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8006 }
8007
8008 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)8009 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
8010 {
8011 constexpr char kVS[] = R"(#version 300 es
8012 in vec2 position;
8013 uniform highp float inVal;
8014 out mediump float myVarying;
8015
8016 void main()
8017 {
8018 myVarying = inVal;
8019 gl_Position = vec4(position, 0, 1);
8020 })";
8021
8022 constexpr char kFS[] = R"(#version 300 es
8023 precision highp float;
8024 out vec4 my_FragColor;
8025 in highp float myVarying;
8026
8027 void main()
8028 {
8029 my_FragColor = vec4(1, 0, 0, 1);
8030 if (myVarying > 1.0)
8031 {
8032 my_FragColor = vec4(0, 1, 0, 1);
8033 }
8034 })";
8035
8036 ANGLE_GL_PROGRAM(program, kVS, kFS);
8037
8038 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8039 glClear(GL_COLOR_BUFFER_BIT);
8040 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8041
8042 glUseProgram(program.get());
8043 GLint positionLocation = glGetAttribLocation(program.get(), "position");
8044 std::array<Vector3, 6> quadVertices = GetQuadVertices();
8045 for (Vector3 &vertex : quadVertices)
8046 {
8047 vertex.z() = 0.5f;
8048 }
8049 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
8050 glEnableVertexAttribArray(positionLocation);
8051
8052 GLint inValLoc = glGetUniformLocation(program, "inVal");
8053 ASSERT_NE(-1, inValLoc);
8054 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
8055
8056 glDrawArrays(GL_TRIANGLES, 0, 6);
8057 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8058 }
8059
8060 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)8061 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
8062 {
8063 constexpr char kFS[] = R"(precision mediump float;
8064
8065 void main() {
8066 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
8067 for (int i = 0; i < 2; i++)
8068 {
8069 gl_FragColor += (2.0 * gl_FragCoord.x);
8070 }
8071 if (gl_FragColor.g == gl_FragColor.r &&
8072 gl_FragColor.b == gl_FragColor.r &&
8073 gl_FragColor.a == gl_FragColor.r)
8074 {
8075 gl_FragColor = vec4(0, 1, 0, 1);
8076 }
8077 })";
8078
8079 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8080 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
8081 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8082 }
8083
8084 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)8085 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
8086 {
8087 constexpr char kFS[] = R"(precision mediump float;
8088
8089 void main() {
8090 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
8091 for (int i = 0; i < 2; i++)
8092 {
8093 float x = gl_FragCoord.x;
8094 gl_FragColor = gl_FragColor + (x /= 2.0);
8095 }
8096 if (gl_FragColor.g == gl_FragColor.r &&
8097 gl_FragColor.b == gl_FragColor.r &&
8098 gl_FragColor.a == gl_FragColor.r)
8099 {
8100 gl_FragColor = vec4(0, 1, 0, 1);
8101 }
8102 })";
8103
8104 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8105 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
8106 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8107 }
8108
8109 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
8110 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)8111 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
8112 {
8113 constexpr char kVS[] = R"(#version 300 es
8114
8115 in vec4 inputAttribute;
8116
8117 flat out int v;
8118
8119 void main()
8120 {
8121 v = 1;
8122 gl_Position = inputAttribute;
8123 })";
8124
8125 constexpr char kFS[] = R"(#version 300 es
8126
8127 precision highp float;
8128 out vec4 my_FragColor;
8129
8130 flat in int v;
8131
8132 void main()
8133 {
8134 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
8135 })";
8136
8137 ANGLE_GL_PROGRAM(program, kVS, kFS);
8138 drawQuad(program.get(), "inputAttribute", 0.5f);
8139 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8140 }
8141
8142 // Verify that the link error message from last link failure is cleared when the new link is
8143 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)8144 TEST_P(GLSLTest, ClearLinkErrorLog)
8145 {
8146 constexpr char kVS[] = R"(attribute vec4 vert_in;
8147 varying vec4 vert_out;
8148 void main()
8149 {
8150 gl_Position = vert_in;
8151 vert_out = vert_in;
8152 })";
8153
8154 constexpr char kFS[] = R"(precision mediump float;
8155 varying vec4 frag_in;
8156 void main()
8157 {
8158 gl_FragColor = frag_in;
8159 })";
8160
8161 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
8162 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
8163
8164 GLuint program = glCreateProgram();
8165
8166 // The first time the program link fails because of lack of fragment shader.
8167 glAttachShader(program, vs);
8168 glLinkProgram(program);
8169 GLint linkStatus = GL_TRUE;
8170 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
8171 ASSERT_FALSE(linkStatus);
8172
8173 const std::string &lackOfFragmentShader = QueryErrorMessage(program);
8174
8175 // The second time the program link fails because of the mismatch of the varying types.
8176 glAttachShader(program, fs);
8177 glLinkProgram(program);
8178 linkStatus = GL_TRUE;
8179 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
8180 ASSERT_FALSE(linkStatus);
8181
8182 const std::string &varyingTypeMismatch = QueryErrorMessage(program);
8183
8184 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
8185
8186 glDetachShader(program, vs);
8187 glDetachShader(program, fs);
8188 glDeleteShader(vs);
8189 glDeleteShader(fs);
8190 glDeleteProgram(program);
8191
8192 ASSERT_GL_NO_ERROR();
8193 }
8194
8195 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)8196 TEST_P(GLSLTest, DrawAfterShaderLinkError)
8197 {
8198 constexpr char kVS[] = R"(attribute vec4 position;
8199 varying vec4 vColor;
8200 void main()
8201 {
8202 vColor = vec4(0.0, 1.0, 0.0, 1.0);
8203 gl_Position = position;
8204 })";
8205 constexpr char kFS[] = R"(precision mediump float;
8206 varying vec4 vColor;
8207 void main()
8208 {
8209 gl_FragColor = vColor;
8210 })";
8211 constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
8212
8213 GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
8214
8215 // Create bad fragment shader
8216 {
8217 const char *sourceArray[1] = {kBadFS};
8218 glShaderSource(fsBad, 1, sourceArray, nullptr);
8219 glCompileShader(fsBad);
8220
8221 GLint compileResult;
8222 glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
8223 ASSERT_FALSE(compileResult);
8224 }
8225
8226 ANGLE_GL_PROGRAM(program, kVS, kFS);
8227 GLuint fs = GetProgramShader(program.get(), GL_FRAGMENT_SHADER);
8228
8229 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8230 glClear(GL_COLOR_BUFFER_BIT);
8231 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8232
8233 glUseProgram(program.get());
8234 GLint positionLocation = glGetAttribLocation(program.get(), "position");
8235 std::array<Vector3, 6> quadVertices = GetQuadVertices();
8236 for (Vector3 &vertex : quadVertices)
8237 {
8238 vertex.z() = 0.5f;
8239 }
8240 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
8241 glEnableVertexAttribArray(positionLocation);
8242 glDrawArrays(GL_TRIANGLES, 0, 6);
8243 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8244
8245 glDetachShader(program.get(), fs);
8246 glAttachShader(program.get(), fsBad);
8247 glLinkProgram(program.get());
8248 GLint linkStatus = GL_TRUE;
8249 glGetProgramiv(program.get(), GL_LINK_STATUS, &linkStatus);
8250 ASSERT_FALSE(linkStatus);
8251
8252 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8253 glClear(GL_COLOR_BUFFER_BIT);
8254 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8255
8256 glDrawArrays(GL_TRIANGLES, 0, 6);
8257 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8258 }
8259
8260 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)8261 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
8262 {
8263 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
8264 varying vec4 vertex_out;
8265 void main()
8266 {
8267 vertex_out = inputAttribute;
8268 gl_Position = inputAttribute;
8269 })";
8270
8271 constexpr char kFS[] = R"(precision mediump float;
8272 varying float vertex_out;
8273 void main()
8274 {
8275 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
8276 })";
8277
8278 validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
8279 }
8280
8281 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)8282 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
8283 {
8284 constexpr char kVS[] = R"(#version 300 es
8285 in vec4 inputAttribute;
8286 struct S {
8287 float val1;
8288 vec4 val2;
8289 };
8290 out S vertex_out;
8291 void main()
8292 {
8293 vertex_out.val2 = inputAttribute;
8294 vertex_out.val1 = inputAttribute[0];
8295 gl_Position = inputAttribute;
8296 })";
8297
8298 constexpr char kFS[] = R"(#version 300 es
8299 precision mediump float;
8300 struct S {
8301 float val1;
8302 vec4 val3;
8303 };
8304 in S vertex_out;
8305 layout (location = 0) out vec4 frag_out;
8306 void main()
8307 {
8308 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
8309 })";
8310
8311 validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
8312 }
8313
8314 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)8315 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
8316 {
8317 constexpr char kVS[] = R"(#version 300 es
8318 in vec4 inputAttribute;
8319 struct S {
8320 float val1;
8321 vec4 val2;
8322 };
8323 out S vertex_out;
8324 void main()
8325 {
8326 vertex_out.val2 = inputAttribute;
8327 vertex_out.val1 = inputAttribute[0];
8328 gl_Position = inputAttribute;
8329 })";
8330
8331 constexpr char kFS[] = R"(#version 300 es
8332 precision mediump float;
8333 struct S {
8334 float val1;
8335 vec2 val2;
8336 };
8337 in S vertex_out;
8338 layout (location = 0) out vec4 frag_out;
8339 void main()
8340 {
8341 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
8342 })";
8343
8344 validateComponentsInErrorMessage(kVS, kFS, "Types",
8345 "varying 'vertex_out' member 'vertex_out.val2'");
8346 }
8347
8348 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
8349 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)8350 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
8351 {
8352 constexpr char kVS[] = R"(
8353 struct T
8354 {
8355 vec2 t1;
8356 vec3 t2;
8357 };
8358 struct S {
8359 T val1;
8360 vec4 val2;
8361 };
8362 uniform S uni;
8363
8364 attribute vec4 inputAttribute;
8365 varying vec4 vertex_out;
8366 void main()
8367 {
8368 vertex_out = uni.val2;
8369 gl_Position = inputAttribute;
8370 })";
8371
8372 constexpr char kFS[] = R"(precision highp float;
8373 struct T
8374 {
8375 vec2 t1;
8376 vec3 t3;
8377 };
8378 struct S {
8379 T val1;
8380 vec4 val2;
8381 };
8382 uniform S uni;
8383
8384 varying vec4 vertex_out;
8385 void main()
8386 {
8387 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
8388 })";
8389
8390 validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
8391 }
8392
8393 // Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
8394 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)8395 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
8396 {
8397 constexpr char kVS[] = R"(#version 300 es
8398 uniform S {
8399 vec2 val1;
8400 vec4 val2;
8401 } uni;
8402
8403 in vec4 inputAttribute;
8404 out vec4 vertex_out;
8405 void main()
8406 {
8407 vertex_out = uni.val2;
8408 gl_Position = inputAttribute;
8409 })";
8410
8411 constexpr char kFS[] = R"(#version 300 es
8412 precision highp float;
8413 uniform S {
8414 vec2 val1;
8415 vec3 val2;
8416 } uni;
8417
8418 in vec4 vertex_out;
8419 layout (location = 0) out vec4 frag_out;
8420 void main()
8421 {
8422 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
8423 })";
8424
8425 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
8426 }
8427
8428 // Validate error messages when the link mismatch occurs on the type of a member of a uniform block
8429 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)8430 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
8431 {
8432 constexpr char kVS[] = R"(#version 300 es
8433 struct T
8434 {
8435 vec2 t1;
8436 vec3 t2;
8437 };
8438 uniform S {
8439 T val1;
8440 vec4 val2;
8441 } uni;
8442
8443 in vec4 inputAttribute;
8444 out vec4 vertex_out;
8445 void main()
8446 {
8447 vertex_out = uni.val2;
8448 gl_Position = inputAttribute;
8449 })";
8450
8451 constexpr char kFS[] = R"(#version 300 es
8452 precision highp float;
8453 struct T
8454 {
8455 vec2 t1;
8456 vec4 t2;
8457 };
8458 uniform S {
8459 T val1;
8460 vec4 val2;
8461 } uni;
8462
8463 in vec4 vertex_out;
8464 layout (location = 0) out vec4 frag_out;
8465 void main()
8466 {
8467 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
8468 })";
8469
8470 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
8471 }
8472
8473 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
8474 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)8475 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
8476 {
8477 constexpr char kVS[] = R"(#version 300 es
8478 precision mediump float;
8479
8480 void main()
8481 {
8482 gl_Position = vec4(0, 1, 0, 1);
8483 })";
8484
8485 constexpr char kFS[] = R"(#version 300 es
8486 precision mediump float;
8487 in float foo;
8488 out vec4 my_FragColor;
8489
8490 void main()
8491 {
8492 if (false)
8493 {
8494 float unreferenced = foo;
8495 }
8496 my_FragColor = vec4(0, 1, 0, 1);
8497 })";
8498
8499 validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
8500 }
8501
8502 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)8503 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
8504 {
8505 constexpr char kVS[] = R"(#version 300 es
8506 precision mediump float;
8507 in vec4 iv;
8508 out vec4 v;
8509 void main()
8510 {
8511 gl_Position = iv;
8512 v = iv;
8513 })";
8514
8515 constexpr char kFS[] = R"(#version 300 es
8516 precision mediump float;
8517 in vec4 v;
8518 out vec4 color;
8519 void main()
8520 {
8521 color = true ? vec4(0.0) : v;
8522 })";
8523
8524 ANGLE_GL_PROGRAM(program, kVS, kFS);
8525 }
8526
8527 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)8528 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
8529 {
8530 constexpr char kVS[] = R"(#version 310 es
8531 precision highp float;
8532 in vec4 position;
8533 layout(location = 1) out vec4 shaderOutput;
8534 void main() {
8535 gl_Position = position;
8536 shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
8537 })";
8538
8539 constexpr char kFS[] = R"(#version 310 es
8540 precision highp float;
8541 layout(location = 1) in vec4 shaderInput;
8542 out vec4 outColor;
8543 void main() {
8544 outColor = shaderInput;
8545 })";
8546
8547 ANGLE_GL_PROGRAM(program, kVS, kFS);
8548 drawQuad(program, "position", 0.5f);
8549 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8550 }
8551
8552 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)8553 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
8554 {
8555 // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
8556 // up red. http://crbug.com/838885
8557 ANGLE_SKIP_TEST_IF(IsD3D11());
8558
8559 constexpr char kFS[] = R"(#version 300 es
8560 precision highp float;
8561 out vec4 my_FragColor;
8562 void main()
8563 {
8564 vec2 coord = gl_FragCoord.xy / 500.0;
8565 my_FragColor = vec4(1, 0, 0, 1);
8566 if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
8567 {
8568 my_FragColor = vec4(0, 1, 0, 1);
8569 }
8570 })";
8571
8572 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8573 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
8574 // Verify that all the corners of the rendered result are green.
8575 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8576 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8577 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
8578 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
8579 }
8580
8581 // Verify that a link error is generated when the sum of the number of active image uniforms and
8582 // active shader storage blocks in a rendering pipeline exceeds
8583 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)8584 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
8585 {
8586 // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
8587 // D3D11 back-ends.
8588 ANGLE_SKIP_TEST_IF(IsD3D11());
8589
8590 GLint maxVertexShaderStorageBlocks;
8591 GLint maxVertexImageUniforms;
8592 GLint maxFragmentShaderStorageBlocks;
8593 GLint maxFragmentImageUniforms;
8594 GLint maxCombinedShaderStorageBlocks;
8595 GLint maxCombinedImageUniforms;
8596 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
8597 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
8598 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
8599 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
8600 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
8601 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
8602
8603 ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
8604 ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
8605 ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
8606 ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
8607
8608 GLint vertexSSBOs = maxVertexShaderStorageBlocks;
8609 GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
8610 // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
8611 if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
8612 {
8613 fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
8614 }
8615
8616 GLint vertexImages = maxVertexImageUniforms;
8617 GLint fragmentImages = maxFragmentImageUniforms;
8618 // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
8619 if (vertexImages + fragmentImages > maxCombinedImageUniforms)
8620 {
8621 vertexImages = maxCombinedImageUniforms - fragmentImages;
8622 }
8623
8624 GLint maxDrawBuffers;
8625 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
8626
8627 GLint maxCombinedShaderOutputResources;
8628 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
8629 ASSERT_GL_NO_ERROR();
8630
8631 ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
8632 maxDrawBuffers <=
8633 maxCombinedShaderOutputResources);
8634
8635 std::ostringstream vertexStream;
8636 vertexStream << "#version 310 es\n";
8637 for (int i = 0; i < vertexSSBOs; ++i)
8638 {
8639 vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
8640 << "{\n"
8641 " float data;\n"
8642 "} ssbo"
8643 << i << ";\n";
8644 }
8645 vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
8646 << "];\n";
8647 vertexStream << "void main()\n"
8648 "{\n"
8649 " float val = 0.1;\n"
8650 " vec4 val2 = vec4(0.0);\n";
8651 for (int i = 0; i < vertexSSBOs; ++i)
8652 {
8653 vertexStream << " val += ssbo" << i << ".data; \n";
8654 }
8655 for (int i = 0; i < vertexImages; ++i)
8656 {
8657 vertexStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
8658 }
8659 vertexStream << " gl_Position = vec4(val, val2);\n"
8660 "}\n";
8661
8662 std::ostringstream fragmentStream;
8663 fragmentStream << "#version 310 es\n"
8664 << "precision highp float;\n";
8665 for (int i = 0; i < fragmentSSBOs; ++i)
8666 {
8667 fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
8668 << "{\n"
8669 " float data;\n"
8670 "} ssbo"
8671 << i << ";\n";
8672 }
8673 fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
8674 << fragmentImages << "];\n";
8675 fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
8676
8677 fragmentStream << "void main()\n"
8678 "{\n"
8679 " float val = 0.1;\n"
8680 " vec4 val2 = vec4(0.0);\n";
8681 for (int i = 0; i < fragmentSSBOs; ++i)
8682 {
8683 fragmentStream << " val += ssbo" << i << ".data; \n";
8684 }
8685 for (int i = 0; i < fragmentImages; ++i)
8686 {
8687 fragmentStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
8688 }
8689 for (int i = 0; i < maxDrawBuffers; ++i)
8690 {
8691 fragmentStream << " foutput[" << i << "] = vec4(val, val2);\n";
8692 }
8693 fragmentStream << "}\n";
8694
8695 GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
8696 EXPECT_EQ(0u, program);
8697
8698 ASSERT_GL_NO_ERROR();
8699 }
8700
8701 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
8702 // function works correctly.
TEST_P(GLSLTest_ES3,AssignAssignmentToSwizzled)8703 TEST_P(GLSLTest_ES3, AssignAssignmentToSwizzled)
8704 {
8705 constexpr char kFS[] = R"(#version 300 es
8706 precision highp float;
8707 out vec4 my_FragColor;
8708
8709 uniform float uzero;
8710
8711 vec3 fun(float s, float v)
8712 {
8713 vec3 r = vec3(0);
8714 if (s < 1.0) {
8715 r.x = r.y = r.z = v;
8716 return r;
8717 }
8718 return r;
8719 }
8720
8721 void main()
8722 {
8723 my_FragColor.a = 1.0;
8724 my_FragColor.rgb = fun(uzero, 1.0);
8725 })";
8726
8727 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8728 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
8729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
8730 }
8731
8732 // Test a fragment shader that returns inside if (that being the only branch that actually gets
8733 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)8734 TEST_P(GLSLTest, IfElseIfAndReturn)
8735 {
8736 constexpr char kVS[] = R"(attribute vec4 a_position;
8737 varying vec2 vPos;
8738 void main()
8739 {
8740 gl_Position = a_position;
8741 vPos = a_position.xy;
8742 })";
8743
8744 constexpr char kFS[] = R"(precision mediump float;
8745 varying vec2 vPos;
8746 void main()
8747 {
8748 if (vPos.x < 1.0) // This colors the whole canvas green
8749 {
8750 gl_FragColor = vec4(0, 1, 0, 1);
8751 return;
8752 }
8753 else if (vPos.x < 1.1) // This should have no effect
8754 {
8755 gl_FragColor = vec4(1, 0, 0, 1);
8756 }
8757 })";
8758
8759 ANGLE_GL_PROGRAM(program, kVS, kFS);
8760 drawQuad(program.get(), "a_position", 0.5f);
8761 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8762 }
8763
8764 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)8765 TEST_P(GLSLTest, IfElsePrunedBlocks)
8766 {
8767 constexpr char kFS[] = R"(precision mediump float;
8768 uniform float u;
8769 void main()
8770 {
8771 // if with only a pruned true block
8772 if (u > 0.0)
8773 if (false) discard;
8774
8775 // if with a pruned true block and a false block
8776 if (u > 0.0)
8777 {
8778 if (false) discard;
8779 }
8780 else
8781 ;
8782
8783 // if with a true block and a pruned false block
8784 if (u > 0.0)
8785 ;
8786 else
8787 if (false) discard;
8788
8789 // if with a pruned true block and a pruned false block
8790 if (u > 0.0)
8791 {
8792 if (false) discard;
8793 }
8794 else
8795 if (false) discard;
8796
8797 gl_FragColor = vec4(0, 1, 0, 1);
8798 })";
8799
8800 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8801 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
8802 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8803 }
8804
8805 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)8806 TEST_P(GLSLTest, PointCoordConsistency)
8807 {
8808 // http://anglebug.com/4092
8809 ANGLE_SKIP_TEST_IF(isSwiftshader());
8810
8811 constexpr char kPointCoordVS[] = R"(attribute vec2 position;
8812 uniform vec2 viewportSize;
8813 void main()
8814 {
8815 gl_Position = vec4(position, 0, 1);
8816 gl_PointSize = viewportSize.x;
8817 })";
8818
8819 constexpr char kPointCoordFS[] = R"(void main()
8820 {
8821 gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
8822 })";
8823
8824 ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
8825 glUseProgram(program);
8826
8827 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8828 ASSERT_NE(-1, uniLoc);
8829 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8830 static_cast<GLfloat>(getWindowHeight()));
8831
8832 // Draw to backbuffer.
8833 glClear(GL_COLOR_BUFFER_BIT);
8834 glDrawArrays(GL_POINTS, 0, 1);
8835 ASSERT_GL_NO_ERROR();
8836
8837 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8838 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8839 backbufferData.data());
8840
8841 GLTexture tex;
8842 glBindTexture(GL_TEXTURE_2D, tex);
8843 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8844 GL_UNSIGNED_BYTE, nullptr);
8845
8846 GLFramebuffer fbo;
8847 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8848 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8849 ASSERT_GL_NO_ERROR();
8850 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8851
8852 // Draw to user FBO.
8853 glClear(GL_COLOR_BUFFER_BIT);
8854 glDrawArrays(GL_POINTS, 0, 1);
8855 ASSERT_GL_NO_ERROR();
8856
8857 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8858 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8859 userFBOData.data());
8860
8861 ASSERT_GL_NO_ERROR();
8862 ASSERT_EQ(userFBOData.size(), backbufferData.size());
8863 EXPECT_EQ(userFBOData, backbufferData);
8864 }
8865
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)8866 bool SubrectEquals(const std::vector<GLColor> &bigArray,
8867 const std::vector<GLColor> &smallArray,
8868 int bigSize,
8869 int offset,
8870 int smallSize)
8871 {
8872 int badPixels = 0;
8873 for (int y = 0; y < smallSize; y++)
8874 {
8875 for (int x = 0; x < smallSize; x++)
8876 {
8877 int bigOffset = (y + offset) * bigSize + x + offset;
8878 int smallOffset = y * smallSize + x;
8879 if (bigArray[bigOffset] != smallArray[smallOffset])
8880 badPixels++;
8881 }
8882 }
8883 return badPixels == 0;
8884 }
8885
8886 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)8887 TEST_P(GLSLTest, FragCoordConsistency)
8888 {
8889 constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
8890 void main()
8891 {
8892 gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
8893 })";
8894
8895 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
8896 glUseProgram(program);
8897
8898 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8899 ASSERT_NE(-1, uniLoc);
8900 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8901 static_cast<GLfloat>(getWindowHeight()));
8902
8903 // Draw to backbuffer.
8904 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8905 ASSERT_GL_NO_ERROR();
8906
8907 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8908 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8909 backbufferData.data());
8910
8911 GLTexture tex;
8912 glBindTexture(GL_TEXTURE_2D, tex);
8913 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8914 GL_UNSIGNED_BYTE, nullptr);
8915
8916 GLFramebuffer fbo;
8917 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8918 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8919 ASSERT_GL_NO_ERROR();
8920 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8921
8922 // Draw to user FBO.
8923 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8924 ASSERT_GL_NO_ERROR();
8925
8926 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8927 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8928 userFBOData.data());
8929
8930 ASSERT_GL_NO_ERROR();
8931 ASSERT_EQ(userFBOData.size(), backbufferData.size());
8932 EXPECT_EQ(userFBOData, backbufferData)
8933 << "FragCoord should be the same to default and user FBO";
8934
8935 // Repeat the same test but with a smaller viewport.
8936 ASSERT_EQ(getWindowHeight(), getWindowWidth());
8937 const int kQuarterSize = getWindowWidth() >> 2;
8938 glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
8939
8940 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8941 glClear(GL_COLOR_BUFFER_BIT);
8942 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8943
8944 std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
8945 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8946 GL_UNSIGNED_BYTE, userFBOViewportData.data());
8947
8948 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8949 glClear(GL_COLOR_BUFFER_BIT);
8950 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8951
8952 std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
8953 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8954 GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
8955 ASSERT_GL_NO_ERROR();
8956 EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
8957 << "FragCoord should be the same to default and user FBO even with a custom viewport";
8958
8959 // Check that the subrectangles are the same between the viewport and non-viewport modes.
8960 EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
8961 kQuarterSize * 2));
8962 EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
8963 kQuarterSize, kQuarterSize * 2));
8964 }
8965
8966 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)8967 TEST_P(GLSLTest, DefinedInMacroSucceeds)
8968 {
8969 constexpr char kVS[] = R"(precision mediump float;
8970 attribute highp vec4 position;
8971 varying vec2 out0;
8972
8973 void main()
8974 {
8975 #define AAA defined(BBB)
8976
8977 #if !AAA
8978 out0 = vec2(0.0, 1.0);
8979 #else
8980 out0 = vec2(1.0, 0.0);
8981 #endif
8982 gl_Position = position;
8983 })";
8984
8985 constexpr char kFS[] = R"(precision mediump float;
8986 varying vec2 out0;
8987 void main()
8988 {
8989 gl_FragColor = vec4(out0, 0, 1);
8990 })";
8991
8992 ANGLE_GL_PROGRAM(program, kVS, kFS);
8993 drawQuad(program, "position", 0.5f);
8994 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8995 }
8996
8997 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)8998 TEST_P(GLSLTest, DefinedInMacroWithUndef)
8999 {
9000 constexpr char kVS[] = R"(precision mediump float;
9001 attribute highp vec4 position;
9002 varying vec2 out0;
9003
9004 void main()
9005 {
9006 #define BBB 1
9007 #define AAA defined(BBB)
9008 #undef BBB
9009
9010 #if AAA
9011 out0 = vec2(1.0, 0.0);
9012 #else
9013 out0 = vec2(0.0, 1.0);
9014 #endif
9015 gl_Position = position;
9016 })";
9017
9018 constexpr char kFS[] = R"(precision mediump float;
9019 varying vec2 out0;
9020 void main()
9021 {
9022 gl_FragColor = vec4(out0, 0, 1);
9023 })";
9024
9025 ANGLE_GL_PROGRAM(program, kVS, kFS);
9026 drawQuad(program, "position", 0.5f);
9027 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9028 }
9029
9030 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)9031 TEST_P(GLSLTest, DefinedAfterMacroUsage)
9032 {
9033 constexpr char kVS[] = R"(precision mediump float;
9034 attribute highp vec4 position;
9035 varying vec2 out0;
9036
9037 void main()
9038 {
9039 #define AAA defined(BBB)
9040 #define BBB 1
9041
9042 #if AAA
9043 out0 = vec2(0.0, 1.0);
9044 #else
9045 out0 = vec2(1.0, 0.0);
9046 #endif
9047 gl_Position = position;
9048 })";
9049
9050 constexpr char kFS[] = R"(precision mediump float;
9051 varying vec2 out0;
9052 void main()
9053 {
9054 gl_FragColor = vec4(out0, 0, 1);
9055 })";
9056
9057 ANGLE_GL_PROGRAM(program, kVS, kFS);
9058 drawQuad(program, "position", 0.5f);
9059 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9060 }
9061
9062 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)9063 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
9064 {
9065 constexpr char kVS[] = R"(precision mediump float;
9066 attribute highp vec4 position;
9067 varying vec2 out0;
9068
9069 void main()
9070 {
9071 #define BBB 1
9072 #define AAA(defi, ned) defi ## ned(BBB)
9073
9074 #if AAA(defi, ned)
9075 out0 = vec2(0.0, 1.0);
9076 #else
9077 out0 = vec2(1.0, 0.0);
9078 #endif
9079 gl_Position = position;
9080 })";
9081
9082 constexpr char kFS[] = R"(precision mediump float;
9083 varying vec2 out0;
9084 void main()
9085 {
9086 gl_FragColor = vec4(out0, 0, 1);
9087 })";
9088
9089 GLuint program = CompileProgram(kVS, kFS);
9090 EXPECT_EQ(0u, program);
9091 glDeleteProgram(program);
9092 }
9093
9094 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)9095 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
9096 {
9097 constexpr char kVS[] = R"(precision mediump float;
9098 attribute highp vec4 position;
9099 varying vec2 out0;
9100
9101 void main()
9102 {
9103 #define BBB 1
9104 #define AAA(defined) defined(BBB)
9105
9106 #if AAA(defined)
9107 out0 = vec2(0.0, 1.0);
9108 #else
9109 out0 = vec2(1.0, 0.0);
9110 #endif
9111 gl_Position = position;
9112 })";
9113
9114 constexpr char kFS[] = R"(precision mediump float;
9115 varying vec2 out0;
9116 void main()
9117 {
9118 gl_FragColor = vec4(out0, 0, 1);
9119 })";
9120
9121 GLuint program = CompileProgram(kVS, kFS);
9122 EXPECT_EQ(0u, program);
9123 glDeleteProgram(program);
9124 }
9125
9126 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)9127 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
9128 {
9129 constexpr char kVS[] = R"(precision mediump float;
9130 attribute highp vec4 position;
9131 varying float out0;
9132
9133 void main()
9134 {
9135 #define AAA defined(BBB)
9136
9137 #if !AAA
9138 out0 = 1.0;
9139 #else
9140 out0 = 0.0;
9141 #endif
9142 gl_Position = dEQP_Position;
9143 })";
9144
9145 constexpr char kFS[] = R"(precision mediump float;
9146 varying float out0;
9147 void main()
9148 {
9149 gl_FragColor = vec4(out0, 0, 0, 1);
9150 })";
9151
9152 GLuint program = CompileProgram(kVS, kFS);
9153 EXPECT_EQ(0u, program);
9154 glDeleteProgram(program);
9155 }
9156
9157 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)9158 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
9159 {
9160 constexpr char kVS[] = R"(void main()
9161 {
9162 gl_Position = vec4(1, 0, 0, 1);
9163 })";
9164
9165 constexpr char kFS[] = R"(#if defined(GL_ES)
9166 precision mediump float;
9167 void main()
9168 {
9169 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
9170 }
9171 #else
9172 foo
9173 #endif
9174 )";
9175
9176 ANGLE_GL_PROGRAM(program, kVS, kFS);
9177 }
9178
9179 // Test that inactive output variables compile ok in combination with SH_INIT_OUTPUT_VARIABLES
9180 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)9181 TEST_P(WebGL2GLSLTest, InactiveOutput)
9182 {
9183 constexpr char kFS[] = R"(#version 300 es
9184 precision highp float;
9185 out vec4 _cassgl_2_;
9186 void main()
9187 {
9188 })";
9189
9190 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
9191 EXPECT_NE(shader, 0u);
9192 }
9193
9194 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)9195 TEST_P(GLSLTest, ValidIndexClampES100)
9196 {
9197 // http://anglebug.com/6027
9198 ANGLE_SKIP_TEST_IF(IsD3D9());
9199
9200 constexpr char kFS[] = R"(
9201 precision mediump float;
9202 uniform int u;
9203 uniform mat4 m[2];
9204 void main()
9205 {
9206 gl_FragColor = vec4(m[u][1].xyz, 1);
9207 }
9208 )";
9209
9210 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9211 glUseProgram(program);
9212
9213 GLint uniformLocation = glGetUniformLocation(program, "u");
9214 ASSERT_NE(-1, uniformLocation);
9215
9216 GLint matrixLocation = glGetUniformLocation(program, "m");
9217 ASSERT_NE(matrixLocation, -1);
9218 const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
9219 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
9220 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
9221 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
9222 glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
9223
9224 glUniform1i(uniformLocation, 1);
9225 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9226 EXPECT_GL_NO_ERROR();
9227
9228 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9229 }
9230
9231 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)9232 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
9233 {
9234 constexpr char kFS[] = R"(#version 300 es
9235 precision mediump float;
9236 out vec4 color;
9237 uniform int u;
9238 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
9239 void main()
9240 {
9241 color = vec4(m[u][2].xyz, 1);
9242 }
9243 )";
9244
9245 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9246 glUseProgram(program);
9247
9248 GLint uniformLocation = glGetUniformLocation(program, "u");
9249 ASSERT_NE(-1, uniformLocation);
9250
9251 glUniform1i(uniformLocation, 2);
9252 EXPECT_GL_NO_ERROR();
9253 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9254 EXPECT_GL_NO_ERROR();
9255
9256 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
9257 }
9258
9259 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)9260 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
9261 {
9262 constexpr char kFS[] = R"(#version 300 es
9263 precision mediump float;
9264
9265 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
9266 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);
9267
9268 out vec4 color;
9269
9270 void main()
9271 {
9272 mat4x2 result = matrixCompMult(matA, matB);
9273 vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
9274 if (vresult == vec2(4.0, 4.0))
9275 {
9276 color = vec4(0.0, 1.0, 0.0, 1.0);
9277 }
9278 else
9279 {
9280 color = vec4(1.0, 0.0, 0.0, 1.0);
9281 }
9282 })";
9283
9284 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9285 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9286 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9287 }
9288
9289 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)9290 TEST_P(GLSLTest_ES3, InitSameNameArray)
9291 {
9292 constexpr char kFS[] = R"(#version 300 es
9293 precision highp float;
9294 out vec4 my_FragColor;
9295
9296 void main()
9297 {
9298 float arr[2] = float[2](1.0, 1.0);
9299 {
9300 float arr[2] = arr;
9301 my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
9302 }
9303 })";
9304
9305 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9306 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9307 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9308 }
9309
9310 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)9311 TEST_P(GLSLTest, FragData)
9312 {
9313 // Ensures that we don't regress and emit Vulkan layer warnings.
9314 // TODO(jonahr): http://anglebug.com/3900 - Remove check once warnings are cleaned up
9315 if (IsVulkan())
9316 {
9317 treatPlatformWarningsAsErrors();
9318 }
9319
9320 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
9321 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9322 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9323 EXPECT_GL_NO_ERROR();
9324 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9325 }
9326
9327 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)9328 TEST_P(GLSLTest, MemoryExhaustedTest)
9329 {
9330 GLuint program =
9331 CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
9332 EXPECT_NE(0u, program);
9333 }
9334
9335 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)9336 TEST_P(GLSLTest, InactiveSamplersInStruct)
9337 {
9338 constexpr char kVS[] = R"(attribute vec4 a_position;
9339 void main() {
9340 gl_Position = a_position;
9341 })";
9342
9343 constexpr char kFS[] = R"(precision highp float;
9344 struct S
9345 {
9346 vec4 v;
9347 sampler2D t[10];
9348 };
9349 uniform S s;
9350 void main() {
9351 gl_FragColor = s.v;
9352 })";
9353
9354 ANGLE_GL_PROGRAM(program, kVS, kFS);
9355
9356 drawQuad(program, "a_position", 0.5f);
9357 }
9358
9359 // Helper functions for MixedRowAndColumnMajorMatrices* tests
9360
9361 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)9362 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
9363 {
9364 return (value + alignment - 1) & ~(alignment - 1);
9365 }
9366
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)9367 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
9368 {
9369 unsigned int outputInitData = 0;
9370 glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
9371 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9372 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
9373 EXPECT_GL_NO_ERROR();
9374 }
9375
9376 // Fill provided buffer with matrices based on the given dimensions. The buffer should be large
9377 // 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)9378 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
9379 const bool matrixIsColMajor[],
9380 size_t matrixCount,
9381 float data[],
9382 bool isStd430,
9383 bool isTransposed)
9384 {
9385 size_t offset = 0;
9386 for (size_t m = 0; m < matrixCount; ++m)
9387 {
9388 uint32_t cols = matrixDims[m].first;
9389 uint32_t rows = matrixDims[m].second;
9390 bool isColMajor = matrixIsColMajor[m] != isTransposed;
9391
9392 uint32_t arraySize = isColMajor ? cols : rows;
9393 uint32_t arrayElementComponents = isColMajor ? rows : cols;
9394 // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
9395 // MixedRowAndColumnMajorMatrices* tests don't use). With std430, small matrices can have
9396 // a stride of 2 between rows/columns.
9397 uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
9398
9399 offset = RoundUpPow2(offset, stride);
9400
9401 for (uint32_t i = 0; i < arraySize; ++i)
9402 {
9403 for (uint32_t c = 0; c < arrayElementComponents; ++c)
9404 {
9405 uint32_t row = isColMajor ? c : i;
9406 uint32_t col = isColMajor ? i : c;
9407
9408 data[offset + i * stride + c] = col * 4 + row;
9409 }
9410 }
9411
9412 offset += arraySize * stride;
9413 }
9414 return offset;
9415 }
9416
9417 // Initialize and bind the buffer.
9418 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)9419 void InitBuffer(GLuint program,
9420 const char *name,
9421 GLuint buffer,
9422 uint32_t bindingIndex,
9423 const T data[],
9424 uint32_t dataSize,
9425 bool isUniform)
9426 {
9427 GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
9428
9429 glBindBufferBase(bindPoint, bindingIndex, buffer);
9430 glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
9431
9432 if (isUniform)
9433 {
9434 GLint blockIndex = glGetUniformBlockIndex(program, name);
9435 glUniformBlockBinding(program, blockIndex, bindingIndex);
9436 }
9437 }
9438
9439 // Verify that buffer data is written by the shader as expected.
9440 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)9441 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
9442 {
9443 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
9444
9445 const T *ptr = reinterpret_cast<const T *>(
9446 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize, GL_MAP_READ_BIT));
9447
9448 bool isCorrect = memcmp(ptr, data, dataSize * sizeof(*data)) == 0;
9449 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9450
9451 return isCorrect;
9452 }
9453
9454 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)9455 bool VerifySuccess(GLuint buffer)
9456 {
9457 uint32_t success = 1;
9458 return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
9459 }
9460
9461 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
9462 // both std140 and std430 layouts. Tests many combinations of std140 vs std430, struct being used
9463 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
9464 // nested structs, matrix arrays, inout parameters etc.
9465 //
9466 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)9467 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
9468 {
9469 GLint maxComputeShaderStorageBlocks;
9470 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
9471
9472 // The test uses 9 SSBOs. Skip if not that many are supported.
9473 ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
9474
9475 // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
9476 // UBO also see it as row-major despite explicit column-major qualifier.
9477 // http://anglebug.com/3830
9478 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
9479
9480 // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
9481 // read column-major despite explicit row-major qualifier. http://anglebug.com/3837
9482 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
9483
9484 // Fails on windows AMD on GL: http://anglebug.com/3838
9485 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
9486
9487 // Fails to compile the shader on Android. http://anglebug.com/3839
9488 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
9489
9490 // Fails on assertion in translation to D3D. http://anglebug.com/3841
9491 ANGLE_SKIP_TEST_IF(IsD3D11());
9492
9493 // Fails on SSBO validation on Android/Vulkan. http://anglebug.com/3840
9494 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
9495
9496 // Fails input verification as well as std140 SSBO validation. http://anglebug.com/3844
9497 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
9498
9499 // Fails on ARM on Vulkan. http://anglebug.com/4492
9500 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
9501
9502 constexpr char kCS[] = R"(#version 310 es
9503 precision highp float;
9504 layout(local_size_x=1) in;
9505
9506 struct Inner
9507 {
9508 mat3x4 m3c4r;
9509 mat4x3 m4c3r;
9510 };
9511
9512 struct Matrices
9513 {
9514 mat2 m2c2r;
9515 mat2x3 m2c3r[2];
9516 mat3x2 m3c2r;
9517 Inner inner;
9518 };
9519
9520 // For simplicity, the layouts are either of:
9521 // - col-major mat4, row-major rest
9522 // - row-major mat4, col-major rest
9523 //
9524 // The former is tagged with c, the latter with r.
9525 layout(std140, column_major) uniform Ubo140c
9526 {
9527 mat4 m4c4r;
9528 layout(row_major) Matrices m;
9529 } ubo140cIn;
9530
9531 layout(std140, row_major) uniform Ubo140r
9532 {
9533 mat4 m4c4r;
9534 layout(column_major) Matrices m;
9535 } ubo140rIn;
9536
9537 layout(std140, row_major, binding = 0) buffer Ssbo140c
9538 {
9539 layout(column_major) mat4 m4c4r;
9540 Matrices m;
9541 } ssbo140cIn;
9542
9543 layout(std140, column_major, binding = 1) buffer Ssbo140r
9544 {
9545 layout(row_major) mat4 m4c4r;
9546 Matrices m;
9547 } ssbo140rIn;
9548
9549 layout(std430, column_major, binding = 2) buffer Ssbo430c
9550 {
9551 mat4 m4c4r;
9552 layout(row_major) Matrices m;
9553 } ssbo430cIn;
9554
9555 layout(std430, row_major, binding = 3) buffer Ssbo430r
9556 {
9557 mat4 m4c4r;
9558 layout(column_major) Matrices m;
9559 } ssbo430rIn;
9560
9561 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
9562 {
9563 layout(column_major) mat4 m4c4r;
9564 Matrices m;
9565 } ssbo140cOut;
9566
9567 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
9568 {
9569 layout(row_major) mat4 m4c4r;
9570 Matrices m;
9571 } ssbo140rOut;
9572
9573 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
9574 {
9575 mat4 m4c4r;
9576 layout(row_major) Matrices m;
9577 } ssbo430cOut;
9578
9579 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
9580 {
9581 mat4 m4c4r;
9582 layout(column_major) Matrices m;
9583 } ssbo430rOut;
9584
9585 layout(std140, binding = 8) buffer Result
9586 {
9587 uint success;
9588 } resultOut;
9589
9590 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
9591 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
9592
9593 #define VERIFY_IN(result, mat, cols, rows) \
9594 EXPECT(result, mat[0].x, 0.0); \
9595 EXPECT(result, mat[0][1], 1.0); \
9596 EXPECTV(result, mat[0].xy, vec2(0, 1)); \
9597 EXPECTV(result, mat[1].xy, vec2(4, 5)); \
9598 for (int c = 0; c < cols; ++c) \
9599 { \
9600 for (int r = 0; r < rows; ++r) \
9601 { \
9602 EXPECT(result, mat[c][r], float(c * 4 + r)); \
9603 } \
9604 }
9605
9606 #define COPY(matIn, matOut, cols, rows) \
9607 matOut = matOut + matIn; \
9608 /* random operations for testing */ \
9609 matOut[0].x += matIn[0].x + matIn[1].x; \
9610 matOut[0].x -= matIn[1].x; \
9611 matOut[0][1] += matIn[0][1]; \
9612 matOut[1] += matIn[1]; \
9613 matOut[1].xy -= matIn[1].xy; \
9614 /* undo the above to get back matIn */ \
9615 matOut[0].x -= matIn[0].x; \
9616 matOut[0][1] -= matIn[0][1]; \
9617 matOut[1] -= matIn[1]; \
9618 matOut[1].xy += matIn[1].xy;
9619
9620 bool verifyMatrices(in Matrices m)
9621 {
9622 bool result = true;
9623 VERIFY_IN(result, m.m2c2r, 2, 2);
9624 VERIFY_IN(result, m.m2c3r[0], 2, 3);
9625 VERIFY_IN(result, m.m2c3r[1], 2, 3);
9626 VERIFY_IN(result, m.m3c2r, 3, 2);
9627 VERIFY_IN(result, m.inner.m3c4r, 3, 4);
9628 VERIFY_IN(result, m.inner.m4c3r, 4, 3);
9629 return result;
9630 }
9631
9632 mat4 copyMat4(in mat4 m)
9633 {
9634 return m;
9635 }
9636
9637 void copyMatrices(in Matrices mIn, inout Matrices mOut)
9638 {
9639 COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
9640 COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
9641 COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
9642 COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
9643 COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
9644 COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
9645 }
9646
9647 void main()
9648 {
9649 bool result = true;
9650
9651 VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
9652 VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
9653 EXPECT(result, verifyMatrices(ubo140cIn.m), true);
9654
9655 VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
9656 VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
9657 EXPECT(result, verifyMatrices(ubo140rIn.m), true);
9658
9659 VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
9660 VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
9661 EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
9662
9663 VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
9664 VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
9665 EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
9666
9667 VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
9668 VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
9669 EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
9670
9671 VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
9672 VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
9673 EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
9674
9675 // Only assign to SSBO from a single invocation.
9676 if (gl_GlobalInvocationID.x == 0u)
9677 {
9678 ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
9679 copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
9680 ssbo140cOut.m.m2c3r[1] = mat2x3(0);
9681 COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
9682
9683 ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
9684 copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
9685 ssbo140rOut.m.inner.m3c4r = mat3x4(0);
9686 COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
9687
9688 ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
9689 copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
9690 ssbo430cOut.m.m3c2r = mat3x2(0);
9691 COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
9692
9693 ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
9694 copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
9695 ssbo430rOut.m.inner.m4c3r = mat4x3(0);
9696 COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
9697
9698 resultOut.success = uint(result);
9699 }
9700 })";
9701
9702 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
9703 EXPECT_GL_NO_ERROR();
9704
9705 constexpr size_t kMatrixCount = 7;
9706 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9707 {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
9708 };
9709 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9710 true, false, false, false, false, false, false,
9711 };
9712
9713 float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
9714 float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
9715 float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
9716 float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
9717 float dataZeros[kMatrixCount * 4 * 4] = {};
9718
9719 const uint32_t sizeStd140ColMajor =
9720 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
9721 const uint32_t sizeStd140RowMajor =
9722 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
9723 const uint32_t sizeStd430ColMajor =
9724 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
9725 const uint32_t sizeStd430RowMajor =
9726 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
9727
9728 GLBuffer uboStd140ColMajor, uboStd140RowMajor;
9729 GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
9730 GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
9731 GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
9732 GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
9733
9734 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
9735 true);
9736 InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
9737 true);
9738 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
9739 false);
9740 InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
9741 false);
9742 InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
9743 false);
9744 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
9745 false);
9746 InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
9747 false);
9748 InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
9749 false);
9750 InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
9751 false);
9752 InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
9753 false);
9754 EXPECT_GL_NO_ERROR();
9755
9756 GLBuffer outputBuffer;
9757 CreateOutputBuffer(&outputBuffer, 8);
9758
9759 glUseProgram(program);
9760 glDispatchCompute(1, 1, 1);
9761 EXPECT_GL_NO_ERROR();
9762 EXPECT_TRUE(VerifySuccess(outputBuffer));
9763
9764 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
9765 EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
9766 EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
9767 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
9768 }
9769
9770 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)9771 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
9772 {
9773 constexpr char kFS[] = R"(#version 300 es
9774 precision highp float;
9775 out vec4 outColor;
9776
9777 layout(std140, row_major) uniform Ubo
9778 {
9779 mat4 m1;
9780 };
9781
9782 void main()
9783 {
9784 outColor = m1[3] / 255.0;
9785 })";
9786
9787 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9788 EXPECT_GL_NO_ERROR();
9789
9790 constexpr size_t kMatrixCount = 1;
9791 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9792 {4, 4},
9793 };
9794 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9795 false,
9796 };
9797
9798 float data[kMatrixCount * 4 * 4] = {};
9799
9800 const uint32_t size =
9801 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9802
9803 GLBuffer ubos;
9804
9805 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
9806
9807 EXPECT_GL_NO_ERROR();
9808
9809 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9810 EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
9811 }
9812
9813 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)9814 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
9815 {
9816 constexpr char kFS[] = R"(#version 300 es
9817 precision highp float;
9818 out vec4 outColor;
9819
9820 layout(std140, row_major) uniform Ubo
9821 {
9822 mat2x3 m1;
9823 };
9824
9825 void main()
9826 {
9827 outColor = vec4(m1[1], 0) / 255.0;
9828 })";
9829
9830 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9831 EXPECT_GL_NO_ERROR();
9832
9833 constexpr size_t kMatrixCount = 1;
9834 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9835 {2, 3},
9836 };
9837 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9838 false,
9839 };
9840
9841 float data[kMatrixCount * 3 * 4] = {};
9842
9843 const uint32_t size =
9844 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9845
9846 GLBuffer ubos;
9847
9848 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
9849
9850 EXPECT_GL_NO_ERROR();
9851
9852 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9853 EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
9854 }
9855
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)9856 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
9857 {
9858 constexpr char kFS[] = R"(#version 300 es
9859 precision highp float;
9860 out vec4 outColor;
9861
9862 layout(std140, row_major) uniform Ubo
9863 {
9864 mat3x2 m1;
9865 };
9866
9867 void main()
9868 {
9869 outColor = vec4(m1[2], 0, 0) / 255.0;
9870 })";
9871
9872 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9873 EXPECT_GL_NO_ERROR();
9874
9875 constexpr size_t kMatrixCount = 1;
9876 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9877 {3, 2},
9878 };
9879 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9880 false,
9881 };
9882
9883 float data[kMatrixCount * 2 * 4] = {};
9884
9885 const uint32_t size =
9886 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9887
9888 GLBuffer ubos;
9889
9890 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
9891
9892 EXPECT_GL_NO_ERROR();
9893
9894 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9895 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
9896 }
9897
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)9898 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
9899 {
9900 // Many OpenGL drivers seem to fail this
9901 ANGLE_SKIP_TEST_IF((IsLinux() || IsOSX()) && IsOpenGL());
9902
9903 constexpr char kFS[] = R"(#version 300 es
9904 precision mediump float;
9905
9906 uniform Ubo {
9907 layout(row_major) mat4 u_mat[3];
9908 layout(row_major) mat4 u_ndx[3];
9909 } stuff;
9910
9911 precision highp float;
9912 out vec4 outColor;
9913
9914 void main() {
9915 outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
9916 }
9917 )";
9918
9919 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9920 EXPECT_GL_NO_ERROR();
9921
9922 typedef float vec4[4];
9923 typedef vec4 mat4[4];
9924
9925 constexpr size_t kMatrixCount = 6;
9926 mat4 data[] = {
9927 {
9928 {0, 1, 2, 3}, //
9929 {4, 5, 6, 7}, //
9930 {8, 9, 10, 11}, //
9931 {12, 13, 14, 15}, //
9932 },
9933 {
9934 // +-- we should be looking up this column
9935 // V
9936 {0, 4, 8, 12}, //
9937 {1, 5, 9, 13}, //
9938 {2, 6, 10, 14}, //
9939 {3, 7, 11, 15}, //
9940 },
9941 {
9942 {0, 2, 4, 6}, //
9943 {8, 10, 12, 14}, //
9944 {16, 18, 20, 22}, //
9945 {24, 26, 28, 30}, //
9946 },
9947 {
9948 {0, 0, 0, 0}, //
9949 {0, 0, 0, 0}, //
9950 {0, 0, 0, 0}, //
9951 {0, 0, 0, 0}, //
9952 },
9953 {
9954 {0, 0, 0, 0}, //
9955 {0, 0, 0, 2}, //
9956 {0, 0, 0, 0}, //
9957 {0, 1, 0, 0},
9958 // ^
9959 // +-- we should be using this element
9960 },
9961 {
9962 {0, 0, 0, 0}, //
9963 {0, 0, 0, 0}, //
9964 {0, 0, 0, 0}, //
9965 {0, 0, 0, 0}, //
9966 },
9967 };
9968
9969 GLBuffer ubos;
9970 InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
9971 EXPECT_GL_NO_ERROR();
9972
9973 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9974 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
9975 }
9976
9977 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)9978 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
9979 {
9980 // Fails to compile the shader on Android: http://anglebug.com/3839
9981 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
9982
9983 // http://anglebug.com/3837
9984 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
9985
9986 // Fails on Mac on Intel and AMD: http://anglebug.com/3842
9987 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
9988
9989 // Fails on windows AMD on GL: http://anglebug.com/3838
9990 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
9991
9992 // Fails on D3D due to mistranslation: http://anglebug.com/3841
9993 ANGLE_SKIP_TEST_IF(IsD3D11());
9994
9995 constexpr char kFS[] = R"(#version 300 es
9996 precision highp float;
9997 out vec4 outColor;
9998
9999 layout(std140, column_major) uniform Ubo
10000 {
10001 mat4 m1;
10002 layout(row_major) mat4 m2;
10003 } ubo[3];
10004
10005 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
10006
10007 #define VERIFY_IN(result, mat, cols, rows) \
10008 for (int c = 0; c < cols; ++c) \
10009 { \
10010 for (int r = 0; r < rows; ++r) \
10011 { \
10012 EXPECT(result, mat[c][r], float(c * 4 + r)); \
10013 } \
10014 }
10015
10016 void main()
10017 {
10018 bool result = true;
10019
10020 VERIFY_IN(result, ubo[0].m1, 4, 4);
10021 VERIFY_IN(result, ubo[0].m2, 4, 4);
10022
10023 VERIFY_IN(result, ubo[1].m1, 4, 4);
10024 VERIFY_IN(result, ubo[1].m2, 4, 4);
10025
10026 VERIFY_IN(result, ubo[2].m1, 4, 4);
10027 VERIFY_IN(result, ubo[2].m2, 4, 4);
10028
10029 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10030 })";
10031
10032 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10033 EXPECT_GL_NO_ERROR();
10034
10035 constexpr size_t kMatrixCount = 2;
10036 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10037 {4, 4},
10038 {4, 4},
10039 };
10040 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10041 true,
10042 false,
10043 };
10044
10045 float data[kMatrixCount * 4 * 4] = {};
10046
10047 const uint32_t size =
10048 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10049
10050 GLBuffer ubos[3];
10051
10052 InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
10053 InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
10054 InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
10055
10056 EXPECT_GL_NO_ERROR();
10057
10058 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10059 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10060 }
10061
10062 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)10063 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
10064 {
10065 // Fails on Mac on Intel and AMD: http://anglebug.com/3842
10066 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
10067
10068 // Fails on D3D due to mistranslation: http://anglebug.com/3841
10069 ANGLE_SKIP_TEST_IF(IsD3D11());
10070
10071 constexpr char kFS[] = R"(#version 300 es
10072 precision highp float;
10073 out vec4 outColor;
10074
10075 struct S
10076 {
10077 mat2x3 m2[3];
10078 };
10079
10080 layout(std140, column_major) uniform Ubo
10081 {
10082 mat4 m1;
10083 layout(row_major) S s[2];
10084 } ubo;
10085
10086 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
10087
10088 #define VERIFY_IN(result, mat, cols, rows) \
10089 for (int c = 0; c < cols; ++c) \
10090 { \
10091 for (int r = 0; r < rows; ++r) \
10092 { \
10093 EXPECT(result, mat[c][r], float(c * 4 + r)); \
10094 } \
10095 }
10096
10097 bool verify2x3(mat2x3 mat)
10098 {
10099 bool result = true;
10100
10101 for (int c = 0; c < 2; ++c)
10102 {
10103 for (int r = 0; r < 3; ++r)
10104 {
10105 EXPECT(result, mat[c][r], float(c * 4 + r));
10106 }
10107 }
10108
10109 return result;
10110 }
10111
10112 void main()
10113 {
10114 bool result = true;
10115
10116 int sideEffect = 0;
10117 VERIFY_IN(result, ubo.m1, 4, 4);
10118 EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
10119 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
10120 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
10121
10122 EXPECT(result, sideEffect, 2);
10123
10124 EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
10125 EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
10126 EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
10127
10128 EXPECT(result, sideEffect, 4);
10129
10130 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10131 })";
10132
10133 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10134 EXPECT_GL_NO_ERROR();
10135
10136 constexpr size_t kMatrixCount = 7;
10137 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10138 {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
10139 };
10140 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10141 true, false, false, false, false, false, false,
10142 };
10143
10144 float data[kMatrixCount * 4 * 4] = {};
10145
10146 const uint32_t size =
10147 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10148
10149 GLBuffer ubo;
10150 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10151
10152 EXPECT_GL_NO_ERROR();
10153
10154 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10155 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10156 }
10157
10158 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)10159 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
10160 {
10161 // http://anglebug.com/3837
10162 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10163
10164 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10165 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
10166 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10167
10168 constexpr char kFS[] = R"(#version 300 es
10169 precision highp float;
10170 out vec4 outColor;
10171
10172 layout(std140, column_major) uniform Ubo
10173 {
10174 mat4 m1;
10175 layout(row_major) mat4 m2[2];
10176 } ubo;
10177
10178 void main()
10179 {
10180 bool result = true;
10181
10182 int x = 0;
10183 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
10184 {
10185 result = true;
10186 }
10187 else
10188 {
10189 result = false;
10190 }
10191
10192 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10193 })";
10194
10195 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10196 EXPECT_GL_NO_ERROR();
10197
10198 constexpr size_t kMatrixCount = 3;
10199 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10200 {4, 4},
10201 {4, 4},
10202 {4, 4},
10203 };
10204 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10205
10206 float data[kMatrixCount * 4 * 4] = {};
10207
10208 const uint32_t size =
10209 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10210
10211 GLBuffer ubo;
10212 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10213
10214 EXPECT_GL_NO_ERROR();
10215
10216 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10217 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10218 }
10219
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)10220 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
10221 {
10222 // http://anglebug.com/3837
10223 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10224
10225 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10226 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
10227 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10228
10229 constexpr char kFS[] = R"(#version 300 es
10230 precision highp float;
10231 out vec4 outColor;
10232
10233 layout(std140, column_major) uniform Ubo
10234 {
10235 mat4 m1;
10236 layout(row_major) mat4 m2[2];
10237 } ubo;
10238
10239 void main()
10240 {
10241 bool result = false;
10242
10243 for(int x = 0; x < 1; ++x)
10244 {
10245 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
10246 result = true;
10247 }
10248 }
10249 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10250 })";
10251
10252 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10253 EXPECT_GL_NO_ERROR();
10254
10255 constexpr size_t kMatrixCount = 3;
10256 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10257 {4, 4},
10258 {4, 4},
10259 {4, 4},
10260 };
10261 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10262
10263 float data[kMatrixCount * 4 * 4] = {};
10264
10265 const uint32_t size =
10266 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10267
10268 GLBuffer ubo;
10269 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10270
10271 EXPECT_GL_NO_ERROR();
10272
10273 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10274 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10275 }
10276
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)10277 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
10278 {
10279 // http://anglebug.com/3837
10280 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10281
10282 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10283 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
10284 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10285
10286 constexpr char kFS[] = R"(#version 300 es
10287 precision highp float;
10288 out vec4 outColor;
10289
10290 layout(std140, column_major) uniform Ubo
10291 {
10292 mat4 m1;
10293 layout(row_major) mat4 m2[2];
10294 } ubo;
10295
10296 void main()
10297 {
10298 bool result = false;
10299
10300 for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
10301 {
10302 result = true;
10303 }
10304 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10305 })";
10306
10307 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10308 EXPECT_GL_NO_ERROR();
10309
10310 constexpr size_t kMatrixCount = 3;
10311 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10312 {4, 4},
10313 {4, 4},
10314 {4, 4},
10315 };
10316 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10317
10318 float data[kMatrixCount * 4 * 4] = {};
10319
10320 const uint32_t size =
10321 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10322
10323 GLBuffer ubo;
10324 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10325
10326 EXPECT_GL_NO_ERROR();
10327
10328 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10329 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10330 }
10331
10332 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)10333 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
10334 {
10335 // Fails on Android: http://anglebug.com/3839
10336 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
10337
10338 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10339 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
10340 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10341
10342 constexpr char kFS[] = R"(#version 300 es
10343 precision highp float;
10344 out vec4 outColor;
10345
10346 layout(std140, column_major) uniform Ubo
10347 {
10348 mat4 m1;
10349 layout(row_major) mat4 m2[2];
10350 } ubo;
10351
10352 void main()
10353 {
10354 bool result = true;
10355
10356 int x = 0;
10357 if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
10358 {
10359 // First x == 1 should prevent the side effect of the second expression (x = 1) from
10360 // being executed. If x = 1 is run before the if, the condition of the if would be true,
10361 // which is a failure.
10362 result = false;
10363 }
10364 if (x == 1)
10365 {
10366 result = false;
10367 }
10368
10369 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10370 })";
10371
10372 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10373 EXPECT_GL_NO_ERROR();
10374
10375 constexpr size_t kMatrixCount = 3;
10376 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10377 {4, 4},
10378 {4, 4},
10379 {4, 4},
10380 };
10381 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10382
10383 float data[kMatrixCount * 4 * 4] = {};
10384
10385 const uint32_t size =
10386 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10387
10388 GLBuffer ubo;
10389 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10390
10391 EXPECT_GL_NO_ERROR();
10392
10393 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10394 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10395 }
10396
10397 // Test that dynamic indexing of swizzled l-values should work.
10398 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)10399 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
10400 {
10401 // The shader first assigns v.x to v.z (1.0)
10402 // Then v.y to v.y (2.0)
10403 // Then v.z to v.x (1.0)
10404 constexpr char kFS[] = R"(#version 300 es
10405 precision highp float;
10406 out vec4 my_FragColor;
10407 void main() {
10408 vec3 v = vec3(1.0, 2.0, 3.0);
10409 for (int i = 0; i < 3; i++) {
10410 v.zyx[i] = v[i];
10411 }
10412 my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10413 })";
10414
10415 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10416 EXPECT_GL_NO_ERROR();
10417 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10418 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10419 }
10420
10421 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)10422 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
10423 {
10424 constexpr char kFS[] = R"(#version 300 es
10425 precision mediump float;
10426 out vec4 color;
10427
10428 vec4 f(vec4 c)
10429 {
10430 return c;
10431 // dead code
10432 c = vec4(0, 0, 1, 1);
10433 return c;
10434 }
10435
10436 void main()
10437 {
10438 vec4 result = vec4(0, 0.5, 0, 1);
10439 int var = int(result.y * 2.2);
10440
10441 {
10442 if (result.x > 1.0)
10443 {
10444 discard;
10445 // dead code
10446 result = vec4(1, 0, 0, 1);
10447 }
10448 for (int i = 0; i < 3; ++i)
10449 {
10450 if (i < 2)
10451 {
10452 result = f(result);
10453 continue;
10454 // dead code
10455 result = vec4(1, 0, 1, 1);
10456 }
10457 result = f(result);
10458 break;
10459 // dead code
10460 result = vec4(1, 0, 1, 0);
10461 }
10462 while (true)
10463 {
10464 if (result.x > -1.0)
10465 {
10466 {
10467 result = f(result);
10468 {
10469 break;
10470 // dead code
10471 result = vec4(1, 0, 0, 0);
10472 }
10473 // dead code
10474 for (int j = 0; j < 3; ++j)
10475 {
10476 if (j > 1) continue;
10477 result = vec4(0, 0, 1, 0);
10478 color = vec4(0.5, 0, 0.5, 0.5);
10479 return;
10480 }
10481 }
10482 // dead code
10483 result = vec4(0.5, 0, 0, 0);
10484 }
10485 }
10486 switch (var)
10487 {
10488 case 2:
10489 return;
10490 // dead code
10491 color = vec4(0.25, 0, 0.25, 0.25);
10492 case 1:
10493 {
10494 // Make sure this path is not pruned due to the return in the previous case.
10495 result.y += 0.5;
10496 break;
10497 // dead code
10498 color = vec4(0.25, 0, 0, 0);
10499 }
10500 // dead code
10501 color = vec4(0, 0, 0.25, 0);
10502 break;
10503 default:
10504 break;
10505 }
10506
10507 color = result;
10508 return;
10509 // dead code
10510 color = vec4(0, 0, 0.5, 0);
10511 }
10512 // dead code
10513 color = vec4(0, 0, 0, 0.5);
10514 })";
10515
10516 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10517
10518 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10519 EXPECT_GL_NO_ERROR();
10520
10521 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10522 }
10523
10524 // Regression test based on fuzzer issue. If a case has statements that are pruned, and those
10525 // pruned statements in turn have branches, and another case follows, a prior implementation of
10526 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)10527 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
10528 {
10529 constexpr char kFS[] = R"(#version 300 es
10530 precision mediump float;
10531 out vec4 color;
10532 void main()
10533 {
10534 color = vec4(0, 1, 0, 1);
10535 switch(0)
10536 {
10537 case 0:
10538 break;
10539 break;
10540 color = vec4(1, 0, 0, 1); // The bug was pruning this statement twice
10541 default:
10542 color = vec4(0, 0, 1, 1);
10543 break;
10544 }
10545 })";
10546
10547 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10548
10549 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10550 EXPECT_GL_NO_ERROR();
10551
10552 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10553 }
10554
10555 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
10556 // make sure they are all linked ok. The front-end sorts these resources and traverses the list of
10557 // "uniforms" to find the range for each resource. A bug there was causing some resource ranges to
10558 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)10559 TEST_P(GLSLTest_ES31, MixOfAllResources)
10560 {
10561 // http://anglebug.com/5072
10562 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
10563
10564 constexpr char kComputeShader[] = R"(#version 310 es
10565 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10566 layout(binding = 1, std430) buffer Output {
10567 uint ubo_value;
10568 uint default_value;
10569 uint sampler_value;
10570 uint ac_value;
10571 uint image_value;
10572 } outbuf;
10573 uniform Input {
10574 uint input_value;
10575 } inbuf;
10576 uniform uint default_uniform;
10577 uniform sampler2D smplr;
10578 layout(binding=0) uniform atomic_uint ac;
10579 layout(r32ui) uniform highp readonly uimage2D image;
10580
10581 void main(void)
10582 {
10583 outbuf.ubo_value = inbuf.input_value;
10584 outbuf.default_value = default_uniform;
10585 outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
10586 outbuf.ac_value = atomicCounterIncrement(ac);
10587 outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
10588 }
10589 )";
10590 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10591 EXPECT_GL_NO_ERROR();
10592
10593 glUseProgram(program);
10594
10595 unsigned int inputData = 89u;
10596 GLBuffer inputBuffer;
10597 glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
10598 glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
10599 GLuint inputBufferIndex = glGetUniformBlockIndex(program.get(), "Input");
10600 ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
10601 glUniformBlockBinding(program.get(), inputBufferIndex, 0);
10602 glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
10603
10604 unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
10605 0x13579BDFu};
10606 GLBuffer outputBuffer;
10607 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10608 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
10609 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10610 EXPECT_GL_NO_ERROR();
10611
10612 unsigned int uniformData = 456u;
10613 GLint uniformLocation = glGetUniformLocation(program, "default_uniform");
10614 ASSERT_NE(uniformLocation, -1);
10615 glUniform1ui(uniformLocation, uniformData);
10616
10617 unsigned int acData = 2u;
10618 GLBuffer atomicCounterBuffer;
10619 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10620 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10621 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10622 EXPECT_GL_NO_ERROR();
10623
10624 unsigned int imageData = 33u;
10625 GLTexture image;
10626 glBindTexture(GL_TEXTURE_2D, image);
10627 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
10628 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
10629 glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
10630 EXPECT_GL_NO_ERROR();
10631
10632 GLColor textureData(127, 18, 189, 211);
10633 GLTexture texture;
10634 glBindTexture(GL_TEXTURE_2D, texture);
10635 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
10636 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10637 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10638 ASSERT_GL_NO_ERROR();
10639
10640 glDispatchCompute(1, 1, 1);
10641 EXPECT_GL_NO_ERROR();
10642
10643 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10644
10645 // read back
10646 const GLuint *ptr = reinterpret_cast<const GLuint *>(
10647 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10648 EXPECT_EQ(ptr[0], inputData);
10649 EXPECT_EQ(ptr[1], uniformData);
10650 EXPECT_NEAR(ptr[2], textureData.R, 1.0);
10651 EXPECT_EQ(ptr[3], acData);
10652 EXPECT_EQ(ptr[4], imageData);
10653
10654 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10655 }
10656
10657 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)10658 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
10659 {
10660 // http://anglebug.com/5546
10661 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
10662
10663 // anglebug.com/3832 - no sampler array params on Android
10664 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10665
10666 constexpr char kComputeShader[] = R"(#version 310 es
10667 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10668
10669 layout(binding = 1, std430) buffer Output {
10670 uint success;
10671 } outbuf;
10672
10673 uniform uint initialAcValue;
10674 uniform sampler2D smplr[2][3];
10675 layout(binding=0) uniform atomic_uint ac;
10676
10677 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
10678 {
10679 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
10680 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
10681 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
10682 uint aResult = atomicCounterIncrement(a);
10683
10684 return sExpect == sResult && aExpect == aResult;
10685 }
10686
10687 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
10688 {
10689 bool success = true;
10690 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
10691 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
10692 return success;
10693 }
10694
10695 void main(void)
10696 {
10697 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
10698 }
10699 )";
10700 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10701 EXPECT_GL_NO_ERROR();
10702
10703 glUseProgram(program);
10704
10705 unsigned int outputInitData = 0x12345678u;
10706 GLBuffer outputBuffer;
10707 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10708 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10709 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10710 EXPECT_GL_NO_ERROR();
10711
10712 unsigned int acData = 2u;
10713 GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
10714 ASSERT_NE(uniformLocation, -1);
10715 glUniform1ui(uniformLocation, acData);
10716
10717 GLBuffer atomicCounterBuffer;
10718 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10719 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10720 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10721 EXPECT_GL_NO_ERROR();
10722
10723 const std::array<GLColor, 6> kTextureData = {
10724 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
10725 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
10726 };
10727 GLTexture textures[2][3];
10728
10729 for (int dim1 = 0; dim1 < 2; ++dim1)
10730 {
10731 for (int dim2 = 0; dim2 < 3; ++dim2)
10732 {
10733 int textureUnit = dim1 * 3 + dim2;
10734 glActiveTexture(GL_TEXTURE0 + textureUnit);
10735 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
10736 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10737 &kTextureData[textureUnit]);
10738 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10739 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10740
10741 std::stringstream uniformName;
10742 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
10743 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10744 EXPECT_NE(samplerLocation, -1);
10745 glUniform1i(samplerLocation, textureUnit);
10746 }
10747 }
10748 ASSERT_GL_NO_ERROR();
10749
10750 glDispatchCompute(1, 1, 1);
10751 EXPECT_GL_NO_ERROR();
10752
10753 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10754
10755 // read back
10756 const GLuint *ptr = reinterpret_cast<const GLuint *>(
10757 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10758 EXPECT_EQ(ptr[0], 1u);
10759
10760 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10761 }
10762
10763 // Test that array of array of samplers used as function parameter with an index that has a
10764 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)10765 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
10766 {
10767 // http://anglebug.com/5546
10768 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
10769
10770 // anglebug.com/3832 - no sampler array params on Android
10771 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10772
10773 // Skip if EXT_gpu_shader5 is not enabled.
10774 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10775
10776 constexpr char kComputeShader[] = R"(#version 310 es
10777 #extension GL_EXT_gpu_shader5 : require
10778
10779 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10780
10781 layout(binding = 1, std430) buffer Output {
10782 uint success;
10783 } outbuf;
10784
10785 uniform sampler2D smplr[2][3];
10786 layout(binding=0) uniform atomic_uint ac;
10787
10788 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
10789 {
10790 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
10791 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
10792 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
10793 uint aResult = atomicCounter(a);
10794
10795 return sExpect == sResult && aExpect == aResult;
10796 }
10797
10798 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
10799 {
10800 bool success = true;
10801 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
10802 s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
10803 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
10804 s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
10805 return success;
10806 }
10807
10808 void main(void)
10809 {
10810 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
10811 }
10812 )";
10813 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10814 EXPECT_GL_NO_ERROR();
10815
10816 glUseProgram(program);
10817
10818 unsigned int outputInitData = 0x12345678u;
10819 GLBuffer outputBuffer;
10820 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10821 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10822 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10823 EXPECT_GL_NO_ERROR();
10824
10825 unsigned int acData = 0u;
10826 GLBuffer atomicCounterBuffer;
10827 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10828 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10829 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10830 EXPECT_GL_NO_ERROR();
10831
10832 const std::array<GLColor, 6> kTextureData = {
10833 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
10834 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
10835 };
10836 GLTexture textures[2][3];
10837
10838 for (int dim1 = 0; dim1 < 2; ++dim1)
10839 {
10840 for (int dim2 = 0; dim2 < 3; ++dim2)
10841 {
10842 int textureUnit = dim1 * 3 + dim2;
10843 glActiveTexture(GL_TEXTURE0 + textureUnit);
10844 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
10845 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10846 &kTextureData[textureUnit]);
10847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10849
10850 std::stringstream uniformName;
10851 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
10852 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10853 EXPECT_NE(samplerLocation, -1);
10854 glUniform1i(samplerLocation, textureUnit);
10855 }
10856 }
10857 ASSERT_GL_NO_ERROR();
10858
10859 glDispatchCompute(1, 1, 1);
10860 EXPECT_GL_NO_ERROR();
10861
10862 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10863
10864 // read back
10865 const GLuint *ptr = reinterpret_cast<const GLuint *>(
10866 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10867 EXPECT_EQ(ptr[0], 1u);
10868
10869 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10870 }
10871
10872 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndex)10873 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndex)
10874 {
10875 // Skip if EXT_gpu_shader5 is not enabled.
10876 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10877
10878 int maxTextureImageUnits = 0;
10879 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
10880 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
10881
10882 // anglebug.com/3832 - no sampler array params on Android
10883 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10884
10885 // http://anglebug.com/5546
10886 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
10887
10888 constexpr char kComputeShader[] = R"(#version 310 es
10889 #extension GL_EXT_gpu_shader5 : require
10890
10891 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10892
10893 layout(binding = 1, std430) buffer Output {
10894 uint success;
10895 } outbuf;
10896
10897 uniform sampler2D smplr[2][3][4];
10898 layout(binding=0) uniform atomic_uint ac;
10899
10900 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
10901 {
10902 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
10903 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
10904 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
10905 uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
10906 uint aResult = atomicCounter(a);
10907
10908 return sExpect == sResult && aExpect == aResult;
10909 }
10910
10911 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
10912 {
10913 bool success = true;
10914 // [0][0]
10915 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
10916 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
10917 // [1][0]
10918 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
10919 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
10920 // [0][1]
10921 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
10922 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
10923 // [0][2]
10924 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
10925 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
10926 // [1][1]
10927 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
10928 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
10929 // [1][2]
10930 uint acValue = atomicCounterIncrement(ac); // Returns 5
10931 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
10932 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
10933
10934 return success;
10935 }
10936
10937 void main(void)
10938 {
10939 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
10940 }
10941 )";
10942 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10943 EXPECT_GL_NO_ERROR();
10944
10945 glUseProgram(program);
10946
10947 unsigned int outputInitData = 0x12345678u;
10948 GLBuffer outputBuffer;
10949 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10950 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10951 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10952 EXPECT_GL_NO_ERROR();
10953
10954 unsigned int acData = 0u;
10955 GLBuffer atomicCounterBuffer;
10956 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10957 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10958 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10959 EXPECT_GL_NO_ERROR();
10960
10961 const std::array<GLColor, 24> kTextureData = {
10962 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
10963 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
10964 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
10965 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
10966 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
10967 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
10968 };
10969 GLTexture textures[2][3][4];
10970
10971 for (int dim1 = 0; dim1 < 2; ++dim1)
10972 {
10973 for (int dim2 = 0; dim2 < 3; ++dim2)
10974 {
10975 for (int dim3 = 0; dim3 < 4; ++dim3)
10976 {
10977 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
10978 glActiveTexture(GL_TEXTURE0 + textureUnit);
10979 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
10980 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10981 &kTextureData[textureUnit]);
10982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10983 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10984
10985 std::stringstream uniformName;
10986 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
10987 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10988 EXPECT_NE(samplerLocation, -1);
10989 glUniform1i(samplerLocation, textureUnit);
10990 }
10991 }
10992 }
10993 ASSERT_GL_NO_ERROR();
10994
10995 glDispatchCompute(1, 1, 1);
10996 EXPECT_GL_NO_ERROR();
10997
10998 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10999
11000 // read back
11001 const GLuint *ptr = reinterpret_cast<const GLuint *>(
11002 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
11003 EXPECT_EQ(ptr[0], 1u);
11004
11005 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11006 }
11007
11008 // Test that array of array of samplers can be indexed correctly with dynamic indices. Uses
11009 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)11010 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
11011 {
11012 // Skip if EXT_gpu_shader5 is not enabled.
11013 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
11014
11015 int maxTextureImageUnits = 0;
11016 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
11017 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
11018
11019 // http://anglebug.com/5072
11020 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
11021
11022 // anglebug.com/3832 - no sampler array params on Android
11023 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
11024
11025 // http://anglebug.com/5546
11026 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
11027
11028 constexpr char kComputeShader[] = R"(#version 310 es
11029 #extension GL_EXT_gpu_shader5 : require
11030
11031 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
11032
11033 layout(binding = 1, std430) buffer Output {
11034 uint success;
11035 } outbuf;
11036
11037 struct I
11038 {
11039 uint index;
11040 };
11041
11042 struct S
11043 {
11044 sampler2D smplr[4];
11045 I nested;
11046 };
11047
11048 struct T
11049 {
11050 S nested[3];
11051 uint tIndex;
11052 };
11053
11054 uniform T u[2];
11055
11056 uint getValue(in sampler2D s)
11057 {
11058 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
11059 }
11060
11061 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
11062 {
11063 uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
11064 getValue(s[2]), getValue(s[3]));
11065
11066 return sExpect == sResult;
11067 }
11068
11069 bool samplerTest(T t, uint N)
11070 {
11071 // u[N].tIndex == 0 + N*4
11072 // u[N].nested[0].nested.index == 1 + N*4
11073 // u[N].nested[1].nested.index == 2 + N*4
11074 // u[N].nested[2].nested.index == 3 + N*4
11075
11076 uvec4 colorOffset = N * 3u * 4u * uvec4(8);
11077
11078 bool success = true;
11079 // [N][0]
11080 success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
11081 t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
11082 // [N][1]
11083 success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
11084 t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
11085 // [N][2]
11086 success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
11087 t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
11088
11089 return success;
11090 }
11091
11092 bool uniformTest(T t, uint N)
11093 {
11094 // Also verify that expressions that involve structs-with-samplers are correct when not
11095 // referecing the sampler.
11096
11097 bool success = true;
11098 success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
11099 success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
11100 success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
11101
11102 success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
11103 && success;
11104 success = (t.nested[t.nested[0].nested.index - t.tIndex ].nested.index - t.tIndex == 2u)
11105 && success;
11106 success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
11107 && success;
11108
11109 success = (t.nested[
11110 t.nested[
11111 t.nested[2].nested.index - t.tIndex - 1u // 2
11112 ].nested.index - t.tIndex - 2u // 1
11113 ].nested.index - t.tIndex // 2
11114 == 2u) && success;
11115
11116 return success;
11117 }
11118
11119 void main(void)
11120 {
11121 bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
11122 && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
11123 outbuf.success = uint(success);
11124 }
11125 )";
11126 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
11127 EXPECT_GL_NO_ERROR();
11128
11129 glUseProgram(program);
11130
11131 unsigned int outputInitData = 0x12345678u;
11132 GLBuffer outputBuffer;
11133 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
11134 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11135 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
11136 EXPECT_GL_NO_ERROR();
11137
11138 const std::array<GLColor, 24> kTextureData = {
11139 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
11140 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
11141 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
11142 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
11143 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
11144 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
11145 };
11146 GLTexture textures[2][3][4];
11147
11148 for (int dim1 = 0; dim1 < 2; ++dim1)
11149 {
11150 for (int dim2 = 0; dim2 < 3; ++dim2)
11151 {
11152 for (int dim3 = 0; dim3 < 4; ++dim3)
11153 {
11154 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
11155 glActiveTexture(GL_TEXTURE0 + textureUnit);
11156 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
11157 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11158 &kTextureData[textureUnit]);
11159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11161
11162 std::stringstream uniformName;
11163 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
11164 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
11165 EXPECT_NE(samplerLocation, -1);
11166 glUniform1i(samplerLocation, textureUnit);
11167 }
11168
11169 std::stringstream uniformName;
11170 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
11171 GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
11172 EXPECT_NE(nestedIndexLocation, -1);
11173 glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
11174 }
11175
11176 std::stringstream uniformName;
11177 uniformName << "u[" << dim1 << "].tIndex";
11178 GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
11179 EXPECT_NE(indexLocation, -1);
11180 glUniform1ui(indexLocation, dim1 * 4);
11181 }
11182 ASSERT_GL_NO_ERROR();
11183
11184 glDispatchCompute(1, 1, 1);
11185 EXPECT_GL_NO_ERROR();
11186
11187 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11188
11189 // read back
11190 const GLuint *ptr = reinterpret_cast<const GLuint *>(
11191 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
11192 EXPECT_EQ(ptr[0], 1u);
11193
11194 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11195 }
11196
11197 // Test that array of array of samplers work when indexed with an expression that's derived from an
11198 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)11199 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
11200 {
11201 // Skip if EXT_gpu_shader5 is not enabled.
11202 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
11203
11204 // anglebug.com/3832 - no sampler array params on Android
11205 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
11206
11207 constexpr char kComputeShader[] = R"(#version 310 es
11208 #extension GL_EXT_gpu_shader5 : require
11209
11210 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
11211
11212 layout(binding = 1, std430) buffer Output {
11213 uint success;
11214 } outbuf;
11215
11216 uniform sampler2D smplr[2][3];
11217
11218 uint getValue(in sampler2D s)
11219 {
11220 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
11221 }
11222
11223 bool runTest(in sampler2D s[2][3])
11224 {
11225 // s[0][0] should contain 2
11226 // s[0][1] should contain 0
11227 // s[0][2] should contain 1
11228 // s[1][0] should contain 1
11229 // s[1][1] should contain 2
11230 // s[1][2] should contain 0
11231
11232 uint result = getValue(
11233 s[
11234 getValue(
11235 s[
11236 getValue(s[0][1]) // 0
11237 ][
11238 getValue(s[0][0]) // 2
11239 ]
11240 ) // s[0][2] -> 1
11241 ][
11242 getValue(
11243 s[
11244 getValue(s[1][0]) // 1
11245 ][
11246 getValue(s[1][1]) // 2
11247 ]
11248 ) // s[1][2] -> 0
11249 ]
11250 ); // s[1][0] -> 1
11251
11252 return result == 1u;
11253 }
11254
11255 void main(void)
11256 {
11257 outbuf.success = uint(runTest(smplr));
11258 }
11259 )";
11260 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
11261 EXPECT_GL_NO_ERROR();
11262
11263 glUseProgram(program);
11264
11265 unsigned int outputInitData = 0x12345678u;
11266 GLBuffer outputBuffer;
11267 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
11268 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11269 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
11270 EXPECT_GL_NO_ERROR();
11271
11272 const std::array<GLColor, 6> kTextureData = {
11273 GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
11274 GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
11275 };
11276 GLTexture textures[2][3];
11277
11278 for (int dim1 = 0; dim1 < 2; ++dim1)
11279 {
11280 for (int dim2 = 0; dim2 < 3; ++dim2)
11281 {
11282 int textureUnit = dim1 * 3 + dim2;
11283 glActiveTexture(GL_TEXTURE0 + textureUnit);
11284 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
11285 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11286 &kTextureData[textureUnit]);
11287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11289
11290 std::stringstream uniformName;
11291 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
11292 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
11293 EXPECT_NE(samplerLocation, -1);
11294 glUniform1i(samplerLocation, textureUnit);
11295 }
11296 }
11297 ASSERT_GL_NO_ERROR();
11298
11299 glDispatchCompute(1, 1, 1);
11300 EXPECT_GL_NO_ERROR();
11301
11302 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11303
11304 // read back
11305 const GLuint *ptr = reinterpret_cast<const GLuint *>(
11306 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
11307 EXPECT_EQ(ptr[0], 1u);
11308
11309 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11310 }
11311
11312 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)11313 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
11314 {
11315 // http://anglebug.com/3831
11316 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
11317
11318 // Fails on windows AMD on GL: http://anglebug.com/3838
11319 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11320 // http://anglebug.com/5384
11321 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
11322
11323 // Fails on D3D due to mistranslation: http://anglebug.com/3841
11324 ANGLE_SKIP_TEST_IF(IsD3D11());
11325
11326 constexpr char kCS[] = R"(#version 310 es
11327 precision highp float;
11328 layout(local_size_x=1) in;
11329
11330 layout(std140, column_major) uniform Ubo
11331 {
11332 mat4 m1;
11333 layout(row_major) mat4 m2;
11334 } ubo;
11335
11336 layout(std140, row_major, binding = 0) buffer Ssbo
11337 {
11338 layout(column_major) mat4 m1;
11339 mat4 m2;
11340 } ssbo;
11341
11342 layout(std140, binding = 1) buffer Result
11343 {
11344 uint success;
11345 } resultOut;
11346
11347 void main()
11348 {
11349 bool result = true;
11350
11351 // Only assign to SSBO from a single invocation.
11352 if (gl_GlobalInvocationID.x == 0u)
11353 {
11354 if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
11355 {
11356 result = false;
11357 }
11358
11359 resultOut.success = uint(result);
11360 }
11361 })";
11362
11363 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11364 EXPECT_GL_NO_ERROR();
11365
11366 constexpr size_t kMatrixCount = 2;
11367 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11368 {4, 4},
11369 {4, 4},
11370 };
11371 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11372 true,
11373 false,
11374 };
11375
11376 float data[kMatrixCount * 4 * 4] = {};
11377 float zeros[kMatrixCount * 4 * 4] = {};
11378
11379 const uint32_t size =
11380 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11381
11382 GLBuffer ubo, ssbo;
11383
11384 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11385 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
11386 EXPECT_GL_NO_ERROR();
11387
11388 GLBuffer outputBuffer;
11389 CreateOutputBuffer(&outputBuffer, 1);
11390
11391 glUseProgram(program);
11392 glDispatchCompute(1, 1, 1);
11393 EXPECT_GL_NO_ERROR();
11394 EXPECT_TRUE(VerifySuccess(outputBuffer));
11395
11396 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
11397 }
11398
11399 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)11400 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
11401 {
11402 // Fails on windows AMD on GL: http://anglebug.com/3838
11403 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11404 // http://anglebug.com/5384
11405 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
11406
11407 // Fails on D3D due to mistranslation: http://anglebug.com/3841
11408 ANGLE_SKIP_TEST_IF(IsD3D11());
11409
11410 // Fails compiling shader on Android/Vulkan. http://anglebug.com/4290
11411 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
11412
11413 // Fails on ARM on Vulkan. http://anglebug.com/4492
11414 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
11415
11416 constexpr char kCS[] = R"(#version 310 es
11417 precision highp float;
11418 layout(local_size_x=1) in;
11419
11420 layout(std140, column_major) uniform Ubo
11421 {
11422 mat4 m1;
11423 layout(row_major) mat4 m2[2][3];
11424 } ubo;
11425
11426 layout(std140, row_major, binding = 0) buffer Ssbo
11427 {
11428 layout(column_major) mat4 m1;
11429 mat4 m2[2][3];
11430 } ssbo;
11431
11432 layout(std140, binding = 1) buffer Result
11433 {
11434 uint success;
11435 } resultOut;
11436
11437 void main()
11438 {
11439 bool result = true;
11440
11441 // Only assign to SSBO from a single invocation.
11442 if (gl_GlobalInvocationID.x == 0u)
11443 {
11444 ssbo.m1 = ubo.m1;
11445 ssbo.m2 = ubo.m2;
11446
11447 resultOut.success = uint(result);
11448 }
11449 })";
11450
11451 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11452 EXPECT_GL_NO_ERROR();
11453
11454 constexpr size_t kMatrixCount = 7;
11455 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11456 {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
11457 };
11458 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11459 true, false, false, false, false, false, false,
11460 };
11461
11462 float data[kMatrixCount * 4 * 4] = {};
11463 float zeros[kMatrixCount * 4 * 4] = {};
11464
11465 const uint32_t size =
11466 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11467
11468 GLBuffer ubo, ssbo;
11469
11470 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11471 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
11472 EXPECT_GL_NO_ERROR();
11473
11474 GLBuffer outputBuffer;
11475 CreateOutputBuffer(&outputBuffer, 1);
11476
11477 glUseProgram(program);
11478 glDispatchCompute(1, 1, 1);
11479 EXPECT_GL_NO_ERROR();
11480 EXPECT_TRUE(VerifySuccess(outputBuffer));
11481
11482 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
11483 }
11484
11485 // Verify that types used differently (in different block storages, differently qualified etc) work
11486 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)11487 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
11488 {
11489 constexpr char kCS[] = R"(#version 310 es
11490 precision highp float;
11491 layout(local_size_x=1) in;
11492
11493 struct Inner
11494 {
11495 mat3x2 m;
11496 float f[3];
11497 uvec2 u[2][4];
11498 ivec3 i;
11499 mat2x3 m2[3][2];
11500 };
11501
11502 struct Outer
11503 {
11504 Inner i[2];
11505 };
11506
11507 layout(std140, column_major) uniform Ubo140c
11508 {
11509 mat2 m;
11510 layout(row_major) Outer o;
11511 } ubo140cIn;
11512
11513 layout(std430, row_major, binding = 0) buffer Ubo430r
11514 {
11515 mat2 m;
11516 layout(column_major) Outer o;
11517 } ubo430rIn;
11518
11519 layout(std140, column_major, binding = 1) buffer Ssbo140c
11520 {
11521 layout(row_major) mat2 m[2];
11522 Outer o;
11523 layout(row_major) Inner i;
11524 } ssbo140cOut;
11525
11526 layout(std430, row_major, binding = 2) buffer Ssbo430r
11527 {
11528 layout(column_major) mat2 m[2];
11529 Outer o;
11530 layout(column_major) Inner i;
11531 } ssbo430rOut;
11532
11533 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
11534 {
11535 ssbo140cOut.o.i[innerIndex].u = u;
11536 }
11537
11538 void writeBlockArgToStd140(Inner i, int innerIndex)
11539 {
11540 ssbo140cOut.o.i[innerIndex] = i;
11541 }
11542
11543 mat2x3[3][2] readFromStd140(int innerIndex)
11544 {
11545 return ubo140cIn.o.i[0].m2;
11546 }
11547
11548 Inner readBlockFromStd430(int innerIndex)
11549 {
11550 return ubo430rIn.o.i[innerIndex];
11551 }
11552
11553 void copyFromStd140(out Inner i)
11554 {
11555 i = ubo140cIn.o.i[1];
11556 }
11557
11558 void main(){
11559 // Directly copy from one layout to another.
11560 ssbo140cOut.m[0] = ubo140cIn.m;
11561 ssbo140cOut.m[1] = ubo430rIn.m;
11562 ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
11563 ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
11564 ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
11565
11566 // Read from block and pass to function.
11567 writeArgToStd140(ubo140cIn.o.i[0].u, 0);
11568 writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
11569
11570 // Have function return value read from block.
11571 ssbo140cOut.o.i[0].m2 = readFromStd140(0);
11572
11573 // Have function fill in value as out parameter.
11574 copyFromStd140(ssbo140cOut.i);
11575
11576 // Initialize local variable.
11577 mat2 mStd140 = ubo140cIn.m;
11578
11579 // Copy to variable, through multiple assignments.
11580 mat2 mStd430, temp;
11581 mStd430 = temp = ubo430rIn.m;
11582
11583 // Copy from local variable
11584 ssbo430rOut.m[0] = mStd140;
11585 ssbo430rOut.m[1] = mStd430;
11586
11587 // Construct from struct.
11588 Inner iStd140 = ubo140cIn.o.i[1];
11589 Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
11590
11591 // Copy struct from local variable.
11592 ssbo430rOut.o = oStd140;
11593
11594 // Construct from arrays
11595 Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
11596 ubo430rIn.o.i[1].f,
11597 ubo430rIn.o.i[1].u,
11598 ubo430rIn.o.i[1].i,
11599 ubo430rIn.o.i[1].m2);
11600 ssbo430rOut.i = iStd430;
11601 })";
11602
11603 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11604 EXPECT_GL_NO_ERROR();
11605
11606 // Test data, laid out with padding (0) based on std140/std430 rules.
11607 // clang-format off
11608 const std::vector<float> ubo140cData = {
11609 // m (mat2, column-major)
11610 1, 2, 0, 0, 3, 4, 0, 0,
11611
11612 // o.i[0].m (mat3x2, row-major)
11613 5, 7, 9, 0, 6, 8, 10, 0,
11614 // o.i[0].f (float[3])
11615 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
11616 // o.i[0].u (uvec2[2][4])
11617 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
11618 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
11619 // o.i[0].i (ivec3)
11620 31, 32, 33, 0,
11621 // o.i[0].m2 (mat2x3[3][2], row-major)
11622 34, 37, 0, 0, 35, 38, 0, 0, 36, 39, 0, 0,
11623 40, 43, 0, 0, 41, 44, 0, 0, 42, 45, 0, 0,
11624 46, 49, 0, 0, 47, 50, 0, 0, 48, 51, 0, 0,
11625 52, 55, 0, 0, 53, 56, 0, 0, 54, 57, 0, 0,
11626 58, 61, 0, 0, 59, 62, 0, 0, 60, 63, 0, 0,
11627 64, 67, 0, 0, 65, 68, 0, 0, 66, 69, 0, 0,
11628
11629 // o.i[1].m (mat3x2, row-major)
11630 70, 72, 74, 0, 71, 73, 75, 0,
11631 // o.i[1].f (float[3])
11632 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
11633 // o.i[1].u (uvec2[2][4])
11634 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
11635 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
11636 // o.i[1].i (ivec3)
11637 96, 97, 98, 0,
11638 // o.i[1].m2 (mat2x3[3][2], row-major)
11639 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
11640 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
11641 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
11642 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
11643 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
11644 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
11645 };
11646 const std::vector<float> ubo430rData = {
11647 // m (mat2, row-major)
11648 135, 137, 136, 138,
11649
11650 // o.i[0].m (mat3x2, column-major)
11651 139, 140, 141, 142, 143, 144,
11652 // o.i[0].f (float[3])
11653 146, 147, 148, 0,
11654 // o.i[0].u (uvec2[2][4])
11655 149, 150, 151, 152, 153, 154, 155, 156,
11656 157, 158, 159, 160, 161, 162, 163, 164, 0, 0,
11657 // o.i[0].i (ivec3)
11658 165, 166, 167, 0,
11659 // o.i[0].m2 (mat2x3[3][2], column-major)
11660 168, 169, 170, 0, 171, 172, 173, 0,
11661 174, 175, 176, 0, 177, 178, 179, 0,
11662 180, 181, 182, 0, 183, 184, 185, 0,
11663 186, 187, 188, 0, 189, 190, 191, 0,
11664 192, 193, 194, 0, 195, 196, 197, 0,
11665 198, 199, 200, 0, 201, 202, 203, 0,
11666
11667 // o.i[1].m (mat3x2, column-major)
11668 204, 205, 206, 207, 208, 209,
11669 // o.i[1].f (float[3])
11670 211, 212, 213, 0,
11671 // o.i[1].u (uvec2[2][4])
11672 214, 215, 216, 217, 218, 219, 220, 221,
11673 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
11674 // o.i[1].i (ivec3)
11675 230, 231, 232, 0,
11676 // o.i[1].m2 (mat2x3[3][2], column-major)
11677 233, 234, 235, 0, 236, 237, 238, 0,
11678 239, 240, 241, 0, 242, 243, 244, 0,
11679 245, 246, 247, 0, 248, 249, 250, 0,
11680 251, 252, 253, 0, 254, 255, 256, 0,
11681 257, 258, 259, 0, 260, 261, 262, 0,
11682 263, 264, 265, 0, 266, 267, 268, 0,
11683 };
11684 const std::vector<float> ssbo140cExpect = {
11685 // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
11686 1, 3, 0, 0, 2, 4, 0, 0,
11687 135, 137, 0, 0, 136, 138, 0, 0,
11688
11689 // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
11690 5, 6, 0, 0, 7, 8, 0, 0, 9, 10, 0, 0,
11691 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
11692 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
11693 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
11694 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
11695 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
11696 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
11697 31, 32, 33, 0,
11698 // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
11699 34, 35, 36, 0, 37, 38, 39, 0,
11700 40, 41, 42, 0, 43, 44, 45, 0,
11701 46, 47, 48, 0, 49, 50, 51, 0,
11702 52, 53, 54, 0, 55, 56, 57, 0,
11703 58, 59, 60, 0, 61, 62, 63, 0,
11704 64, 65, 66, 0, 67, 68, 69, 0,
11705
11706 // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
11707 139, 140, 0, 0, 141, 142, 0, 0, 143, 144, 0, 0,
11708 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
11709 146, 0, 0, 0, 147, 0, 0, 0, 148, 0, 0, 0,
11710 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
11711 149, 150, 0, 0, 151, 152, 0, 0, 153, 154, 0, 0, 155, 156, 0, 0,
11712 157, 158, 0, 0, 159, 160, 0, 0, 161, 162, 0, 0, 163, 164, 0, 0,
11713 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
11714 165, 166, 167, 0,
11715 // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
11716 168, 169, 170, 0, 171, 172, 173, 0,
11717 174, 175, 176, 0, 177, 178, 179, 0,
11718 180, 181, 182, 0, 183, 184, 185, 0,
11719 186, 187, 188, 0, 189, 190, 191, 0,
11720 192, 193, 194, 0, 195, 196, 197, 0,
11721 198, 199, 200, 0, 201, 202, 203, 0,
11722
11723 // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
11724 70, 72, 74, 0, 71, 73, 75, 0,
11725 // i.f (float[3]), copied from ubo140cIn.o.i[1].f
11726 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
11727 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
11728 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
11729 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
11730 // i.i (ivec3), copied from ubo140cIn.o.i[1].i
11731 96, 97, 98, 0,
11732 // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
11733 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
11734 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
11735 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
11736 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
11737 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
11738 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
11739 };
11740 const std::vector<float> ssbo430rExpect = {
11741 // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
11742 1, 2, 3, 4,
11743 135, 136, 137, 138,
11744
11745 // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
11746 70, 72, 74, 0, 71, 73, 75, 0,
11747 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
11748 77, 78, 79, 0,
11749 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
11750 80, 81, 82, 83, 84, 85, 86, 87,
11751 88, 89, 90, 91, 92, 93, 94, 95,
11752 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
11753 96, 97, 98, 0,
11754 // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
11755 99, 102, 100, 103, 101, 104,
11756 105, 108, 106, 109, 107, 110,
11757 111, 114, 112, 115, 113, 116,
11758 117, 120, 118, 121, 119, 122,
11759 123, 126, 124, 127, 125, 128,
11760 129, 132, 130, 133, 131, 134,
11761
11762 // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
11763 204, 206, 208, 0, 205, 207, 209, 0,
11764 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
11765 211, 212, 213, 0,
11766 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
11767 214, 215, 216, 217, 218, 219, 220, 221,
11768 222, 223, 224, 225, 226, 227, 228, 229,
11769 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
11770 230, 231, 232, 0,
11771 // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
11772 233, 236, 234, 237, 235, 238,
11773 239, 242, 240, 243, 241, 244,
11774 245, 248, 246, 249, 247, 250,
11775 251, 254, 252, 255, 253, 256,
11776 257, 260, 258, 261, 259, 262,
11777 263, 266, 264, 267, 265, 268,
11778
11779 // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
11780 204, 205, 206, 207, 208, 209,
11781 // i.f (float[3]), copied from ubo430rIn.o.i[1].f
11782 211, 212, 213, 0,
11783 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
11784 214, 215, 216, 217, 218, 219, 220, 221,
11785 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
11786 // i.i (ivec3), copied from ubo430rIn.o.i[1].i
11787 230, 231, 232, 0,
11788 // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
11789 233, 234, 235, 0, 236, 237, 238, 0,
11790 239, 240, 241, 0, 242, 243, 244, 0,
11791 245, 246, 247, 0, 248, 249, 250, 0,
11792 251, 252, 253, 0, 254, 255, 256, 0,
11793 257, 258, 259, 0, 260, 261, 262, 0,
11794 263, 264, 265, 0, 266, 267, 268, 0,
11795 };
11796 const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
11797 // clang-format on
11798
11799 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
11800 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
11801
11802 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
11803 static_cast<uint32_t>(ubo140cData.size()), true);
11804 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
11805 static_cast<uint32_t>(ubo430rData.size()), false);
11806 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
11807 static_cast<uint32_t>(ssbo140cExpect.size()), false);
11808 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
11809 static_cast<uint32_t>(ssbo430rExpect.size()), false);
11810 EXPECT_GL_NO_ERROR();
11811
11812 glUseProgram(program);
11813 glDispatchCompute(1, 1, 1);
11814 EXPECT_GL_NO_ERROR();
11815
11816 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
11817 static_cast<uint32_t>(ssbo140cExpect.size())));
11818 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
11819 static_cast<uint32_t>(ssbo430rExpect.size())));
11820 }
11821
11822 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)11823 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
11824 {
11825 constexpr char kCS[] = R"(#version 310 es
11826 precision highp float;
11827 layout(local_size_x=1) in;
11828
11829 struct Inner
11830 {
11831 bool b;
11832 bvec2 b2;
11833 bvec3 b3;
11834 bvec4 b4;
11835 bool ba[5];
11836 bvec2 b2a[2][3];
11837 };
11838
11839 struct Outer
11840 {
11841 Inner i[2];
11842 };
11843
11844 layout(std140) uniform Ubo140
11845 {
11846 Outer o;
11847 };
11848
11849 layout(std430, binding = 0) buffer Ubo430
11850 {
11851 Outer o;
11852 } ubo430In;
11853
11854 layout(std140, binding = 1) buffer Ssbo140
11855 {
11856 bool valid;
11857 Inner i;
11858 } ssbo140Out;
11859
11860 layout(std430, binding = 2) buffer Ssbo430
11861 {
11862 bool valid;
11863 Inner i;
11864 };
11865
11866 void writeArgToStd430(bool ba[5])
11867 {
11868 i.ba = ba;
11869 }
11870
11871 bool[5] readFromStd430(uint innerIndex)
11872 {
11873 return ubo430In.o.i[innerIndex].ba;
11874 }
11875
11876 void copyFromStd430(out bvec2 b2a[2][3])
11877 {
11878 b2a = ubo430In.o.i[0].b2a;
11879 }
11880
11881 bool destroyContent(inout Inner iOut)
11882 {
11883 iOut.b = true;
11884 iOut.b2 = bvec2(true);
11885 iOut.b3 = bvec3(true);
11886 iOut.b4 = bvec4(true);
11887 iOut.ba = bool[5](true, true, true, true, true);
11888 bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
11889 iOut.b2a = bvec2[2][3](true3, true3);
11890 return true;
11891 }
11892
11893 void main(){
11894 // Directly copy from one layout to another.
11895 i.b = o.i[0].b;
11896 i.b2 = o.i[0].b2;
11897 i.b2a = o.i[0].b2a;
11898
11899 // Copy to temp with swizzle.
11900 bvec4 t1 = o.i[0].b3.yxzy;
11901 bvec4 t2 = o.i[0].b4.xxyy;
11902 bvec4 t3 = o.i[0].b4.zzww;
11903
11904 // Copy from temp with swizzle.
11905 i.b3 = t1.ywz;
11906 i.b4.yz = bvec2(t2.z, t3.y);
11907 i.b4.wx = bvec2(t3.w, t2.x);
11908
11909 // Copy by passing argument to function.
11910 writeArgToStd430(o.i[0].ba);
11911
11912 // Copy by return value.
11913 ssbo140Out.i.ba = readFromStd430(0u);
11914
11915 // Copy by out parameter.
11916 copyFromStd430(ssbo140Out.i.b2a);
11917
11918 // Logical operations
11919 uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
11920 ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
11921 ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
11922 ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
11923 ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
11924
11925 ssbo140Out.valid = true;
11926 ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
11927 ssbo140Out.valid = ssbo140Out.valid &&
11928 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])));
11929 ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
11930 for (int x = 0; x < o.i[1].b2a.length(); ++x)
11931 {
11932 for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
11933 {
11934 ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
11935 }
11936 }
11937
11938 valid = o.i[1] == ubo430In.o.i[1];
11939
11940 // Make sure short-circuiting behavior is correct.
11941 bool falseVar = !valid && destroyContent(i);
11942 if (falseVar && destroyContent(ssbo140Out.i))
11943 {
11944 valid = false;
11945 }
11946
11947 if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
11948 {
11949 }
11950 else
11951 {
11952 ssbo140Out.valid = false;
11953 }
11954 })";
11955
11956 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11957 EXPECT_GL_NO_ERROR();
11958
11959 // Test data, laid out with padding (0) based on std140/std430 rules.
11960 // clang-format off
11961 const std::vector<uint32_t> ubo140Data = {
11962 // o.i[0].b (bool)
11963 true, 0,
11964 // o.i[0].b2 (bvec2)
11965 true, false,
11966 // o.i[0].b3 (bvec3)
11967 true, true, false, 0,
11968 // o.i[0].b4 (bvec4)
11969 false, true, false, true,
11970 // o.i[0].ba (bool[5])
11971 true, 0, 0, 0,
11972 false, 0, 0, 0,
11973 false, 0, 0, 0,
11974 true, 0, 0, 0,
11975 true, 0, 0, 0,
11976 // o.i[0].b2a (bool[2][3])
11977 false, true, 0, 0, true, true, 0, 0, true, false, 0, 0,
11978 true, false, 0, 0, false, false, 0, 0, true, true, 0, 0,
11979
11980 // o.i[1].b (bool)
11981 false, 0,
11982 // o.i[1].b2 (bvec2)
11983 true, true,
11984 // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
11985 false, true, true, 0,
11986 // o.i[1].b4 (bvec4)
11987 true, false, true, true,
11988 // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
11989 false, 0, 0, 0,
11990 true, 0, 0, 0,
11991 false, 0, 0, 0,
11992 false, 0, 0, 0,
11993 true, 0, 0, 0,
11994 // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
11995 false, false, 0, 0, false, true, 0, 0, false, false, 0, 0,
11996 true, false, 0, 0, true, true, 0, 0, true, false, 0, 0,
11997 };
11998 const std::vector<uint32_t> ubo430Data = {
11999 // o.i[0].b (bool)
12000 false, 0,
12001 // o.i[0].b2 (bvec2)
12002 true, true,
12003 // o.i[0].b3 (bvec3)
12004 false, false, true, 0,
12005 // o.i[0].b4 (bvec4)
12006 true, false, true, true,
12007 // o.i[0].ba (bool[5])
12008 false, false, false, true, false, 0,
12009 // o.i[0].b2a (bool[2][3])
12010 true, false, true, false, true, true,
12011 false, true, true, true, false, false, 0, 0,
12012
12013 // o.i[1] expected to be equal to ubo140In.o.i[1]
12014 // o.i[1].b (bool)
12015 false, 0,
12016 // o.i[1].b2 (bvec2)
12017 true, true,
12018 // o.i[1].b3 (bvec3)
12019 false, true, true, 0,
12020 // o.i[1].b4 (bvec4)
12021 true, false, true, true,
12022 // o.i[1].ba (bool[5])
12023 false, true, false, false, true, 0,
12024 // o.i[1].b2a (bvec2[2][3])
12025 false, false, false, true, false, false,
12026 true, false, true, true, true, false,
12027 };
12028 const std::vector<uint32_t> ssbo140Expect = {
12029 // valid, expected to be true
12030 true, 0, 0, 0,
12031
12032 // i.b (bool), ubo430In.o.i[0].b ? false : true
12033 true, 0,
12034 // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
12035 false, false,
12036 // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
12037 false, true, false, 0,
12038 // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
12039 true, true, true, false,
12040 // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
12041 false, 0, 0, 0,
12042 false, 0, 0, 0,
12043 false, 0, 0, 0,
12044 true, 0, 0, 0,
12045 false, 0, 0, 0,
12046 // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
12047 true, false, 0, 0, true, false, 0, 0, true, true, 0, 0,
12048 false, true, 0, 0, true, true, 0, 0, false, false, 0, 0,
12049 };
12050 const std::vector<uint32_t> ssbo430Expect = {
12051 // valid, expected to be true
12052 true, 0, 0, 0,
12053
12054 // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
12055 true, 0,
12056 // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
12057 true, false,
12058 // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
12059 true, true, false, 0,
12060 // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
12061 false, true, false, true,
12062 // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
12063 true, false, false, true, true, 0,
12064 // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
12065 false, true, true, true, true, false,
12066 true, false, false, false, true, true, 0, 0,
12067 };
12068 const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
12069 // clang-format on
12070
12071 GLBuffer uboStd140, uboStd430;
12072 GLBuffer ssboStd140, ssboStd430;
12073
12074 InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
12075 static_cast<uint32_t>(ubo140Data.size()), true);
12076 InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
12077 static_cast<uint32_t>(ubo430Data.size()), false);
12078 InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
12079 static_cast<uint32_t>(ssbo140Expect.size()), false);
12080 InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
12081 static_cast<uint32_t>(ssbo430Expect.size()), false);
12082 EXPECT_GL_NO_ERROR();
12083
12084 glUseProgram(program);
12085 glDispatchCompute(1, 1, 1);
12086 EXPECT_GL_NO_ERROR();
12087
12088 EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
12089 static_cast<uint32_t>(ssbo140Expect.size())));
12090 EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
12091 static_cast<uint32_t>(ssbo430Expect.size())));
12092 }
12093
12094 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)12095 TEST_P(GLSLTest_ES3, PreciseNotReserved)
12096 {
12097 // Skip in ES3.1+ as the precise keyword is reserved/core.
12098 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
12099 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
12100
12101 constexpr char kFS[] = R"(#version 300 es
12102 precision mediump float;
12103 in float precise;
12104 out vec4 my_FragColor;
12105 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
12106
12107 constexpr char kVS[] = R"(#version 300 es
12108 in vec4 a_position;
12109 out float precise;
12110 void main() { precise = a_position.x; gl_Position = a_position; })";
12111
12112 GLuint program = CompileProgram(kVS, kFS);
12113 EXPECT_NE(0u, program);
12114 }
12115
12116 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)12117 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
12118 {
12119 // Skip if EXT_gpu_shader5 is enabled.
12120 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12121 // Skip in ES3.2+ as the precise keyword is core.
12122 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
12123 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
12124
12125 constexpr char kFS[] = R"(#version 310 es
12126 precision mediump float;
12127 in float v_varying;
12128 out vec4 my_FragColor;
12129 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
12130
12131 constexpr char kVS[] = R"(#version 310 es
12132 in vec4 a_position;
12133 precise out float v_varying;
12134 void main() { v_varying = a_position.x; gl_Position = a_position; })";
12135
12136 // Should fail, as precise is a reserved keyword when the extension is not enabled.
12137 GLuint program = CompileProgram(kVS, kFS);
12138 EXPECT_EQ(0u, program);
12139 }
12140
12141 // Test that reusing the same variable name for different uses across stages links fine. Glslang
12142 // wrapper's SPIR-V transformation should ignore all names for non-shader-interface variables and
12143 // not get confused by them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)12144 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
12145 {
12146 // Fails to compile the fragment shader with error "undeclared identifier '_g'"
12147 // http://anglebug.com/4404
12148 ANGLE_SKIP_TEST_IF(IsD3D11());
12149
12150 constexpr char kVS[] = R"(#version 310 es
12151 precision mediump float;
12152 uniform highp vec4 a;
12153 in highp vec4 b;
12154 in highp vec4 c;
12155 in highp vec4 d;
12156 out highp vec4 e;
12157
12158 vec4 f(vec4 a)
12159 {
12160 return a;
12161 }
12162
12163 vec4 g(vec4 f)
12164 {
12165 return f + f;
12166 }
12167
12168 void main() {
12169 e = f(b) + a;
12170 gl_Position = g(c) + f(d);
12171 }
12172 )";
12173
12174 constexpr char kFS[] = R"(#version 310 es
12175 precision mediump float;
12176 in highp vec4 e;
12177 uniform sampler2D f;
12178 layout(rgba8) uniform highp readonly image2D g;
12179 uniform A
12180 {
12181 vec4 x;
12182 } c;
12183 layout(std140, binding=0) buffer B
12184 {
12185 vec4 x;
12186 } d[2];
12187 out vec4 col;
12188
12189 vec4 h(vec4 c)
12190 {
12191 return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
12192 }
12193
12194 vec4 i(vec4 x, vec4 y)
12195 {
12196 return vec4(x.xy, y.zw);
12197 }
12198
12199 void main() {
12200 col = h(e) + i(c.x, d[0].x) + d[1].x;
12201 }
12202 )";
12203
12204 GLuint program = CompileProgram(kVS, kFS);
12205 EXPECT_NE(0u, program);
12206 }
12207
12208 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)12209 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
12210 {
12211 constexpr char kVS[] = R"(#version 310 es
12212 precision mediump float;
12213 in highp vec4 variableWithSameName;
12214
12215 void main() {
12216 gl_Position = variableWithSameName;
12217 }
12218 )";
12219
12220 constexpr char kFS[] = R"(#version 310 es
12221 precision mediump float;
12222 uniform vec4 variableWithSameName;
12223 out vec4 col;
12224
12225 void main() {
12226 col = vec4(variableWithSameName);
12227 }
12228 )";
12229
12230 GLuint program = CompileProgram(kVS, kFS);
12231 EXPECT_NE(0u, program);
12232 }
12233
12234 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)12235 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
12236 {
12237 // Nvidia driver bug: http://anglebug.com/5240
12238 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
12239
12240 constexpr char kVSUnused[] = R"(#version 300 es
12241 precision highp float;
12242 uniform highp vec4 positionIn;
12243
12244 void main()
12245 {
12246 gl_Position = vec4(1, 0, 0, 1);
12247 })";
12248
12249 constexpr char kVSStaticUse[] = R"(#version 300 es
12250 precision highp float;
12251 uniform highp vec4 positionIn;
12252
12253 void main()
12254 {
12255 gl_Position = positionIn;
12256 })";
12257
12258 constexpr char kFSUnused[] = R"(#version 300 es
12259 precision highp float;
12260 uniform highp vec4 positionIn;
12261 out vec4 my_FragColor;
12262
12263 void main()
12264 {
12265 my_FragColor = vec4(1, 0, 0, 1);
12266 })";
12267
12268 constexpr char kFSStaticUse[] = R"(#version 300 es
12269 precision highp float;
12270 uniform mediump vec4 positionIn;
12271 out vec4 my_FragColor;
12272
12273 void main()
12274 {
12275 my_FragColor = vec4(1, 0, 0, positionIn.z);
12276 })";
12277
12278 GLuint program = 0;
12279
12280 program = CompileProgram(kVSUnused, kFSUnused);
12281 EXPECT_NE(0u, program);
12282
12283 program = CompileProgram(kVSUnused, kFSStaticUse);
12284 EXPECT_NE(0u, program);
12285
12286 program = CompileProgram(kVSStaticUse, kFSUnused);
12287 EXPECT_NE(0u, program);
12288
12289 program = CompileProgram(kVSStaticUse, kFSStaticUse);
12290 EXPECT_EQ(0u, program);
12291 }
12292
12293 // Validate that link fails when two instanceless interface blocks with different block names but
12294 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)12295 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
12296 {
12297 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12298
12299 constexpr char kVS[] = R"(#version 310 es
12300 in highp vec4 position;
12301 layout(binding = 0) buffer BlockA { mediump float a; };
12302 void main()
12303 {
12304 a = 0.0;
12305 gl_Position = position;
12306 })";
12307
12308 constexpr char kFS[] = R"(#version 310 es
12309 precision mediump float;
12310 layout(location = 0) out mediump vec4 color;
12311 uniform BlockB { float a; };
12312 void main()
12313 {
12314 color = vec4(a, a, a, 1.0);
12315 })";
12316
12317 GLuint program = CompileProgram(kVS, kFS);
12318 EXPECT_EQ(0u, program);
12319 }
12320
12321 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)12322 TEST_P(GLSLTest_ES31, IOBlockLocations)
12323 {
12324 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12325 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
12326
12327 constexpr char kVS[] = R"(#version 310 es
12328 #extension GL_EXT_shader_io_blocks : require
12329
12330 in highp vec4 position;
12331
12332 layout(location = 0) out vec4 aOut;
12333
12334 layout(location = 6) out VSBlock
12335 {
12336 vec4 b; // location 6
12337 vec4 c; // location 7
12338 layout(location = 1) vec4 d;
12339 vec4 e; // location 2
12340 vec4 f[2]; // locations 3 and 4
12341 } blockOut;
12342
12343 layout(location = 5) out vec4 gOut;
12344
12345 void main()
12346 {
12347 aOut = vec4(0.03, 0.06, 0.09, 0.12);
12348 blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
12349 blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
12350 blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
12351 blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
12352 blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
12353 blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
12354 gOut = vec4(0.84, 0.87, 0.9, 0.93);
12355 gl_Position = position;
12356 })";
12357
12358 constexpr char kGS[] = R"(#version 310 es
12359 #extension GL_EXT_geometry_shader : require
12360 layout (triangles) in;
12361 layout (triangle_strip, max_vertices = 3) out;
12362
12363 // Input varyings
12364 layout(location = 0) in vec4 aIn[];
12365
12366 layout(location = 6) in VSBlock
12367 {
12368 vec4 b;
12369 vec4 c;
12370 layout(location = 1) vec4 d;
12371 vec4 e;
12372 vec4 f[2];
12373 } blockIn[];
12374
12375 layout(location = 5) in vec4 gIn[];
12376
12377 // Output varyings
12378 layout(location = 1) out vec4 aOut;
12379
12380 layout(location = 0) out GSBlock
12381 {
12382 vec4 b; // location 0
12383 layout(location = 3) vec4 c;
12384 layout(location = 7) vec4 d;
12385 layout(location = 5) vec4 e[2];
12386 layout(location = 4) vec4 f;
12387 } blockOut;
12388
12389 layout(location = 2) out vec4 gOut;
12390
12391 void main()
12392 {
12393 int n;
12394 for (n = 0; n < gl_in.length(); n++)
12395 {
12396 gl_Position = gl_in[n].gl_Position;
12397
12398 aOut = aIn[n];
12399 blockOut.b = blockIn[n].b;
12400 blockOut.c = blockIn[n].c;
12401 blockOut.d = blockIn[n].d;
12402 blockOut.e[0] = blockIn[n].e;
12403 blockOut.e[1] = blockIn[n].f[0];
12404 blockOut.f = blockIn[n].f[1];
12405 gOut = gIn[n];
12406
12407 EmitVertex();
12408 }
12409 EndPrimitive();
12410 })";
12411
12412 constexpr char kFS[] = R"(#version 310 es
12413 #extension GL_EXT_shader_io_blocks : require
12414 precision mediump float;
12415
12416 layout(location = 0) out mediump vec4 color;
12417
12418 layout(location = 1) in vec4 aIn;
12419
12420 layout(location = 0) in GSBlock
12421 {
12422 vec4 b;
12423 layout(location = 3) vec4 c;
12424 layout(location = 7) vec4 d;
12425 layout(location = 5) vec4 e[2];
12426 layout(location = 4) vec4 f;
12427 } blockIn;
12428
12429 layout(location = 2) in vec4 gIn;
12430
12431 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
12432
12433 void main()
12434 {
12435 bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
12436 bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
12437 isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
12438 isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
12439 isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
12440 isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
12441 isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
12442 bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
12443
12444 color = vec4(passR, passG, passB, 1.0);
12445 })";
12446
12447 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
12448 EXPECT_GL_NO_ERROR();
12449
12450 GLTexture color;
12451 glBindTexture(GL_TEXTURE_2D, color);
12452 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12453
12454 GLFramebuffer fbo;
12455 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12456 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
12457
12458 drawQuad(program, "position", 0);
12459
12460 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
12461 }
12462
12463 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)12464 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
12465 {
12466 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12467
12468 constexpr char kVS[] = R"(#version 310 es
12469 #extension GL_EXT_shader_io_blocks : require
12470
12471 in highp vec4 position;
12472
12473 out VSBlock1
12474 {
12475 vec4 a;
12476 vec4 b[2];
12477 } blockOut1;
12478
12479 out VSBlock2
12480 {
12481 vec4 c[2];
12482 vec4 d;
12483 } blockOut2;
12484
12485 void main()
12486 {
12487 blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
12488 blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
12489 blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
12490 blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
12491 blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
12492 blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
12493 gl_Position = position;
12494 })";
12495
12496 constexpr char kFS[] = R"(#version 310 es
12497 #extension GL_EXT_shader_io_blocks : require
12498 precision mediump float;
12499
12500 layout(location = 0) out mediump vec4 color;
12501
12502 in VSBlock1
12503 {
12504 vec4 a;
12505 vec4 b[2];
12506 } blockIn1;
12507
12508 in VSBlock2
12509 {
12510 vec4 c[2];
12511 vec4 d;
12512 } blockIn2;
12513
12514 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
12515
12516 void main()
12517 {
12518 bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
12519 bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
12520 isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
12521 bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
12522 isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
12523 bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
12524
12525 color = vec4(passR, passG, passB, passA);
12526 })";
12527
12528 ANGLE_GL_PROGRAM(program, kVS, kFS);
12529 EXPECT_GL_NO_ERROR();
12530
12531 GLTexture color;
12532 glBindTexture(GL_TEXTURE_2D, color);
12533 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12534
12535 GLFramebuffer fbo;
12536 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12537 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
12538
12539 drawQuad(program, "position", 0);
12540
12541 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
12542 }
12543
12544 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)12545 TEST_P(GLSLTest_ES31, IOBlockArray)
12546 {
12547 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12548
12549 constexpr char kVS[] = R"(#version 310 es
12550 #extension GL_EXT_shader_io_blocks : require
12551
12552 in highp vec4 position;
12553
12554 out VSBlock1
12555 {
12556 vec4 b[2];
12557 } blockOut1[2];
12558
12559 out VSBlock2
12560 {
12561 vec4 d;
12562 } blockOut2[3];
12563
12564 void main()
12565 {
12566 blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
12567 blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
12568 blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
12569 blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
12570 blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
12571 blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
12572 blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
12573 gl_Position = position;
12574 })";
12575
12576 constexpr char kFS[] = R"(#version 310 es
12577 #extension GL_EXT_shader_io_blocks : require
12578 precision mediump float;
12579
12580 layout(location = 0) out mediump vec4 color;
12581
12582 in VSBlock1
12583 {
12584 vec4 b[2];
12585 } blockIn1[2];
12586
12587 in VSBlock2
12588 {
12589 vec4 d;
12590 } blockIn2[3];
12591
12592 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
12593
12594 void main()
12595 {
12596 bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
12597 isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
12598 bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
12599 isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
12600 bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
12601 bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
12602 isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
12603
12604 color = vec4(passR, passG, passB, passA);
12605 })";
12606
12607 ANGLE_GL_PROGRAM(program, kVS, kFS);
12608 EXPECT_GL_NO_ERROR();
12609
12610 GLTexture color;
12611 glBindTexture(GL_TEXTURE_2D, color);
12612 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12613
12614 GLFramebuffer fbo;
12615 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12616 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
12617
12618 drawQuad(program, "position", 0);
12619
12620 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
12621 }
12622
12623 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)12624 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
12625 {
12626 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12627
12628 constexpr char kVS[] = R"(#version 310 es
12629 #extension GL_EXT_shader_io_blocks : require
12630 in highp vec4 position;
12631 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12632 void main()
12633 {
12634 blockOut1.a = vec4(0);
12635 blockOut1.b[0] = vec4(0);
12636 blockOut1.b[1] = vec4(0);
12637 gl_Position = position;
12638 })";
12639
12640 constexpr char kFS[] = R"(#version 310 es
12641 #extension GL_EXT_shader_io_blocks : require
12642 precision mediump float;
12643 layout(location = 0) out mediump vec4 color;
12644 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
12645 void main()
12646 {
12647 color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12648 })";
12649
12650 GLuint program = CompileProgram(kVS, kFS);
12651 EXPECT_EQ(0u, program);
12652 }
12653
12654 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)12655 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
12656 {
12657 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12658
12659 constexpr char kVS[] = R"(#version 310 es
12660 #extension GL_EXT_shader_io_blocks : require
12661 in highp vec4 position;
12662 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12663 void main()
12664 {
12665 blockOut1.a = vec4(0);
12666 blockOut1.b[0] = vec4(0);
12667 blockOut1.b[1] = vec4(0);
12668 gl_Position = position;
12669 })";
12670
12671 constexpr char kFS[] = R"(#version 310 es
12672 #extension GL_EXT_shader_io_blocks : require
12673 precision mediump float;
12674 layout(location = 0) out mediump vec4 color;
12675 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
12676 void main()
12677 {
12678 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12679 })";
12680
12681 GLuint program = CompileProgram(kVS, kFS);
12682 EXPECT_EQ(0u, program);
12683 }
12684
12685 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)12686 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
12687 {
12688 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12689
12690 constexpr char kVS[] = R"(#version 310 es
12691 #extension GL_EXT_shader_io_blocks : require
12692 in highp vec4 position;
12693 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12694 void main()
12695 {
12696 blockOut1.a = vec4(0);
12697 blockOut1.b[0] = vec4(0);
12698 blockOut1.b[1] = vec4(0);
12699 gl_Position = position;
12700 })";
12701
12702 constexpr char kFS[] = R"(#version 310 es
12703 #extension GL_EXT_shader_io_blocks : require
12704 precision mediump float;
12705 layout(location = 0) out mediump vec4 color;
12706 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
12707 void main()
12708 {
12709 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12710 })";
12711
12712 GLuint program = CompileProgram(kVS, kFS);
12713 EXPECT_EQ(0u, program);
12714 }
12715
12716 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)12717 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
12718 {
12719 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12720
12721 constexpr char kVS[] = R"(#version 310 es
12722 #extension GL_EXT_shader_io_blocks : require
12723 in highp vec4 position;
12724 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12725 void main()
12726 {
12727 blockOut1.a = vec4(0);
12728 blockOut1.b[0] = vec4(0);
12729 blockOut1.b[1] = vec4(0);
12730 gl_Position = position;
12731 })";
12732
12733 constexpr char kFS[] = R"(#version 310 es
12734 #extension GL_EXT_shader_io_blocks : require
12735 precision mediump float;
12736 layout(location = 0) out mediump vec4 color;
12737 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
12738 void main()
12739 {
12740 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12741 })";
12742
12743 GLuint program = CompileProgram(kVS, kFS);
12744 EXPECT_EQ(0u, program);
12745 }
12746
12747 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)12748 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
12749 {
12750 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12751
12752 constexpr char kVS[] = R"(#version 310 es
12753 #extension GL_EXT_shader_io_blocks : require
12754 in highp vec4 position;
12755 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
12756 void main()
12757 {
12758 blockOut1.a = vec4(0);
12759 blockOut1.b[0] = vec4(0);
12760 blockOut1.b[1] = vec4(0);
12761 gl_Position = position;
12762 })";
12763
12764 constexpr char kFS[] = R"(#version 310 es
12765 #extension GL_EXT_shader_io_blocks : require
12766 precision mediump float;
12767 layout(location = 0) out mediump vec4 color;
12768 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
12769 void main()
12770 {
12771 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12772 })";
12773
12774 GLuint program = CompileProgram(kVS, kFS);
12775 EXPECT_EQ(0u, program);
12776 }
12777
12778 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)12779 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
12780 {
12781 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12782
12783 constexpr char kVS[] = R"(#version 310 es
12784 #extension GL_EXT_shader_io_blocks : require
12785 in highp vec4 position;
12786 struct S1 { vec4 a; vec4 b[2]; };
12787 out VSBlock { S1 s; } blockOut1;
12788 void main()
12789 {
12790 blockOut1.s.a = vec4(0);
12791 blockOut1.s.b[0] = vec4(0);
12792 blockOut1.s.b[1] = vec4(0);
12793 gl_Position = position;
12794 })";
12795
12796 constexpr char kFS[] = R"(#version 310 es
12797 #extension GL_EXT_shader_io_blocks : require
12798 precision mediump float;
12799 layout(location = 0) out mediump vec4 color;
12800 struct S2 { vec4 a; vec4 b[2]; };
12801 in VSBlock { S2 s; } blockIn1;
12802 void main()
12803 {
12804 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12805 })";
12806
12807 GLuint program = CompileProgram(kVS, kFS);
12808 EXPECT_EQ(0u, program);
12809 }
12810
12811 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)12812 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
12813 {
12814 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12815
12816 constexpr char kVS[] = R"(#version 310 es
12817 #extension GL_EXT_shader_io_blocks : require
12818 in highp vec4 position;
12819 struct S { vec4 c; vec4 b[2]; };
12820 out VSBlock { S s; } blockOut1;
12821 void main()
12822 {
12823 blockOut1.s.c = vec4(0);
12824 blockOut1.s.b[0] = vec4(0);
12825 blockOut1.s.b[1] = vec4(0);
12826 gl_Position = position;
12827 })";
12828
12829 constexpr char kFS[] = R"(#version 310 es
12830 #extension GL_EXT_shader_io_blocks : require
12831 precision mediump float;
12832 layout(location = 0) out mediump vec4 color;
12833 struct S { vec4 a; vec4 b[2]; };
12834 in VSBlock { S s; } blockIn1;
12835 void main()
12836 {
12837 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12838 })";
12839
12840 GLuint program = CompileProgram(kVS, kFS);
12841 EXPECT_EQ(0u, program);
12842 }
12843
12844 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)12845 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
12846 {
12847 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12848
12849 constexpr char kVS[] = R"(#version 310 es
12850 #extension GL_EXT_shader_io_blocks : require
12851 in highp vec4 position;
12852 struct S { vec4 a; vec4 b[2]; };
12853 out VSBlock { S s; } blockOut1;
12854 void main()
12855 {
12856 blockOut1.s.a = vec4(0);
12857 blockOut1.s.b[0] = vec4(0);
12858 blockOut1.s.b[1] = vec4(0);
12859 gl_Position = position;
12860 })";
12861
12862 constexpr char kFS[] = R"(#version 310 es
12863 #extension GL_EXT_shader_io_blocks : require
12864 precision mediump float;
12865 layout(location = 0) out mediump vec4 color;
12866 struct S { vec3 a; vec4 b[2]; };
12867 in VSBlock { S s; } blockIn1;
12868 void main()
12869 {
12870 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12871 })";
12872
12873 GLuint program = CompileProgram(kVS, kFS);
12874 EXPECT_EQ(0u, program);
12875 }
12876
12877 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)12878 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
12879 {
12880 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12881
12882 constexpr char kVS[] = R"(#version 310 es
12883 #extension GL_EXT_shader_io_blocks : require
12884 in highp vec4 position;
12885 struct S { vec4 a; vec4 b[3]; };
12886 out VSBlock { S s; } blockOut1;
12887 void main()
12888 {
12889 blockOut1.s.a = vec4(0);
12890 blockOut1.s.b[0] = vec4(0);
12891 blockOut1.s.b[1] = vec4(0);
12892 gl_Position = position;
12893 })";
12894
12895 constexpr char kFS[] = R"(#version 310 es
12896 #extension GL_EXT_shader_io_blocks : require
12897 precision mediump float;
12898 layout(location = 0) out mediump vec4 color;
12899 struct S { vec4 a; vec4 b[2]; };
12900 in VSBlock { S s; } blockIn1;
12901 void main()
12902 {
12903 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12904 })";
12905
12906 GLuint program = CompileProgram(kVS, kFS);
12907 EXPECT_EQ(0u, program);
12908 }
12909
12910 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)12911 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
12912 {
12913 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12914
12915 constexpr char kVS[] = R"(#version 310 es
12916 #extension GL_EXT_shader_io_blocks : require
12917 in highp vec4 position;
12918 struct S { vec4 a; vec4 b[2]; vec4 c; };
12919 out VSBlock { S s; } blockOut1;
12920 void main()
12921 {
12922 blockOut1.s.c = vec4(0);
12923 blockOut1.s.b[0] = vec4(0);
12924 blockOut1.s.b[1] = vec4(0);
12925 gl_Position = position;
12926 })";
12927
12928 constexpr char kFS[] = R"(#version 310 es
12929 #extension GL_EXT_shader_io_blocks : require
12930 precision mediump float;
12931 layout(location = 0) out mediump vec4 color;
12932 struct S { vec4 a; vec4 b[2]; };
12933 in VSBlock { S s; } blockIn1;
12934 void main()
12935 {
12936 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12937 })";
12938
12939 GLuint program = CompileProgram(kVS, kFS);
12940 EXPECT_EQ(0u, program);
12941 }
12942
12943 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)12944 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
12945 {
12946 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12947
12948 constexpr char kVS[] = R"(#version 310 es
12949 #extension GL_EXT_shader_io_blocks : require
12950 in highp vec4 position;
12951 struct S1 { vec4 c; vec4 b[2]; };
12952 struct S2 { S1 s; };
12953 struct S3 { S2 s; };
12954 out VSBlock { S3 s; } blockOut1;
12955 void main()
12956 {
12957 blockOut1.s.s.s.c = vec4(0);
12958 blockOut1.s.s.s.b[0] = vec4(0);
12959 blockOut1.s.s.s.b[1] = vec4(0);
12960 gl_Position = position;
12961 })";
12962
12963 constexpr char kFS[] = R"(#version 310 es
12964 #extension GL_EXT_shader_io_blocks : require
12965 precision mediump float;
12966 layout(location = 0) out mediump vec4 color;
12967 struct S1 { vec4 a; vec4 b[2]; };
12968 struct S2 { S1 s; };
12969 struct S3 { S2 s; };
12970 in VSBlock { S3 s; } blockIn1;
12971 void main()
12972 {
12973 color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
12974 })";
12975
12976 GLuint program = CompileProgram(kVS, kFS);
12977 EXPECT_EQ(0u, program);
12978 }
12979
12980 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)12981 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
12982 {
12983 constexpr char kVS[] = R"(#version 310 es
12984 precision highp float;
12985
12986 struct S
12987 {
12988 mat4 a;
12989 mat4 b;
12990 };
12991
12992 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
12993
12994 void main() {
12995 S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
12996
12997 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);
12998 })";
12999
13000 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13001
13002 const char *sourceArray[1] = {kVS};
13003 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
13004 glShaderSource(shader, 1, sourceArray, lengths);
13005 glCompileShader(shader);
13006
13007 GLint compileResult;
13008 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13009 EXPECT_NE(compileResult, 0);
13010 }
13011
13012 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)13013 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
13014 {
13015 constexpr char kVS[] = R"(#version 310 es
13016 precision highp float;
13017
13018 struct S
13019 {
13020 mat4 a;
13021 mat4 b;
13022 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
13023
13024 void main() {
13025 struct T
13026 {
13027 mat4 a;
13028 mat4 b;
13029 } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
13030
13031 float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
13032
13033 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
13034 })";
13035
13036 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13037
13038 const char *sourceArray[1] = {kVS};
13039 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
13040 glShaderSource(shader, 1, sourceArray, lengths);
13041 glCompileShader(shader);
13042
13043 GLint compileResult;
13044 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13045 EXPECT_NE(compileResult, 0);
13046 }
13047
13048 // Test that separating declarators works with structs that are simultaneously defined and that are
13049 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)13050 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
13051 {
13052 constexpr char kVS[] = R"(#version 310 es
13053 precision highp float;
13054
13055 struct
13056 {
13057 mat4 a;
13058 mat4 b;
13059 } s1, s2[2][3], s3[2];
13060
13061 void main() {
13062 struct
13063 {
13064 mat4 a;
13065 mat4 b;
13066 } s4[2][3], s5, s6[2], s7 = s5;
13067
13068 float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
13069
13070 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
13071 })";
13072
13073 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13074
13075 const char *sourceArray[1] = {kVS};
13076 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
13077 glShaderSource(shader, 1, sourceArray, lengths);
13078 glCompileShader(shader);
13079
13080 GLint compileResult;
13081 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13082 EXPECT_NE(compileResult, 0);
13083 }
13084
13085 // Regression test for transformation bug which separates struct declarations from uniform
13086 // declarations. The bug was that the uniform variable usage in the initializer of a new
13087 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)13088 TEST_P(GLSLTest, UniformStructBug)
13089 {
13090 constexpr char kVS[] = R"(precision highp float;
13091
13092 uniform struct Global
13093 {
13094 float x;
13095 } u_global;
13096
13097 void main() {
13098 float y = u_global.x;
13099
13100 gl_Position = vec4(y);
13101 })";
13102
13103 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13104
13105 const char *sourceArray[1] = {kVS};
13106 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
13107 glShaderSource(shader, 1, sourceArray, lengths);
13108 glCompileShader(shader);
13109
13110 GLint compileResult;
13111 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13112 EXPECT_NE(compileResult, 0);
13113 }
13114
13115 // Regression test for transformation bug which separates struct declarations from uniform
13116 // declarations. The bug was that the arrayness of the declaration was not being applied to the
13117 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)13118 TEST_P(GLSLTest_ES31, UniformStructBug2)
13119 {
13120 constexpr char kVS[] = R"(#version 310 es
13121 precision highp float;
13122
13123 uniform struct Global
13124 {
13125 float x;
13126 } u_global[2][3];
13127
13128 void main() {
13129 float y = u_global[0][0].x;
13130
13131 gl_Position = vec4(y);
13132 })";
13133
13134 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13135
13136 const char *sourceArray[1] = {kVS};
13137 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
13138 glShaderSource(shader, 1, sourceArray, lengths);
13139 glCompileShader(shader);
13140
13141 GLint compileResult;
13142 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13143 EXPECT_NE(compileResult, 0);
13144 }
13145
13146 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
13147 // was not found in the tree. Tests that struct declaration in function return value is visible to
13148 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)13149 TEST_P(GLSLTest, MissingStructDeclarationBug)
13150 {
13151 constexpr char kVS[] = R"(
13152 struct S
13153 {
13154 vec4 i;
13155 } p();
13156 void main()
13157 {
13158 S s;
13159 })";
13160
13161 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13162 EXPECT_NE(0u, shader);
13163 glDeleteShader(shader);
13164 }
13165
13166 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
13167 // was not found in the tree. Tests that struct declaration in function return value is visible to
13168 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)13169 TEST_P(GLSLTest, MissingStructDeclarationBug2)
13170 {
13171 constexpr char kVS[] = R"(
13172 struct T
13173 {
13174 vec4 I;
13175 } p();
13176 struct
13177 {
13178 T c;
13179 };
13180 void main()
13181 {
13182 })";
13183
13184 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13185 EXPECT_NE(0u, shader);
13186 glDeleteShader(shader);
13187 }
13188
13189 // Regression test for bug in HLSL code generation where the for loop init expression was expected
13190 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)13191 TEST_P(GLSLTest, HandleExcessiveLoopBug)
13192 {
13193 constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
13194
13195 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13196 EXPECT_NE(0u, shader);
13197 glDeleteShader(shader);
13198 }
13199
13200 // Regression test for a validation bug in the translator where func(void, int) was accepted even
13201 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)13202 TEST_P(GLSLTest, NoParameterAfterVoid)
13203 {
13204 constexpr char kVS[] = R"(void f(void, int a){}
13205 void main(){f(1);})";
13206
13207 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13208 EXPECT_EQ(0u, shader);
13209 glDeleteShader(shader);
13210 }
13211
13212 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)13213 TEST_P(GLSLTest, NoParameterAfterVoid2)
13214 {
13215 constexpr char kVS[] = R"(void f(void, void){}
13216 void main(){f();})";
13217
13218 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13219 EXPECT_EQ(0u, shader);
13220 glDeleteShader(shader);
13221 }
13222
13223 // Test that providing more components to a matrix constructor than necessary works. Based on a
13224 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)13225 TEST_P(GLSLTest, MatrixConstructor)
13226 {
13227 constexpr char kVS[] = R"(attribute vec4 aPosition;
13228 varying vec4 vColor;
13229 void main()
13230 {
13231 gl_Position = aPosition;
13232 vec4 color = vec4(aPosition.xy, 0, 1);
13233 mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
13234 vColor = m4[0];
13235 })";
13236
13237 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13238 EXPECT_NE(0u, shader);
13239 glDeleteShader(shader);
13240 }
13241
13242 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)13243 TEST_P(GLSLTest_ES3, ScalarConstructor)
13244 {
13245 constexpr char kFS[] = R"(#version 300 es
13246 precision mediump float;
13247 uniform vec4 u;
13248 out vec4 color;
13249 void main()
13250 {
13251 float f1 = float(u);
13252 mat3 m = mat3(u, u, u);
13253 int i = int(m);
13254 color = vec4(f1, float(i), 0, 1);
13255 })";
13256
13257 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
13258 glUseProgram(program);
13259
13260 GLint uloc = glGetUniformLocation(program, "u");
13261 ASSERT_NE(uloc, -1);
13262 glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
13263
13264 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13265 EXPECT_GL_NO_ERROR();
13266
13267 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
13268 }
13269
13270 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)13271 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
13272 {
13273 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
13274
13275 constexpr char kVS[] = R"(#version 300 es
13276 #extension GL_EXT_shader_non_constant_global_initializers : require
13277 uniform vec4 u;
13278 out vec4 color;
13279
13280 vec4 global1 = u;
13281 vec4 global2 = u + vec4(1);
13282 vec4 global3 = global1 * global2;
13283 void main()
13284 {
13285 color = global3;
13286 })";
13287
13288 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13289 EXPECT_NE(0u, shader);
13290 glDeleteShader(shader);
13291 }
13292
13293 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)13294 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
13295 {
13296 constexpr char kFS[] = R"(#version 300 es
13297 precision highp float;
13298 out vec4 color;
13299
13300 struct T
13301 {
13302 float f;
13303 };
13304
13305 struct S
13306 {
13307 vec4 v;
13308 mat3x4 m[2];
13309 T t;
13310 };
13311
13312 S s = S(
13313 vec4(0, 1, 2, 3),
13314 mat3x4[2](
13315 mat3x4(
13316 vec4(4, 5, 6, 7),
13317 vec4(8, 9, 10, 11),
13318 vec4(12, 13, 14, 15)
13319 ),
13320 mat3x4(
13321 vec4(16, 17, 18, 19),
13322 vec4(20, 21, 22, 23),
13323 vec4(24, 25, 26, 27)
13324 )
13325 ),
13326 T(28.0)
13327 );
13328
13329 void main()
13330 {
13331 vec4 result = vec4(0, 1, 0, 1);
13332
13333 if (s.v != vec4(0, 1, 2, 3))
13334 result = vec4(1, 0, 0, 0);
13335
13336 for (int index = 0; index < 2; ++index)
13337 {
13338 for (int column = 0; column < 3; ++column)
13339 {
13340 int expect = index * 12 + column * 4 + 4;
13341 if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
13342 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
13343 }
13344 }
13345
13346 if (s.t.f != 28.0)
13347 result = vec4(0, 0, 1, 0);
13348
13349 color = result;
13350 })";
13351
13352 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
13353
13354 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13355 EXPECT_GL_NO_ERROR();
13356
13357 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13358 }
13359
13360 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)13361 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
13362 {
13363 constexpr char kFS[] = R"(#version 310 es
13364 precision highp float;
13365 precision highp int;
13366
13367 out vec4 color;
13368
13369 uniform float f; // = 3.41
13370 uniform uvec4 u1; // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
13371 uniform uvec4 u2; // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
13372
13373 struct S
13374 {
13375 float fvalue;
13376 int ivalues[2];
13377 uvec4 uvalues[3];
13378 };
13379
13380 struct T
13381 {
13382 S s[2];
13383 };
13384
13385 void main()
13386 {
13387 float integer;
13388 float fraction = modf(f, integer);
13389
13390 T t;
13391
13392 t.s[0].fvalue = frexp(f, t.s[0].ivalues[0]);
13393 float significand = t.s[0].fvalue;
13394 int exponent = t.s[0].ivalues[0];
13395
13396 t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
13397 uvec4 addResult = t.s[0].uvalues[0];
13398 uvec4 addCarry = t.s[0].uvalues[1].yxwz;
13399
13400 t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
13401 uvec2 subResult = t.s[0].uvalues[2].wx;
13402 uvec2 subBorrow = t.s[1].uvalues[0].wx;
13403
13404 umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
13405 uvec4 mulMsb = t.s[1].uvalues[1];
13406 uvec4 mulLsb = t.s[1].uvalues[2];
13407
13408 ivec2 imulMsb, imulLsb;
13409 imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
13410
13411 bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
13412 bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
13413 bool addPassed =
13414 addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
13415 addCarry == uvec4(1, 0, 1, 0);
13416 bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
13417 bool mulPassed =
13418 mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
13419 mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
13420 bool imulPassed =
13421 imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
13422 imulLsb == ivec2(0x35068740, 0x822E97E0);
13423
13424 color = vec4(modfPassed ? 1 : 0,
13425 frexpPassed ? 1 : 0,
13426 (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
13427 (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
13428 })";
13429
13430 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
13431 glUseProgram(program);
13432
13433 GLint floc = glGetUniformLocation(program, "f");
13434 GLint u1loc = glGetUniformLocation(program, "u1");
13435 GLint u2loc = glGetUniformLocation(program, "u2");
13436 ASSERT_NE(floc, -1);
13437 ASSERT_NE(u1loc, -1);
13438 ASSERT_NE(u2loc, -1);
13439 glUniform1f(floc, 3.41);
13440 glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
13441 glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
13442
13443 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
13444 EXPECT_GL_NO_ERROR();
13445
13446 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
13447 }
13448
13449 // Test that interpolateAt* work with swizzle. This test is disabled as swizzled interpolants are
13450 // only allowed in desktop GLSL.
TEST_P(GLSLTest_ES31,InterpolateAtWithSwizzle)13451 TEST_P(GLSLTest_ES31, InterpolateAtWithSwizzle)
13452 {
13453 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
13454
13455 constexpr char kVS[] = R"(#version 310 es
13456
13457 out vec4 interpolant;
13458
13459 void main()
13460 {
13461 // The following triangle is being drawn over the framebuffer.
13462 //
13463 // (-1,3) |\
13464 // | \
13465 // | \
13466 // | \
13467 // | \
13468 // +--------------+
13469 // | | \
13470 // | | \
13471 // | Framebuffer | \
13472 // | | \
13473 // | | \
13474 // (-1,-1) +--------------+--------------- (3,-1)
13475 //
13476 // Interpolant is set such that interpolateAtCentroid would produce the desired value for
13477 // position == (0, 0), and interpolateAtOffset(0.5, -0.5) for position == (1,-1)
13478 if (gl_VertexID == 0)
13479 {
13480 gl_Position = vec4(-1, -1, 0, 1);
13481 interpolant = vec4(1.5, 0.5, 0, 0);
13482 }
13483 else if (gl_VertexID == 1)
13484 {
13485 gl_Position = vec4(3, -1, 0, 1);
13486 interpolant = vec4(0, 0, 1, 2);
13487 }
13488 else
13489 {
13490 gl_Position = vec4(-1, 3, 0, 1);
13491 interpolant = vec4(0, 1, -1, 2);
13492 }
13493 })";
13494
13495 constexpr char kFS[] = R"(#version 310 es
13496 #extension GL_OES_shader_multisample_interpolation : require
13497 precision highp float;
13498
13499 in vec4 interpolant;
13500 out vec4 color;
13501
13502 void main()
13503 {
13504 // Should result in (0.75, 1.0)
13505 vec2 atCentroid = interpolateAtCentroid(interpolant.xw);
13506 // Selecting the bottom-right corner, this should result in (0.5, 0.25), but interpolateAtOffset
13507 // doesn't make guarantees regarding the range and granularity of the offset. The interpolant
13508 // is given values such that the bottom-left/top-right diagonal is interpolated to a constant
13509 // value of (0, 0.5). The top-left corner has the value (-0.5, 0.75). We therefore make a
13510 // coarse test to make sure that atOffset.x > 0 and atOffset.y < 0.5, thus ensuring at least
13511 // that the offset is in the correct half of the pixel.
13512 vec2 atOffset = interpolateAtOffset(interpolant.zy, vec2(0.5, -0.5));
13513
13514 color = vec4(atCentroid, atOffset.x > 0.0 ? 1 : 0, atOffset.y < 0.5 ? 1 : 0);
13515 })";
13516
13517 GLRenderbuffer rbo;
13518 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
13519 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
13520
13521 GLFramebuffer fbo;
13522 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
13523 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
13524 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
13525
13526 ANGLE_GL_PROGRAM(program, kVS, kFS);
13527 glUseProgram(program);
13528
13529 glViewport(0, 0, 1, 1);
13530 glDrawArrays(GL_TRIANGLES, 0, 3);
13531 EXPECT_GL_NO_ERROR();
13532
13533 EXPECT_PIXEL_NEAR(0, 0, 191, 255, 255, 255, 1);
13534 }
13535
13536 class GLSLTestLoops : public GLSLTest
13537 {
13538 protected:
runTest(const char * fs)13539 void runTest(const char *fs)
13540 {
13541 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
13542
13543 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13544 EXPECT_GL_NO_ERROR();
13545
13546 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13547 }
13548 };
13549
13550 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)13551 TEST_P(GLSLTestLoops, BasicFor)
13552 {
13553 constexpr char kFS[] = R"(#version 300 es
13554 precision mediump float;
13555 out vec4 color;
13556
13557 void main()
13558 {
13559 int result = 0;
13560 for (int i = 0; i < 10; ++i)
13561 for (int j = 0; j < 8; ++j)
13562 {
13563 for (int k = 0; k < 2; ++k, ++j) ++result;
13564 for (int k = 0; k < 3; ++k) ++result;
13565 for (int k = 0; k < 0; ++k) ++result;
13566 }
13567
13568 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13569 })";
13570
13571 runTest(kFS);
13572 }
13573
13574 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)13575 TEST_P(GLSLTestLoops, ForNoCondition)
13576 {
13577 constexpr char kFS[] = R"(#version 300 es
13578 precision mediump float;
13579 out vec4 color;
13580
13581 void main()
13582 {
13583 int result = 0;
13584 for (int i = 0; i < 10; ++i)
13585 for (int j = 0; ; ++j)
13586 {
13587 for (int k = 0; k < 2; ++k, ++j) ++result;
13588 for (int k = 0; k < 3; ++k) ++result;
13589 for (int k = 0; k < 0; ++k) ++result;
13590
13591 if (j >= 8)
13592 break;
13593 }
13594
13595 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13596 })";
13597
13598 runTest(kFS);
13599 }
13600
13601 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)13602 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
13603 {
13604 constexpr char kFS[] = R"(#version 300 es
13605 precision mediump float;
13606 out vec4 color;
13607
13608 void main()
13609 {
13610 int result = 0;
13611 for (int i = 0; i < 10; ++i)
13612 {
13613 int j = 0;
13614 for (;;)
13615 {
13616 for (int k = 0; k < 2; ++k, ++j) ++result;
13617 for (int k = 0; k < 3; ++k) ++result;
13618 for (int k = 0; k < 0; ++k) ++result;
13619
13620 if (j >= 8)
13621 break;
13622 ++j;
13623 }
13624 }
13625
13626 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13627 })";
13628
13629 runTest(kFS);
13630 }
13631
13632 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)13633 TEST_P(GLSLTestLoops, ForContinue)
13634 {
13635 constexpr char kFS[] = R"(#version 300 es
13636 precision mediump float;
13637 out vec4 color;
13638
13639 void main()
13640 {
13641 int result = 0;
13642 for (int i = 0; i < 10; ++i)
13643 for (int j = 0; j < 8; ++j)
13644 {
13645 for (int k = 0; k < 2; ++k, ++j) ++result;
13646 for (int k = 0; k < 3; ++k) ++result;
13647 if (i > 3)
13648 continue;
13649 for (int k = 0; k < 0; ++k) ++result;
13650 }
13651
13652 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13653 })";
13654
13655 runTest(kFS);
13656 }
13657
13658 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)13659 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
13660 {
13661 constexpr char kFS[] = R"(#version 300 es
13662 precision mediump float;
13663 out vec4 color;
13664
13665 void main()
13666 {
13667 int result = 0;
13668 for (int i = 0; i < 10; ++i)
13669 for (int j = 0; j < 8; ++j)
13670 {
13671 for (int k = 0; k < 2; ++k, ++j) ++result;
13672 for (int k = 0; k < 3; ++k) ++result;
13673 for (int k = 0; k < 0; ++k) ++result;
13674 continue;
13675 }
13676
13677 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13678 })";
13679
13680 runTest(kFS);
13681 }
13682
13683 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)13684 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
13685 {
13686 constexpr char kFS[] = R"(#version 300 es
13687 precision mediump float;
13688 out vec4 color;
13689
13690 void main()
13691 {
13692 int result = 0;
13693 for (int i = 0; i < 10; ++i)
13694 for (int j = 0; j < 8; ++j)
13695 {
13696 for (int k = 0; k < 2; ++k, ++j) ++result;
13697 for (int k = 0; k < 3; ++k) ++result;
13698 for (int k = 0; k < 0; ++k) ++result;
13699 break;
13700 }
13701
13702 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13703 })";
13704
13705 runTest(kFS);
13706 }
13707
13708 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)13709 TEST_P(GLSLTestLoops, ForBreakContinue)
13710 {
13711 constexpr char kFS[] = R"(#version 300 es
13712 precision mediump float;
13713 out vec4 color;
13714
13715 void main()
13716 {
13717 int result = 0;
13718 for (int i = 0; i < 10; ++i)
13719 for (int j = 0; j < 8; ++j)
13720 {
13721 if (j < 2) continue;
13722 if (j > 6) break;
13723 if (i < 3) continue;
13724 if (i > 8) break;
13725 ++result;
13726 }
13727
13728 color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13729 })";
13730
13731 runTest(kFS);
13732 }
13733
13734 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)13735 TEST_P(GLSLTestLoops, BasicWhile)
13736 {
13737 constexpr char kFS[] = R"(#version 300 es
13738 precision mediump float;
13739 out vec4 color;
13740
13741 void main()
13742 {
13743 int result = 0;
13744 int i = 0;
13745 while (i < 10)
13746 {
13747 int j = 0;
13748 while (j < 8)
13749 {
13750 int k = 0;
13751 while (k < 2) { ++result; ++k; ++j; }
13752 while (k < 5) { ++result; ++k; }
13753 while (k < 4) { ++result; }
13754 ++j;
13755 }
13756 ++i;
13757 }
13758
13759 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13760 })";
13761
13762 runTest(kFS);
13763 }
13764
13765 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)13766 TEST_P(GLSLTestLoops, WhileContinue)
13767 {
13768 constexpr char kFS[] = R"(#version 300 es
13769 precision mediump float;
13770 out vec4 color;
13771
13772 void main()
13773 {
13774 int result = 0;
13775 int i = 0;
13776 while (i < 10)
13777 {
13778 int j = 0;
13779 while (j < 8)
13780 {
13781 int k = 0;
13782 while (k < 2) { ++result; ++k; ++j; }
13783 while (k < 5) { ++result; ++k; }
13784 if (i > 3)
13785 {
13786 ++j;
13787 continue;
13788 }
13789 while (k < 4) { ++result; }
13790 ++j;
13791 }
13792 ++i;
13793 }
13794
13795 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13796 })";
13797
13798 runTest(kFS);
13799 }
13800
13801 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)13802 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
13803 {
13804 constexpr char kFS[] = R"(#version 300 es
13805 precision mediump float;
13806 out vec4 color;
13807
13808 void main()
13809 {
13810 int result = 0;
13811 int i = 0;
13812 while (i < 10)
13813 {
13814 int j = 0;
13815 while (j < 8)
13816 {
13817 int k = 0;
13818 while (k < 2) { ++result; ++k; ++j; }
13819 while (k < 5) { ++result; ++k; }
13820 while (k < 4) { ++result; }
13821 ++j;
13822 continue;
13823 }
13824 ++i;
13825 }
13826
13827 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13828 })";
13829
13830 runTest(kFS);
13831 }
13832
13833 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)13834 TEST_P(GLSLTestLoops, WhileBreak)
13835 {
13836 constexpr char kFS[] = R"(#version 300 es
13837 precision mediump float;
13838 out vec4 color;
13839
13840 void main()
13841 {
13842 int result = 0;
13843 int i = 0;
13844 while (i < 10)
13845 {
13846 int j = 0;
13847 while (true)
13848 {
13849 int k = 0;
13850 while (k < 2) { ++result; ++k; ++j; }
13851 while (k < 5) { ++result; ++k; }
13852 while (k < 4) { ++result; }
13853 ++j;
13854 if (j >= 8)
13855 break;
13856 }
13857 ++i;
13858 }
13859
13860 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13861 })";
13862
13863 runTest(kFS);
13864 }
13865
13866 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)13867 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
13868 {
13869 constexpr char kFS[] = R"(#version 300 es
13870 precision mediump float;
13871 out vec4 color;
13872
13873 void main()
13874 {
13875 int result = 0;
13876 int i = 0;
13877 while (i < 10)
13878 {
13879 int j = 0;
13880 while (j < 8)
13881 {
13882 int k = 0;
13883 while (k < 2) { ++result; ++k; ++j; }
13884 while (k < 5) { ++result; ++k; }
13885 while (k < 4) { ++result; }
13886 ++j;
13887 break;
13888 }
13889 ++i;
13890 }
13891
13892 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13893 })";
13894
13895 runTest(kFS);
13896 }
13897
13898 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)13899 TEST_P(GLSLTestLoops, BasicDoWhile)
13900 {
13901 constexpr char kFS[] = R"(#version 300 es
13902 precision mediump float;
13903 out vec4 color;
13904
13905 void main()
13906 {
13907 int result = 0;
13908 int i = 0;
13909 do
13910 {
13911 int j = 0;
13912 do
13913 {
13914 int k = 0;
13915 do { ++result; ++k; ++j; } while (k < 2);
13916 do { ++result; ++k; } while (k < 5);
13917 do { ++result; } while (k < 3);
13918 ++j;
13919 } while (j < 8);
13920 ++i;
13921 } while (i < 10);
13922
13923 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13924 })";
13925
13926 runTest(kFS);
13927 }
13928
13929 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)13930 TEST_P(GLSLTestLoops, DoWhileContinue)
13931 {
13932 constexpr char kFS[] = R"(#version 300 es
13933 precision mediump float;
13934 out vec4 color;
13935
13936 void main()
13937 {
13938 int result = 0;
13939 int i = 0;
13940 do
13941 {
13942 int j = 0;
13943 do
13944 {
13945 int k = 0;
13946 do { ++result; ++k; ++j; } while (k < 2);
13947 if (i > 3)
13948 {
13949 ++j;
13950 continue;
13951 }
13952 do { ++result; ++k; } while (k < 5);
13953 do { ++result; } while (k < 3);
13954 ++j;
13955 } while (j < 8);
13956 ++i;
13957 } while (i < 10);
13958
13959 color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13960 })";
13961
13962 runTest(kFS);
13963 }
13964
13965 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)13966 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
13967 {
13968 constexpr char kFS[] = R"(#version 300 es
13969 precision mediump float;
13970 out vec4 color;
13971
13972 void main()
13973 {
13974 int result = 0;
13975 int i = 0;
13976 do
13977 {
13978 int j = 0;
13979 do
13980 {
13981 int k = 0;
13982 do { ++result; ++k; ++j; continue; } while (k < 2);
13983 do { ++result; ++k; continue; } while (k < 5);
13984 do { ++result; continue; } while (k < 3);
13985 ++j;
13986 } while (j < 8);
13987 ++i;
13988 } while (i < 10);
13989
13990 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13991 })";
13992
13993 runTest(kFS);
13994 }
13995
13996 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)13997 TEST_P(GLSLTestLoops, DoWhileBreak)
13998 {
13999 constexpr char kFS[] = R"(#version 300 es
14000 precision mediump float;
14001 out vec4 color;
14002
14003 void main()
14004 {
14005 int result = 0;
14006 int i = 0;
14007 do
14008 {
14009 int j = 0;
14010 do
14011 {
14012 int k = 0;
14013 do { ++result; ++k; ++j; } while (k < 2);
14014 do { ++result; ++k; } while (k < 5);
14015 do { ++result; } while (k < 3);
14016 ++j;
14017 if (j >= 8)
14018 break;
14019 } while (true);
14020 ++i;
14021 } while (i < 10);
14022
14023 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14024 })";
14025
14026 runTest(kFS);
14027 }
14028
14029 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)14030 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
14031 {
14032 constexpr char kFS[] = R"(#version 300 es
14033 precision mediump float;
14034 out vec4 color;
14035
14036 void main()
14037 {
14038 int result = 0;
14039 int i = 0;
14040 do
14041 {
14042 int j = 0;
14043 do
14044 {
14045 int k = 0;
14046 do { ++result; ++k; ++j; break; } while (k < 2);
14047 do { ++result; ++k; break; } while (k < 5);
14048 do { ++result; break; } while (k < 3);
14049 ++j;
14050 } while (j < 8);
14051 ++i;
14052 } while (i < 10);
14053
14054 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14055 })";
14056
14057 runTest(kFS);
14058 }
14059
14060 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)14061 TEST_P(GLSLTestLoops, ForContinueInSwitch)
14062 {
14063 constexpr char kFS[] = R"(#version 300 es
14064 precision mediump float;
14065 out vec4 color;
14066
14067 void main()
14068 {
14069 int result = 0;
14070 for (int i = 0; i < 10; ++i)
14071 for (int j = 0; j < 8; ++j)
14072 {
14073 switch (j)
14074 {
14075 case 2:
14076 case 3:
14077 case 4:
14078 ++result;
14079 // fallthrough
14080 case 5:
14081 case 6:
14082 ++result;
14083 break;
14084 default:
14085 continue;
14086 }
14087 }
14088
14089 color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14090 })";
14091
14092 runTest(kFS);
14093 }
14094
14095 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)14096 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
14097 {
14098 constexpr char kFS[] = R"(#version 300 es
14099 precision mediump float;
14100 out vec4 color;
14101
14102 void main()
14103 {
14104 int result = 0;
14105 int i = 0;
14106 while (i < 10)
14107 {
14108 int j = 0;
14109 while (j < 8)
14110 {
14111 switch (j)
14112 {
14113 case 2:
14114 default:
14115 case 3:
14116 case 4:
14117 ++j;
14118 ++result;
14119 continue;
14120 case 0:
14121 case 1:
14122 case 7:
14123 break;
14124 }
14125 ++j;
14126 }
14127 ++i;
14128 }
14129
14130 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14131 })";
14132
14133 runTest(kFS);
14134 }
14135
14136 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)14137 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
14138 {
14139 constexpr char kFS[] = R"(#version 300 es
14140 precision mediump float;
14141 out vec4 color;
14142
14143 void main()
14144 {
14145 int result = 0;
14146 int i = 0;
14147 do
14148 {
14149 int j = 0;
14150 do
14151 {
14152 switch (j)
14153 {
14154 case 0:
14155 ++j;
14156 continue;
14157 default:
14158 case 2:
14159 case 3:
14160 case 4:
14161 ++j;
14162 ++result;
14163 if (j >= 2 && j <= 6)
14164 break;
14165 else
14166 continue;
14167 }
14168 ++result;
14169 } while (j < 8);
14170 ++i;
14171 } while (i < 10);
14172
14173 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14174 })";
14175
14176 runTest(kFS);
14177 }
14178
14179 // Test that precision is retained for constants (which are constant folded). Adapted from a WebGL
14180 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)14181 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
14182 {
14183 constexpr char kFS[] = R"(
14184 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
14185 uniform mediump float uTest;
14186 void main() {
14187 // exact representation of 4096.5 requires 13 bits of relative precision.
14188 const highp float c = 4096.5;
14189 mediump float a = 0.0;
14190 // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
14191 // Thus fract should also be evaluated at highp.
14192 // See OpenGL ES Shading Language spec section 4.5.2.
14193 // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
14194 // (exceptions for operation precision are allowed for a small number of computationally
14195 // intensive built-in functions, but it is reasonable to think that fract is not one of those).
14196 // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
14197 // or at IEEE half float precision, the result is 0.0.
14198 a = fract(c + uTest);
14199 // Multiply by 2.0 to make the color green.
14200 gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
14201 })";
14202
14203 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
14204
14205 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
14206 EXPECT_GL_NO_ERROR();
14207
14208 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14209 }
14210
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)14211 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
14212 {
14213 ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && (IsOpenGL() || IsOpenGLES()));
14214
14215 constexpr char kFS[] = R"(
14216 precision mediump float;
14217
14218 varying vec2 v_texCoord;
14219
14220 float a = 0.;
14221 #define A 0.
14222
14223 #define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
14224 vec2 c;
14225 #define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
14226
14227 void main() {
14228 vec2 U = v_texCoord;
14229
14230 gl_FragColor = U.y > .5
14231 ? vec4( f(U,a) , f(U*4.,a) , 0,1.0) // top
14232 : vec4( f(U,A) , f(U*4.,A) , 0,1.0); // bottom
14233 }
14234
14235 )";
14236
14237 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
14238 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
14239
14240 // Make sure we rendered something.
14241 EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
14242
14243 // Comapare one line in top half to one line in bottom half.
14244 int compareWidth = getWindowWidth();
14245 int compareHeight = getWindowHeight() / 4;
14246
14247 ASSERT_GE(compareWidth, 2);
14248 ASSERT_GE(compareHeight, 2);
14249
14250 GLubyte pixelValue[4];
14251 constexpr int tolerance = 12;
14252
14253 for (int x = 0; x < compareWidth; ++x)
14254 {
14255 glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
14256 EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
14257 pixelValue[2], pixelValue[3], tolerance);
14258 }
14259 EXPECT_GL_NO_ERROR();
14260 }
14261
14262 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)14263 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
14264 {
14265 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14266
14267 const char kVS[] = R"(#version 310 es
14268 #extension GL_EXT_shader_io_blocks : require
14269 in vec4 position;
14270 out BlockType {
14271 vec4 blockMember;
14272 } BlockTypeOut;
14273
14274 void main()
14275 {
14276 gl_Position = position;
14277 })";
14278
14279 const char kFS[] = R"(#version 310 es
14280 #extension GL_EXT_shader_io_blocks : require
14281 precision mediump float;
14282 out vec4 colorOut;
14283 in BlockType {
14284 vec4 blockMember;
14285 } BlockTypeOut;
14286
14287 void main()
14288 {
14289 if (BlockTypeOut.blockMember == vec4(0)) {
14290 colorOut = vec4(0, 1, 0, 1);
14291 } else {
14292 colorOut = vec4(1, 0, 0, 1);
14293 }
14294 })";
14295
14296 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14297 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14298 ASSERT_GL_NO_ERROR();
14299 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14300 }
14301
14302 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)14303 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
14304 {
14305 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14306
14307 const char kVS[] = R"(#version 310 es
14308 #extension GL_EXT_shader_io_blocks : require
14309 in vec4 position;
14310 out BlockType {
14311 vec4 blockMember;
14312 };
14313
14314 void main()
14315 {
14316 gl_Position = position;
14317 })";
14318
14319 const char kFS[] = R"(#version 310 es
14320 #extension GL_EXT_shader_io_blocks : require
14321 precision mediump float;
14322 out vec4 colorOut;
14323 in BlockType {
14324 vec4 blockMember;
14325 };
14326
14327 void main()
14328 {
14329 if (blockMember == vec4(0)) {
14330 colorOut = vec4(0, 1, 0, 1);
14331 } else {
14332 colorOut = vec4(1, 0, 0, 1);
14333 }
14334 })";
14335
14336 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14337 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14338 ASSERT_GL_NO_ERROR();
14339 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14340 }
14341
14342 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)14343 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
14344 {
14345 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14346
14347 const char kVS[] = R"(#version 310 es
14348 #extension GL_EXT_shader_io_blocks : require
14349 in vec4 position;
14350 out BlockType {
14351 vec4 blockMember[2];
14352 } BlockTypeOut;
14353
14354 void main()
14355 {
14356 gl_Position = position;
14357 })";
14358
14359 const char kFS[] = R"(#version 310 es
14360 #extension GL_EXT_shader_io_blocks : require
14361 precision mediump float;
14362 out vec4 colorOut;
14363 in BlockType {
14364 vec4 blockMember[2];
14365 } BlockTypeOut;
14366
14367 void main()
14368 {
14369 if (BlockTypeOut.blockMember[0] == vec4(0) &&
14370 BlockTypeOut.blockMember[1] == vec4(0)) {
14371 colorOut = vec4(0, 1, 0, 1);
14372 } else {
14373 colorOut = vec4(1, 0, 0, 1);
14374 }
14375 })";
14376
14377 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14378 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14379 ASSERT_GL_NO_ERROR();
14380 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14381 }
14382
14383 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)14384 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
14385 {
14386 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14387
14388 const char kVS[] = R"(#version 310 es
14389 #extension GL_EXT_shader_io_blocks : require
14390 in vec4 position;
14391 out BlockType {
14392 vec4 blockMember;
14393 } BlockTypeOut[2];
14394
14395 void main()
14396 {
14397 gl_Position = position;
14398 })";
14399
14400 const char kFS[] = R"(#version 310 es
14401 #extension GL_EXT_shader_io_blocks : require
14402 precision mediump float;
14403 out vec4 colorOut;
14404 in BlockType {
14405 vec4 blockMember;
14406 } BlockTypeOut[2];
14407
14408 void main()
14409 {
14410 if (BlockTypeOut[0].blockMember == vec4(0) &&
14411 BlockTypeOut[1].blockMember == vec4(0)) {
14412 colorOut = vec4(0, 1, 0, 1);
14413 } else {
14414 colorOut = vec4(1, 0, 0, 1);
14415 }
14416 })";
14417
14418 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14419 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14420 ASSERT_GL_NO_ERROR();
14421 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14422 }
14423
14424 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)14425 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
14426 {
14427 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14428
14429 const char kVS[] = R"(#version 310 es
14430 #extension GL_EXT_shader_io_blocks : require
14431 in vec4 position;
14432 struct s {
14433 float f;
14434 vec2 v;
14435 };
14436 out BlockType {
14437 s blockMember;
14438 } BlockTypeOut;
14439
14440 void main()
14441 {
14442 gl_Position = position;
14443 })";
14444
14445 const char kFS[] = R"(#version 310 es
14446 #extension GL_EXT_shader_io_blocks : require
14447 precision mediump float;
14448 out vec4 colorOut;
14449 struct s {
14450 float f;
14451 vec2 v;
14452 };
14453 in BlockType {
14454 s blockMember;
14455 } BlockTypeOut;
14456
14457 void main()
14458 {
14459 if (BlockTypeOut.blockMember.f == 0.0 &&
14460 BlockTypeOut.blockMember.v == vec2(0)) {
14461 colorOut = vec4(0, 1, 0, 1);
14462 } else {
14463 colorOut = vec4(1, 0, 0, 1);
14464 }
14465 })";
14466
14467 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14468 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14469 ASSERT_GL_NO_ERROR();
14470 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14471 }
14472
14473 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)14474 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
14475 {
14476 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14477
14478 const char kVS[] = R"(#version 310 es
14479 #extension GL_EXT_shader_io_blocks : require
14480 in vec4 position;
14481 struct s {
14482 float f;
14483 vec2 v;
14484 };
14485 out BlockType {
14486 vec4 v;
14487 s s1;
14488 s s2[2];
14489 } BlockTypeOut;
14490
14491 void main()
14492 {
14493 gl_Position = position;
14494 })";
14495
14496 const char kFS[] = R"(#version 310 es
14497 #extension GL_EXT_shader_io_blocks : require
14498 precision mediump float;
14499 out vec4 colorOut;
14500 struct s {
14501 float f;
14502 vec2 v;
14503 };
14504 in BlockType {
14505 vec4 v;
14506 s s1;
14507 s s2[2];
14508 } BlockTypeOut;
14509
14510 void main()
14511 {
14512 s sz = s(0.0, vec2(0));
14513 if (BlockTypeOut.v == vec4(0) &&
14514 BlockTypeOut.s1 == sz &&
14515 BlockTypeOut.s2[0] == sz &&
14516 BlockTypeOut.s2[1] == sz) {
14517 colorOut = vec4(0, 1, 0, 1);
14518 } else {
14519 colorOut = vec4(1, 0, 0, 1);
14520 }
14521 })";
14522
14523 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14524 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14525 ASSERT_GL_NO_ERROR();
14526 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14527 }
14528
14529 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)14530 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
14531 {
14532 // Make a simple program.
14533 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
14534
14535 // Install the executable.
14536 glUseProgram(testProgram);
14537
14538 // Re-link with a bad XFB varying and a bound attrib location.
14539 const char *tfVaryings = "gl_FragColor";
14540 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
14541 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
14542 glLinkProgram(testProgram);
14543 GLint linkStatus = 999;
14544 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
14545 ASSERT_GL_NO_ERROR();
14546 ASSERT_EQ(linkStatus, GL_FALSE);
14547
14548 // Under normal GL this is not an error.
14549 glDrawArrays(GL_TRIANGLES, 79, 16);
14550 EXPECT_GL_NO_ERROR();
14551 }
14552
14553 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)14554 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
14555 {
14556 // Make a simple program.
14557 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
14558
14559 // Install the executable.
14560 glUseProgram(testProgram);
14561
14562 // Re-link with a bad XFB varying and a bound attrib location.
14563 const char *tfVaryings = "gl_FragColor";
14564 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
14565 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
14566 glLinkProgram(testProgram);
14567 GLint linkStatus = 999;
14568 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
14569 ASSERT_GL_NO_ERROR();
14570 ASSERT_EQ(linkStatus, GL_FALSE);
14571
14572 // Under WebGL this is an error.
14573 glDrawArrays(GL_TRIANGLES, 79, 16);
14574 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
14575 }
14576
14577 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)14578 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
14579 {
14580 constexpr char kFS[] = R"(#version 300 es
14581 precision mediump float;
14582 vec3 a = vec3(0.0);
14583 out vec4 color;
14584 void main()
14585 {
14586 cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
14587 })";
14588
14589 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
14590 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
14591 ASSERT_GL_NO_ERROR();
14592 }
14593
14594 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)14595 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
14596 {
14597 constexpr char kFS[] = R"(#version 300 es
14598 struct S {
14599 int foo;
14600 };
14601 void main() {
14602 S a[3];
14603 a = S[3](S(0), S(1), S(2));
14604 })";
14605
14606 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
14607
14608 const char *sourceArray[1] = {kFS};
14609 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
14610 glShaderSource(shader, 1, sourceArray, lengths);
14611 glCompileShader(shader);
14612
14613 GLint compileResult;
14614 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14615 EXPECT_NE(compileResult, 0);
14616 }
14617
14618 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)14619 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
14620 {
14621 constexpr char kFS[] = R"(#version 300 es
14622
14623 precision mediump float;
14624
14625 layout(location=0) out vec4 color;
14626
14627 uniform float f;
14628
14629 void main()
14630 {
14631 mat3x2 m = f + mat3x2(0);
14632 color = vec4(m[0][0]);
14633 })";
14634
14635 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
14636
14637 const char *sourceArray[1] = {kFS};
14638 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
14639 glShaderSource(shader, 1, sourceArray, lengths);
14640 glCompileShader(shader);
14641
14642 GLint compileResult;
14643 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14644 EXPECT_NE(compileResult, 0);
14645 }
14646
14647 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
14648 // folding it into a TIntermConstantUnion. This transformation is clamping non-constant indices in
14649 // WebGL. The |false ? i : 5| as index caused the transformation to consider this a non-constant
14650 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)14651 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
14652 {
14653 constexpr char kFS[] = R"(#version 300 es
14654 precision highp float;
14655
14656 layout(location=0) out float f;
14657
14658 uniform int i;
14659
14660 void main()
14661 {
14662 float data[10];
14663 f = data[false ? i : 5];
14664 })";
14665
14666 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
14667
14668 const char *sourceArray[1] = {kFS};
14669 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
14670 glShaderSource(shader, 1, sourceArray, lengths);
14671 glCompileShader(shader);
14672
14673 GLint compileResult;
14674 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14675 EXPECT_NE(compileResult, 0);
14676 }
14677 } // anonymous namespace
14678
14679 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(GLSLTest, WithGlslang(ES2_VULKAN()));
14680
14681 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
14682
14683 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
14684 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTest_ES3, WithGlslang(ES3_VULKAN()));
14685
14686 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
14687 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTestLoops, WithGlslang(ES3_VULKAN()));
14688
14689 ANGLE_INSTANTIATE_TEST_ES2_AND(WebGLGLSLTest, WithGlslang(ES2_VULKAN()));
14690
14691 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
14692 ANGLE_INSTANTIATE_TEST_ES3_AND(WebGL2GLSLTest, WithGlslang(ES3_VULKAN()));
14693
14694 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
14695 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31, WithGlslang(ES31_VULKAN()));
14696
14697 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
14698 ANGLE_INSTANTIATE_TEST(GLSLTest_ES31_InitShaderVariables, WithInitShaderVariables(ES31_VULKAN()));
14699