1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "test_utils/ANGLETest.h"
8
9 #include "test_utils/gl_raii.h"
10
11 using namespace angle;
12
13 namespace
14 {
15
16 class GLSLTest : public ANGLETest
17 {
18 protected:
GLSLTest()19 GLSLTest()
20 {
21 setWindowWidth(128);
22 setWindowHeight(128);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 }
28
GenerateVaryingType(GLint vectorSize)29 std::string GenerateVaryingType(GLint vectorSize)
30 {
31 char varyingType[10];
32
33 if (vectorSize == 1)
34 {
35 sprintf(varyingType, "float");
36 }
37 else
38 {
39 sprintf(varyingType, "vec%d", vectorSize);
40 }
41
42 return std::string(varyingType);
43 }
44
GenerateVectorVaryingDeclaration(GLint vectorSize,GLint arraySize,GLint id)45 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
46 {
47 char buff[100];
48
49 if (arraySize == 1)
50 {
51 sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
52 }
53 else
54 {
55 sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id,
56 arraySize);
57 }
58
59 return std::string(buff);
60 }
61
GenerateVectorVaryingSettingCode(GLint vectorSize,GLint arraySize,GLint id)62 std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
63 {
64 std::string returnString;
65 char buff[100];
66
67 if (arraySize == 1)
68 {
69 sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
70 returnString += buff;
71 }
72 else
73 {
74 for (int i = 0; i < arraySize; i++)
75 {
76 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i,
77 GenerateVaryingType(vectorSize).c_str());
78 returnString += buff;
79 }
80 }
81
82 return returnString;
83 }
84
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)85 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
86 {
87 if (arraySize == 1)
88 {
89 char buff[100];
90 sprintf(buff, "v%d + ", id);
91 return std::string(buff);
92 }
93 else
94 {
95 std::string returnString;
96 for (int i = 0; i < arraySize; i++)
97 {
98 char buff[100];
99 sprintf(buff, "v%d[%d] + ", id, i);
100 returnString += buff;
101 }
102 return returnString;
103 }
104 }
105
GenerateGLSLWithVaryings(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,std::string * fragmentShader,std::string * vertexShader)106 void GenerateGLSLWithVaryings(GLint floatCount,
107 GLint floatArrayCount,
108 GLint vec2Count,
109 GLint vec2ArrayCount,
110 GLint vec3Count,
111 GLint vec3ArrayCount,
112 GLint vec4Count,
113 GLint vec4ArrayCount,
114 bool useFragCoord,
115 bool usePointCoord,
116 bool usePointSize,
117 std::string *fragmentShader,
118 std::string *vertexShader)
119 {
120 // Generate a string declaring the varyings, to share between the fragment shader and the
121 // vertex shader.
122 std::string varyingDeclaration;
123
124 unsigned int varyingCount = 0;
125
126 for (GLint i = 0; i < floatCount; i++)
127 {
128 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
129 varyingCount += 1;
130 }
131
132 for (GLint i = 0; i < floatArrayCount; i++)
133 {
134 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
135 varyingCount += 1;
136 }
137
138 for (GLint i = 0; i < vec2Count; i++)
139 {
140 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
141 varyingCount += 1;
142 }
143
144 for (GLint i = 0; i < vec2ArrayCount; i++)
145 {
146 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
147 varyingCount += 1;
148 }
149
150 for (GLint i = 0; i < vec3Count; i++)
151 {
152 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
153 varyingCount += 1;
154 }
155
156 for (GLint i = 0; i < vec3ArrayCount; i++)
157 {
158 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
159 varyingCount += 1;
160 }
161
162 for (GLint i = 0; i < vec4Count; i++)
163 {
164 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
165 varyingCount += 1;
166 }
167
168 for (GLint i = 0; i < vec4ArrayCount; i++)
169 {
170 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
171 varyingCount += 1;
172 }
173
174 // Generate the vertex shader
175 vertexShader->clear();
176 vertexShader->append(varyingDeclaration);
177 vertexShader->append("\nvoid main()\n{\n");
178
179 unsigned int currentVSVarying = 0;
180
181 for (GLint i = 0; i < floatCount; i++)
182 {
183 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
184 currentVSVarying += 1;
185 }
186
187 for (GLint i = 0; i < floatArrayCount; i++)
188 {
189 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
190 currentVSVarying += 1;
191 }
192
193 for (GLint i = 0; i < vec2Count; i++)
194 {
195 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
196 currentVSVarying += 1;
197 }
198
199 for (GLint i = 0; i < vec2ArrayCount; i++)
200 {
201 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
202 currentVSVarying += 1;
203 }
204
205 for (GLint i = 0; i < vec3Count; i++)
206 {
207 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
208 currentVSVarying += 1;
209 }
210
211 for (GLint i = 0; i < vec3ArrayCount; i++)
212 {
213 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
214 currentVSVarying += 1;
215 }
216
217 for (GLint i = 0; i < vec4Count; i++)
218 {
219 vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
220 currentVSVarying += 1;
221 }
222
223 for (GLint i = 0; i < vec4ArrayCount; i++)
224 {
225 vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
226 currentVSVarying += 1;
227 }
228
229 if (usePointSize)
230 {
231 vertexShader->append("gl_PointSize = 1.0;\n");
232 }
233
234 vertexShader->append("}\n");
235
236 // Generate the fragment shader
237 fragmentShader->clear();
238 fragmentShader->append("precision highp float;\n");
239 fragmentShader->append(varyingDeclaration);
240 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
241
242 unsigned int currentFSVarying = 0;
243
244 // Make use of the float varyings
245 fragmentShader->append("\tretColor += vec4(");
246
247 for (GLint i = 0; i < floatCount; i++)
248 {
249 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
250 currentFSVarying += 1;
251 }
252
253 for (GLint i = 0; i < floatArrayCount; i++)
254 {
255 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
256 currentFSVarying += 1;
257 }
258
259 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
260
261 // Make use of the vec2 varyings
262 fragmentShader->append("\tretColor += vec4(");
263
264 for (GLint i = 0; i < vec2Count; i++)
265 {
266 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
267 currentFSVarying += 1;
268 }
269
270 for (GLint i = 0; i < vec2ArrayCount; i++)
271 {
272 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
273 currentFSVarying += 1;
274 }
275
276 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
277
278 // Make use of the vec3 varyings
279 fragmentShader->append("\tretColor += vec4(");
280
281 for (GLint i = 0; i < vec3Count; i++)
282 {
283 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
284 currentFSVarying += 1;
285 }
286
287 for (GLint i = 0; i < vec3ArrayCount; i++)
288 {
289 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
290 currentFSVarying += 1;
291 }
292
293 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
294
295 // Make use of the vec4 varyings
296 fragmentShader->append("\tretColor += ");
297
298 for (GLint i = 0; i < vec4Count; i++)
299 {
300 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
301 currentFSVarying += 1;
302 }
303
304 for (GLint i = 0; i < vec4ArrayCount; i++)
305 {
306 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
307 currentFSVarying += 1;
308 }
309
310 fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
311
312 // Set gl_FragColor, and use special variables if requested
313 fragmentShader->append("\tgl_FragColor = retColor");
314
315 if (useFragCoord)
316 {
317 fragmentShader->append(" + gl_FragCoord");
318 }
319
320 if (usePointCoord)
321 {
322 fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
323 }
324
325 fragmentShader->append(";\n}");
326 }
327
VaryingTestBase(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,bool expectSuccess)328 void VaryingTestBase(GLint floatCount,
329 GLint floatArrayCount,
330 GLint vec2Count,
331 GLint vec2ArrayCount,
332 GLint vec3Count,
333 GLint vec3ArrayCount,
334 GLint vec4Count,
335 GLint vec4ArrayCount,
336 bool useFragCoord,
337 bool usePointCoord,
338 bool usePointSize,
339 bool expectSuccess)
340 {
341 std::string fragmentShaderSource;
342 std::string vertexShaderSource;
343
344 GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
345 vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
346 usePointCoord, usePointSize, &fragmentShaderSource,
347 &vertexShaderSource);
348
349 GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
350
351 if (expectSuccess)
352 {
353 EXPECT_NE(0u, program);
354 }
355 else
356 {
357 EXPECT_EQ(0u, program);
358 }
359 }
360
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)361 void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
362 GLint fragmentUniformCount,
363 GLint vertexSamplersCount,
364 GLint fragmentSamplersCount,
365 bool expectSuccess)
366 {
367 std::stringstream vertexShader;
368 std::stringstream fragmentShader;
369
370 // Generate the vertex shader
371 vertexShader << "precision mediump float;\n";
372
373 for (int i = 0; i < vertexUniformCount; i++)
374 {
375 vertexShader << "uniform vec4 v" << i << ";\n";
376 }
377
378 for (int i = 0; i < vertexSamplersCount; i++)
379 {
380 vertexShader << "uniform sampler2D s" << i << ";\n";
381 }
382
383 vertexShader << "void main()\n{\n";
384
385 for (int i = 0; i < vertexUniformCount; i++)
386 {
387 vertexShader << " gl_Position += v" << i << ";\n";
388 }
389
390 for (int i = 0; i < vertexSamplersCount; i++)
391 {
392 vertexShader << " gl_Position += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
393 }
394
395 if (vertexUniformCount == 0 && vertexSamplersCount == 0)
396 {
397 vertexShader << " gl_Position = vec4(0.0);\n";
398 }
399
400 vertexShader << "}\n";
401
402 // Generate the fragment shader
403 fragmentShader << "precision mediump float;\n";
404
405 for (int i = 0; i < fragmentUniformCount; i++)
406 {
407 fragmentShader << "uniform vec4 v" << i << ";\n";
408 }
409
410 for (int i = 0; i < fragmentSamplersCount; i++)
411 {
412 fragmentShader << "uniform sampler2D s" << i << ";\n";
413 }
414
415 fragmentShader << "void main()\n{\n";
416
417 for (int i = 0; i < fragmentUniformCount; i++)
418 {
419 fragmentShader << " gl_FragColor += v" << i << ";\n";
420 }
421
422 for (int i = 0; i < fragmentSamplersCount; i++)
423 {
424 fragmentShader << " gl_FragColor += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
425 }
426
427 if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
428 {
429 fragmentShader << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
430 }
431
432 fragmentShader << "}\n";
433
434 GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
435
436 if (expectSuccess)
437 {
438 EXPECT_NE(0u, program);
439 }
440 else
441 {
442 EXPECT_EQ(0u, program);
443 }
444 }
445
QueryErrorMessage(GLuint program)446 std::string QueryErrorMessage(GLuint program)
447 {
448 GLint infoLogLength;
449 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
450 EXPECT_GL_NO_ERROR();
451
452 if (infoLogLength >= 1)
453 {
454 std::vector<GLchar> infoLog(infoLogLength);
455 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
456 infoLog.data());
457 EXPECT_GL_NO_ERROR();
458 return infoLog.data();
459 }
460
461 return "";
462 }
463
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)464 void validateComponentsInErrorMessage(const char *vertexShader,
465 const char *fragmentShader,
466 const char *expectedErrorType,
467 const char *expectedVariableFullName)
468 {
469 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
470 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
471
472 GLuint program = glCreateProgram();
473 glAttachShader(program, vs);
474 glAttachShader(program, fs);
475 glLinkProgram(program);
476
477 glDetachShader(program, vs);
478 glDetachShader(program, fs);
479 glDeleteShader(vs);
480 glDeleteShader(fs);
481
482 const std::string &errorMessage = QueryErrorMessage(program);
483 printf("%s\n", errorMessage.c_str());
484
485 EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
486 EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
487
488 glDeleteProgram(program);
489 ASSERT_GL_NO_ERROR();
490 }
491
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)492 void verifyAttachment2DColor(unsigned int index,
493 GLuint textureName,
494 GLenum target,
495 GLint level,
496 GLColor color)
497 {
498 glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
499 ASSERT_GL_NO_ERROR();
500
501 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
502 << "index " << index;
503 }
504 };
505
506 class GLSLTestNoValidation : public GLSLTest
507 {
508 public:
GLSLTestNoValidation()509 GLSLTestNoValidation() { setNoErrorEnabled(true); }
510 };
511
512 class GLSLTest_ES3 : public GLSLTest
513 {};
514
515 class GLSLTest_ES31 : public GLSLTest
516 {};
517
BuildBigInitialStackShader(int length)518 std::string BuildBigInitialStackShader(int length)
519 {
520 std::string result;
521 result += "void main() { \n";
522 for (int i = 0; i < length; i++)
523 {
524 result += " if (true) { \n";
525 }
526 result += " int temp; \n";
527 for (int i = 0; i <= length; i++)
528 {
529 result += "} \n";
530 }
531 return result;
532 }
533
TEST_P(GLSLTest,NamelessScopedStructs)534 TEST_P(GLSLTest, NamelessScopedStructs)
535 {
536 constexpr char kFS[] = R"(precision mediump float;
537 void main()
538 {
539 struct
540 {
541 float q;
542 } b;
543
544 gl_FragColor = vec4(1, 0, 0, 1);
545 gl_FragColor.a += b.q;
546 })";
547
548 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
549 }
550
551 // Test that array of fragment shader outputs is processed properly and draws
552 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)553 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
554 {
555 GLuint fbo;
556 glGenFramebuffers(1, &fbo);
557 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
558
559 GLuint textures[4];
560 glGenTextures(4, textures);
561
562 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
563 {
564 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
565 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
566 GL_UNSIGNED_BYTE, nullptr);
567 }
568
569 GLint maxDrawBuffers;
570 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
571 ASSERT_GE(maxDrawBuffers, 4);
572
573 GLuint readFramebuffer;
574 glGenFramebuffers(1, &readFramebuffer);
575 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
576
577 constexpr char kFS[] = R"(#version 300 es
578 precision highp float;
579
580 out vec4 frag_color[4];
581
582 void main()
583 {
584 frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
585 frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
586 frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
587 frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
588 }
589 )";
590
591 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
592
593 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
594 GL_COLOR_ATTACHMENT3};
595
596 constexpr GLuint kMaxBuffers = 4;
597
598 // Enable all draw buffers.
599 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
600 {
601 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
602 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
603 textures[texIndex], 0);
604 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
605 textures[texIndex], 0);
606 }
607 glDrawBuffers(kMaxBuffers, allBufs);
608
609 // Draw with simple program.
610 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
611 ASSERT_GL_NO_ERROR();
612
613 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
614 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
615 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
616 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
617 }
618
619 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)620 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
621 {
622 constexpr char kFS[] = R"(#version 300 es
623 precision highp float;
624
625 // Make color0 inactive but specify color1 first. The Vulkan backend assigns bogus locations when
626 // compiling and fixes it up in SPIR-V. If color0's location is not fixed, it will return location
627 // 1 (aliasing color1). This will lead to a Vulkan validation warning about attachment 0 not being
628 // written to, which shouldn't be fatal.
629 layout(location = 1) out vec4 color1;
630 layout(location = 0) out vec4 color0;
631
632 void main()
633 {
634 color1 = vec4(0.0, 1.0, 0.0, 1.0);
635 }
636 )";
637
638 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
639
640 constexpr GLint kDrawBufferCount = 2;
641
642 GLint maxDrawBuffers;
643 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
644 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
645
646 GLTexture textures[kDrawBufferCount];
647
648 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
649 {
650 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
651 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
652 GL_UNSIGNED_BYTE, nullptr);
653 }
654
655 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
656
657 GLFramebuffer fbo;
658 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
659
660 // Enable all draw buffers.
661 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
662 {
663 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
664 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
665 textures[texIndex], 0);
666 }
667 glDrawBuffers(kDrawBufferCount, allBufs);
668
669 // Draw with simple program.
670 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
671 ASSERT_GL_NO_ERROR();
672 }
673
TEST_P(GLSLTest,ScopedStructsOrderBug)674 TEST_P(GLSLTest, ScopedStructsOrderBug)
675 {
676 constexpr char kFS[] = R"(precision mediump float;
677
678 struct T
679 {
680 float f;
681 };
682
683 void main()
684 {
685 T a;
686
687 struct T
688 {
689 float q;
690 };
691
692 T b;
693
694 gl_FragColor = vec4(1, 0, 0, 1);
695 gl_FragColor.a += a.f;
696 gl_FragColor.a += b.q;
697 })";
698
699 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
700 }
701
702 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
703 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)704 TEST_P(GLSLTest, ScopedStructsOrderBug2)
705 {
706 constexpr char kFS[] = R"(precision mediump float;
707
708 uniform struct T
709 {
710 float f;
711 } x;
712
713 void main()
714 {
715 T a;
716
717 struct T
718 {
719 float q;
720 };
721
722 T b;
723
724 gl_FragColor = vec4(1, 0, 0, 1);
725 gl_FragColor.a += a.f;
726 gl_FragColor.a += b.q;
727 })";
728
729 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
730 }
731
732 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)733 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
734 {
735 constexpr char kVS[] = R"(
736 struct S {
737 float member;
738 }, a;
739 void main() {
740 a.member = 0.0;
741 gl_Position = vec4(a.member);
742 })";
743
744 constexpr char kFS[] = R"(precision mediump float;
745 precision mediump float;
746 void main()
747 {
748 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
749 })";
750
751 ANGLE_GL_PROGRAM(program, kVS, kFS);
752 }
753
754 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)755 TEST_P(GLSLTest, StructConstantFoldingBug)
756 {
757 constexpr char kVS[] = R"(
758 void main()
759 {
760
761 const struct s2 {
762 int i;
763 vec3 v3;
764 bvec4 bv4;
765 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
766
767 struct s4 {
768 int ii;
769 vec4 v4;
770 };
771
772 const struct s1 {
773 s2 ss;
774 int i;
775 float f;
776 mat4 m;
777 s4 s44;
778 } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
779
780 const int field3 = s11.i * s11.ss.i; // constant folding (int * int)
781 const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
782 // 49, 64, 81, 100
783 const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]); // 10.0, 5.0, 16.0, 81.0
784 gl_Position = v4;
785 })";
786
787 constexpr char kFS[] = R"(precision mediump float;
788 precision mediump float;
789 void main()
790 {
791 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
792 })";
793
794 ANGLE_GL_PROGRAM(program, kVS, kFS);
795 }
796
797 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)798 TEST_P(GLSLTest, StructConstantFoldingBug2)
799 {
800 constexpr char kVS[] = R"(
801 uniform vec4 u;
802
803 void main()
804 {
805
806 const struct s2 {
807 int i;
808 vec3 v3;
809 bvec4 bv4;
810 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
811
812 s2 x;
813 x.v3 = u.xyz;
814
815 gl_Position = vec4(x.v3, float(s22.i));
816 })";
817
818 constexpr char kFS[] = R"(precision mediump float;
819 precision mediump float;
820 void main()
821 {
822 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
823 })";
824
825 ANGLE_GL_PROGRAM(program, kVS, kFS);
826 }
827
TEST_P(GLSLTest,ScopedStructsBug)828 TEST_P(GLSLTest, ScopedStructsBug)
829 {
830 constexpr char kFS[] = R"(precision mediump float;
831
832 struct T_0
833 {
834 float f;
835 };
836
837 void main()
838 {
839 gl_FragColor = vec4(1, 0, 0, 1);
840
841 struct T
842 {
843 vec2 v;
844 };
845
846 T_0 a;
847 T b;
848
849 gl_FragColor.a += a.f;
850 gl_FragColor.a += b.v.x;
851 })";
852
853 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
854 }
855
TEST_P(GLSLTest,DxPositionBug)856 TEST_P(GLSLTest, DxPositionBug)
857 {
858 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
859 varying float dx_Position;
860 void main()
861 {
862 gl_Position = vec4(inputAttribute);
863 dx_Position = 0.0;
864 })";
865
866 constexpr char kFS[] = R"(precision mediump float;
867
868 varying float dx_Position;
869
870 void main()
871 {
872 gl_FragColor = vec4(dx_Position, 0, 0, 1);
873 })";
874
875 ANGLE_GL_PROGRAM(program, kVS, kFS);
876 }
877
878 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)879 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
880 {
881 // http://anglebug.com/4092
882 ANGLE_SKIP_TEST_IF(isSwiftshader());
883 constexpr int kStartIndex = 0;
884 constexpr int kArrayLength = 5;
885 constexpr char kVS[] = R"(#version 300 es
886 precision highp float;
887 void main() {
888 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
889 gl_PointSize = 3.0;
890 })";
891
892 constexpr char kFS[] = R"(#version 300 es
893 precision highp float;
894 out vec4 outColor;
895 void main() {
896 outColor = vec4(1.0, 0.0, 0.0, 1.0);
897 })";
898
899 ANGLE_GL_PROGRAM(program, kVS, kFS);
900
901 glUseProgram(program);
902 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
903
904 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
905 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
906 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
907 {
908 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
909 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
910 static_cast<int>(pointCenterY), GLColor::red);
911 }
912 }
913
914 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)915 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
916 {
917 glDrawArrays(GL_POINTS, first, count);
918
919 int pixel[4];
920 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
921 // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
922 // pixels.
923 if (err == static_cast<GLenum>(GL_NO_ERROR))
924 {
925 EXPECT_GL_NO_ERROR();
926 EXPECT_EQ(pixel[0], first + count - 1);
927 }
928 else
929 {
930 // If we call this function with err set, we will allow the error, but check the pixels if
931 // the error hasn't occurred.
932 GLenum glError = glGetError();
933 if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
934 {
935 EXPECT_EQ(pixel[0], first + count - 1);
936 }
937 }
938 }
939
940 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
941 // is based off the WebGL test:
942 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)943 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
944 {
945 // http://anglebug.com/4092
946 ANGLE_SKIP_TEST_IF(isSwiftshader());
947 // http://anglebug.com/5232
948 ANGLE_SKIP_TEST_IF(IsMetal());
949 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
950 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
951 // TODO(anglebug.com/5491): Failing on iOS, probably related to the ARM Mac failure above.
952 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
953 // Have to set a large point size because the window size is much larger than the texture
954 constexpr char kVS[] = R"(#version 300 es
955 flat out highp int vVertexID;
956 void main() {
957 vVertexID = gl_VertexID;
958 gl_Position = vec4(0,0,0,1);
959 gl_PointSize = 1000.0;
960 })";
961
962 constexpr char kFS[] = R"(#version 300 es
963 flat in highp int vVertexID;
964 out highp int oVertexID;
965 void main() {
966 oVertexID = vVertexID;
967 })";
968
969 ANGLE_GL_PROGRAM(program, kVS, kFS);
970 glUseProgram(program);
971
972 GLTexture texture;
973 glBindTexture(GL_TEXTURE_2D, texture);
974 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
975 GLFramebuffer fbo;
976 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
977 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
978 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
979 EXPECT_GL_NO_ERROR();
980
981 // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
982 GLint val[4] = {42};
983 glClearBufferiv(GL_COLOR, 0, val);
984 int pixel[4];
985 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
986 EXPECT_EQ(pixel[0], val[0]);
987
988 GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
989 GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
990 GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
991 GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
992 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
993 GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
994 GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
995 GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
996 GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
997 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
998
999 int32_t int32Max = 0x7FFFFFFF;
1000 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1001 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1002 GLVertexIDIntegerTextureDrawArrays_helper(int32Max, 1, GL_OUT_OF_MEMORY);
1003 }
1004
1005 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1006 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1007 {
1008 // http://anglebug.com/4092
1009 ANGLE_SKIP_TEST_IF(isSwiftshader());
1010 // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
1011 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1012
1013 constexpr int kStartIndex = 5;
1014 constexpr int kArrayLength = 5;
1015 constexpr char kVS[] = R"(#version 300 es
1016 precision highp float;
1017 void main() {
1018 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1019 gl_PointSize = 3.0;
1020 })";
1021
1022 constexpr char kFS[] = R"(#version 300 es
1023 precision highp float;
1024 out vec4 outColor;
1025 void main() {
1026 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1027 })";
1028
1029 ANGLE_GL_PROGRAM(program, kVS, kFS);
1030
1031 glUseProgram(program);
1032 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1033
1034 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1035 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1036 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1037 {
1038 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1039 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1040 static_cast<int>(pointCenterY), GLColor::red);
1041 }
1042 }
1043
TEST_P(GLSLTest,ElseIfRewriting)1044 TEST_P(GLSLTest, ElseIfRewriting)
1045 {
1046 constexpr char kVS[] =
1047 "attribute vec4 a_position;\n"
1048 "varying float v;\n"
1049 "void main() {\n"
1050 " gl_Position = a_position;\n"
1051 " v = 1.0;\n"
1052 " if (a_position.x <= 0.5) {\n"
1053 " v = 0.0;\n"
1054 " } else if (a_position.x >= 0.5) {\n"
1055 " v = 2.0;\n"
1056 " }\n"
1057 "}\n";
1058
1059 constexpr char kFS[] =
1060 "precision highp float;\n"
1061 "varying float v;\n"
1062 "void main() {\n"
1063 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1064 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1065 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1066 " gl_FragColor = color;\n"
1067 "}\n";
1068
1069 ANGLE_GL_PROGRAM(program, kVS, kFS);
1070
1071 drawQuad(program, "a_position", 0.5f);
1072
1073 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1074 EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1075 }
1076
TEST_P(GLSLTest,TwoElseIfRewriting)1077 TEST_P(GLSLTest, TwoElseIfRewriting)
1078 {
1079 constexpr char kVS[] =
1080 "attribute vec4 a_position;\n"
1081 "varying float v;\n"
1082 "void main() {\n"
1083 " gl_Position = a_position;\n"
1084 " if (a_position.x == 0.0) {\n"
1085 " v = 1.0;\n"
1086 " } else if (a_position.x > 0.5) {\n"
1087 " v = 0.0;\n"
1088 " } else if (a_position.x > 0.75) {\n"
1089 " v = 0.5;\n"
1090 " }\n"
1091 "}\n";
1092
1093 constexpr char kFS[] =
1094 "precision highp float;\n"
1095 "varying float v;\n"
1096 "void main() {\n"
1097 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1098 "}\n";
1099
1100 ANGLE_GL_PROGRAM(program, kVS, kFS);
1101 }
1102
TEST_P(GLSLTest,FrontFacingAndVarying)1103 TEST_P(GLSLTest, FrontFacingAndVarying)
1104 {
1105 EGLPlatformParameters platform = GetParam().eglParameters;
1106
1107 constexpr char kVS[] = R"(attribute vec4 a_position;
1108 varying float v_varying;
1109 void main()
1110 {
1111 v_varying = a_position.x;
1112 gl_Position = a_position;
1113 })";
1114
1115 constexpr char kFS[] = R"(precision mediump float;
1116 varying float v_varying;
1117 void main()
1118 {
1119 vec4 c;
1120
1121 if (gl_FrontFacing)
1122 {
1123 c = vec4(v_varying, 0, 0, 1.0);
1124 }
1125 else
1126 {
1127 c = vec4(0, v_varying, 0, 1.0);
1128 }
1129 gl_FragColor = c;
1130 })";
1131
1132 GLuint program = CompileProgram(kVS, kFS);
1133
1134 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1135 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1136 {
1137 if (platform.majorVersion == 9 && platform.minorVersion == 3)
1138 {
1139 EXPECT_EQ(0u, program);
1140 return;
1141 }
1142 }
1143
1144 // Otherwise, compilation should succeed
1145 EXPECT_NE(0u, program);
1146 }
1147
1148 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1149 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1150 {
1151 // Draw with the first program.
1152 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1153 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1154 ASSERT_GL_NO_ERROR();
1155 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1156
1157 // Clear and release shader compiler.
1158 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1159 glClear(GL_COLOR_BUFFER_BIT);
1160 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1161 glReleaseShaderCompiler();
1162 ASSERT_GL_NO_ERROR();
1163
1164 // Draw with a second program.
1165 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1166 drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1167 ASSERT_GL_NO_ERROR();
1168 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1169 }
1170
1171 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1172 TEST_P(GLSLTest_ES3, VersionMismatch)
1173 {
1174 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1175 EXPECT_EQ(0u, program);
1176
1177 program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1178 EXPECT_EQ(0u, program);
1179 }
1180
1181 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1182 TEST_P(GLSLTest, InvariantVaryingOut)
1183 {
1184 constexpr char kFS[] =
1185 "precision mediump float;\n"
1186 "varying float v_varying;\n"
1187 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1188
1189 constexpr char kVS[] =
1190 "attribute vec4 a_position;\n"
1191 "invariant varying float v_varying;\n"
1192 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1193
1194 GLuint program = CompileProgram(kVS, kFS);
1195 EXPECT_EQ(0u, program);
1196 }
1197
1198 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1199 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1200 {
1201 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1202 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1203 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1204
1205 constexpr char kFS[] =
1206 "#version 300 es\n"
1207 "precision mediump float;\n"
1208 "in float v_varying;\n"
1209 "out vec4 my_FragColor;\n"
1210 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1211
1212 constexpr char kVS[] =
1213 "#version 300 es\n"
1214 "in vec4 a_position;\n"
1215 "invariant out float v_varying;\n"
1216 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1217
1218 GLuint program = CompileProgram(kVS, kFS);
1219 EXPECT_NE(0u, program);
1220 }
1221
1222 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1223 TEST_P(GLSLTest, InvariantVaryingIn)
1224 {
1225 constexpr char kFS[] =
1226 "precision mediump float;\n"
1227 "invariant varying float v_varying;\n"
1228 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1229
1230 constexpr char kVS[] =
1231 "attribute vec4 a_position;\n"
1232 "varying float v_varying;\n"
1233 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1234
1235 GLuint program = CompileProgram(kVS, kFS);
1236 EXPECT_EQ(0u, program);
1237 }
1238
1239 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1240 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1241 {
1242 constexpr char kFS[] =
1243 "#version 300 es\n"
1244 "precision mediump float;\n"
1245 "invariant in float v_varying;\n"
1246 "out vec4 my_FragColor;\n"
1247 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1248
1249 constexpr char kVS[] =
1250 "#version 300 es\n"
1251 "in vec4 a_position;\n"
1252 "out float v_varying;\n"
1253 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1254
1255 GLuint program = CompileProgram(kVS, kFS);
1256 EXPECT_EQ(0u, program);
1257 }
1258
1259 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1260 TEST_P(GLSLTest, InvariantVaryingBoth)
1261 {
1262 constexpr char kFS[] =
1263 "precision mediump float;\n"
1264 "invariant varying float v_varying;\n"
1265 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1266
1267 constexpr char kVS[] =
1268 "attribute vec4 a_position;\n"
1269 "invariant varying float v_varying;\n"
1270 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1271
1272 GLuint program = CompileProgram(kVS, kFS);
1273 EXPECT_NE(0u, program);
1274 }
1275
1276 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1277 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1278 {
1279 constexpr char kFS[] =
1280 "#version 300 es\n"
1281 "precision mediump float;\n"
1282 "invariant in float v_varying;\n"
1283 "out vec4 my_FragColor;\n"
1284 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1285
1286 constexpr char kVS[] =
1287 "#version 300 es\n"
1288 "in vec4 a_position;\n"
1289 "invariant out float v_varying;\n"
1290 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1291
1292 GLuint program = CompileProgram(kVS, kFS);
1293 EXPECT_EQ(0u, program);
1294 }
1295
1296 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1297 TEST_P(GLSLTest, InvariantGLPosition)
1298 {
1299 constexpr char kFS[] =
1300 "precision mediump float;\n"
1301 "varying float v_varying;\n"
1302 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1303
1304 constexpr char kVS[] =
1305 "attribute vec4 a_position;\n"
1306 "invariant gl_Position;\n"
1307 "varying float v_varying;\n"
1308 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1309
1310 GLuint program = CompileProgram(kVS, kFS);
1311 EXPECT_NE(0u, program);
1312 }
1313
1314 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1315 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1316 {
1317 constexpr char kFS[] =
1318 "#version 300 es\n"
1319 "precision mediump float;\n"
1320 "in float v_varying;\n"
1321 "out vec4 my_FragColor;\n"
1322 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1323
1324 constexpr char kVS[] =
1325 "#version 300 es\n"
1326 "in vec4 a_position;\n"
1327 "invariant gl_Position;\n"
1328 "out float v_varying;\n"
1329 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1330
1331 GLuint program = CompileProgram(kVS, kFS);
1332 EXPECT_NE(0u, program);
1333 }
1334
1335 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1336 TEST_P(GLSLTest, InvariantAllBoth)
1337 {
1338 constexpr char kFS[] =
1339 "#pragma STDGL invariant(all)\n"
1340 "precision mediump float;\n"
1341 "varying float v_varying;\n"
1342 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1343
1344 constexpr char kVS[] =
1345 "#pragma STDGL invariant(all)\n"
1346 "attribute vec4 a_position;\n"
1347 "varying float v_varying;\n"
1348 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1349
1350 GLuint program = CompileProgram(kVS, kFS);
1351 EXPECT_EQ(0u, program);
1352 }
1353
1354 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1355 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1356 {
1357 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1358
1359 constexpr char kVS[] = R"(#version 310 es
1360 #extension GL_EXT_shader_io_blocks : require
1361
1362 struct S
1363 {
1364 vec4 s;
1365 };
1366
1367 out Output
1368 {
1369 vec4 x;
1370 invariant S s;
1371 };
1372
1373 out S s2;
1374
1375 void main(){
1376 x = vec4(0);
1377 s.s = vec4(1);
1378 s2.s = vec4(2);
1379 S s3 = s;
1380 s.s = s3.s;
1381 })";
1382
1383 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1384 EXPECT_NE(0u, shader);
1385 glDeleteShader(shader);
1386 }
1387
1388 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)1389 TEST_P(GLSLTest, MissingReturnFloat)
1390 {
1391 constexpr char kVS[] =
1392 "varying float v_varying;\n"
1393 "float f() { if (v_varying > 0.0) return 1.0; }\n"
1394 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
1395
1396 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1397 EXPECT_NE(0u, program);
1398 }
1399
1400 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)1401 TEST_P(GLSLTest, MissingReturnVec2)
1402 {
1403 constexpr char kVS[] =
1404 "varying float v_varying;\n"
1405 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
1406 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1407
1408 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1409 EXPECT_NE(0u, program);
1410 }
1411
1412 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)1413 TEST_P(GLSLTest, MissingReturnVec3)
1414 {
1415 constexpr char kVS[] =
1416 "varying float v_varying;\n"
1417 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1418 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1419
1420 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1421 EXPECT_NE(0u, program);
1422 }
1423
1424 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)1425 TEST_P(GLSLTest, MissingReturnVec4)
1426 {
1427 constexpr char kVS[] =
1428 "varying float v_varying;\n"
1429 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1430 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1431
1432 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1433 EXPECT_NE(0u, program);
1434 }
1435
1436 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)1437 TEST_P(GLSLTest, MissingReturnIVec4)
1438 {
1439 constexpr char kVS[] =
1440 "varying float v_varying;\n"
1441 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1442 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1443
1444 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1445 EXPECT_NE(0u, program);
1446 }
1447
1448 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)1449 TEST_P(GLSLTest, MissingReturnMat4)
1450 {
1451 constexpr char kVS[] =
1452 "varying float v_varying;\n"
1453 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1454 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1455
1456 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1457 EXPECT_NE(0u, program);
1458 }
1459
1460 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)1461 TEST_P(GLSLTest, MissingReturnStruct)
1462 {
1463 constexpr char kVS[] =
1464 "varying float v_varying;\n"
1465 "struct s { float a; int b; vec2 c; };\n"
1466 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1467 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1468
1469 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1470 EXPECT_NE(0u, program);
1471 }
1472
1473 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)1474 TEST_P(GLSLTest_ES3, MissingReturnArray)
1475 {
1476 constexpr char kVS[] =
1477 "#version 300 es\n"
1478 "in float v_varying;\n"
1479 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1480 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1481
1482 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1483 EXPECT_NE(0u, program);
1484 }
1485
1486 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)1487 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1488 {
1489 constexpr char kVS[] =
1490 "#version 300 es\n"
1491 "in float v_varying;\n"
1492 "struct s { float a; int b; vec2 c; };\n"
1493 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1494 "vec2(1.0, 1.0))); } }\n"
1495 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1496
1497 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1498 EXPECT_NE(0u, program);
1499 }
1500
1501 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)1502 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1503 {
1504 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
1505 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
1506
1507 constexpr char kVS[] =
1508 "#version 300 es\n"
1509 "in float v_varying;\n"
1510 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1511 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1512 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1513 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1514
1515 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1516 EXPECT_NE(0u, program);
1517 }
1518
1519 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)1520 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
1521 {
1522 constexpr char kVS[] = R"(#version 300 es
1523 in float v_varying;
1524 struct s { float a; int b; vec2 c; };
1525 s[2] f()
1526 {
1527 return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
1528 }
1529 void main()
1530 {
1531 gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
1532 })";
1533
1534 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
1535 EXPECT_NE(0u, program);
1536 }
1537
1538 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)1539 TEST_P(GLSLTest_ES3, InvariantAllBoth)
1540 {
1541 constexpr char kFS[] =
1542 "#version 300 es\n"
1543 "#pragma STDGL invariant(all)\n"
1544 "precision mediump float;\n"
1545 "in float v_varying;\n"
1546 "out vec4 my_FragColor;\n"
1547 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1548
1549 constexpr char kVS[] =
1550 "#version 300 es\n"
1551 "#pragma STDGL invariant(all)\n"
1552 "in vec4 a_position;\n"
1553 "out float v_varying;\n"
1554 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1555
1556 GLuint program = CompileProgram(kVS, kFS);
1557 EXPECT_EQ(0u, program);
1558 }
1559
1560 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)1561 TEST_P(GLSLTest, InvariantAllIn)
1562 {
1563 constexpr char kFS[] =
1564 "#pragma STDGL invariant(all)\n"
1565 "precision mediump float;\n"
1566 "varying float v_varying;\n"
1567 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1568
1569 constexpr char kVS[] =
1570 "attribute vec4 a_position;\n"
1571 "varying float v_varying;\n"
1572 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1573
1574 GLuint program = CompileProgram(kVS, kFS);
1575 EXPECT_NE(0u, program);
1576 }
1577
1578 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)1579 TEST_P(GLSLTest_ES3, InvariantAllIn)
1580 {
1581 constexpr char kFS[] =
1582 "#version 300 es\n"
1583 "#pragma STDGL invariant(all)\n"
1584 "precision mediump float;\n"
1585 "in float v_varying;\n"
1586 "out vec4 my_FragColor;\n"
1587 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1588
1589 constexpr char kVS[] =
1590 "#version 300 es\n"
1591 "in vec4 a_position;\n"
1592 "out float v_varying;\n"
1593 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1594
1595 GLuint program = CompileProgram(kVS, kFS);
1596 EXPECT_EQ(0u, program);
1597 }
1598
1599 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)1600 TEST_P(GLSLTest, InvariantAllOut)
1601 {
1602 constexpr char kFS[] =
1603 "precision mediump float;\n"
1604 "varying float v_varying;\n"
1605 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1606
1607 constexpr char kVS[] =
1608 "#pragma STDGL invariant(all)\n"
1609 "attribute vec4 a_position;\n"
1610 "varying float v_varying;\n"
1611 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1612
1613 GLuint program = CompileProgram(kVS, kFS);
1614 EXPECT_EQ(0u, program);
1615 }
1616
1617 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)1618 TEST_P(GLSLTest_ES3, InvariantAllOut)
1619 {
1620 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1621 // for varyings which are invariant in vertex shader,
1622 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
1623 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1624
1625 constexpr char kFS[] =
1626 "#version 300 es\n"
1627 "precision mediump float;\n"
1628 "in float v_varying;\n"
1629 "out vec4 my_FragColor;\n"
1630 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1631
1632 constexpr char kVS[] =
1633 "#version 300 es\n"
1634 "#pragma STDGL invariant(all)\n"
1635 "in vec4 a_position;\n"
1636 "out float v_varying;\n"
1637 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1638
1639 GLuint program = CompileProgram(kVS, kFS);
1640 EXPECT_NE(0u, program);
1641 }
1642
TEST_P(GLSLTest,MaxVaryingVec4)1643 TEST_P(GLSLTest, MaxVaryingVec4)
1644 {
1645 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1646 // (http://anglebug.com/1291)
1647 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1648
1649 GLint maxVaryings = 0;
1650 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1651
1652 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1653 }
1654
1655 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)1656 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
1657 {
1658 GLint maxVaryings = 0;
1659 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1660
1661 // Generate shader code that uses gl_FragCoord.
1662 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
1663 }
1664
1665 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)1666 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
1667 {
1668 GLint maxVaryings = 0;
1669 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1670
1671 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
1672 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1673 }
1674
1675 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)1676 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
1677 {
1678 GLint maxVaryings = 0;
1679 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1680
1681 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1682 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
1683 }
1684
1685 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1686 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)1687 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
1688 {
1689 ANGLE_SKIP_TEST_IF(!IsD3D9());
1690
1691 GLint maxVaryings = 0;
1692 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1693
1694 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
1695 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
1696 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
1697
1698 // Special case for gl_PointSize: we get it for free on D3D9.
1699 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
1700 }
1701
1702 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1703 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)1704 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
1705 {
1706 GLint maxVaryings = 0;
1707 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1708
1709 // Generate shader code that uses gl_FragCoord.
1710 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
1711 }
1712
TEST_P(GLSLTest,MaxVaryingVec3)1713 TEST_P(GLSLTest, MaxVaryingVec3)
1714 {
1715 GLint maxVaryings = 0;
1716 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1717
1718 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
1719 }
1720
TEST_P(GLSLTest,MaxVaryingVec3Array)1721 TEST_P(GLSLTest, MaxVaryingVec3Array)
1722 {
1723 GLint maxVaryings = 0;
1724 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1725
1726 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
1727 }
1728
1729 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)1730 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
1731 {
1732 GLint maxVaryings = 0;
1733 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1734
1735 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
1736 }
1737
1738 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)1739 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
1740 {
1741 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
1742 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsMetal());
1743
1744 GLint maxVaryings = 0;
1745 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1746
1747 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
1748 }
1749
1750 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)1751 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
1752 {
1753 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1754 // (http://anglebug.com/3849)
1755 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
1756
1757 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1758 // (http://anglebug.com/1291)
1759 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1760
1761 GLint maxVaryings = 0;
1762 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1763
1764 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
1765 }
1766
1767 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)1768 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
1769 {
1770 ANGLE_SKIP_TEST_IF(IsD3DSM3());
1771
1772 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1773 ANGLE_SKIP_TEST_IF(IsOpenGLES());
1774
1775 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
1776 // (http://anglebug.com/1291)
1777 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
1778
1779 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
1780 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsMetal());
1781
1782 GLint maxVaryings = 0;
1783 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1784
1785 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1786 // we should be aware that when we're packing into an odd number of varying registers the
1787 // last row will be empty and can not fit the final vec2 arrary.
1788 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1789
1790 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
1791 }
1792
1793 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)1794 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
1795 {
1796 // (http://anglebug.com/4439)
1797 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
1798
1799 // http://anglebug.com/4446
1800 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
1801
1802 GLint maxVaryings = 0;
1803 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1804
1805 std::stringstream vertexShaderSource;
1806 std::stringstream fragmentShaderSource;
1807
1808 // substract 1 here for gl_PointSize
1809 const GLint vec4Count = maxVaryings - 1;
1810 unsigned int varyingCount = 0;
1811 std::string varyingDeclaration;
1812 for (GLint i = 0; i < vec4Count; i++)
1813 {
1814 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
1815 varyingCount += 1;
1816 }
1817 // Generate the vertex shader
1818 vertexShaderSource.clear();
1819 vertexShaderSource << varyingDeclaration;
1820 vertexShaderSource << "\nattribute vec4 a_position;\n";
1821 vertexShaderSource << "\nvoid main()\n{\n";
1822 unsigned int currentVSVarying = 0;
1823 for (GLint i = 0; i < vec4Count; i++)
1824 {
1825 vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
1826 currentVSVarying += 1;
1827 }
1828 vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
1829 vertexShaderSource << "\tgl_PointSize = 1.0;\n";
1830 vertexShaderSource << "}\n";
1831
1832 // Generate the fragment shader
1833 fragmentShaderSource.clear();
1834 fragmentShaderSource << "precision highp float;\n";
1835 fragmentShaderSource << varyingDeclaration;
1836 fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
1837 unsigned int currentFSVarying = 0;
1838 // Make use of the vec4 varyings
1839 fragmentShaderSource << "\tretColor += ";
1840 for (GLint i = 0; i < vec4Count; i++)
1841 {
1842 fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
1843 currentFSVarying += 1;
1844 }
1845 fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
1846 constexpr GLuint testValue = 234;
1847 fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
1848 << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
1849 fragmentShaderSource << "}\n";
1850
1851 std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
1852 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
1853 fragmentShaderSource.str().c_str(), tfVaryings,
1854 GL_INTERLEAVED_ATTRIBS);
1855
1856 GLBuffer xfbBuffer;
1857 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1858 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
1859 GL_STATIC_DRAW);
1860
1861 GLTransformFeedback xfb;
1862 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1863 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1864
1865 glUseProgram(program1);
1866
1867 const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
1868 GLBuffer vertexBuffer;
1869 // need to shift half pixel to make sure the line covers the center of the pixel
1870 const Vector3 vertices[2] = {
1871 {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
1872 {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
1873 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1874 glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
1875 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1876 glEnableVertexAttribArray(positionLocation);
1877
1878 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
1879 glClear(GL_COLOR_BUFFER_BIT);
1880
1881 glBeginTransformFeedback(GL_LINES);
1882 glDrawArrays(GL_LINES, 0, 2);
1883 glEndTransformFeedback();
1884
1885 ASSERT_GL_NO_ERROR();
1886
1887 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
1888 }
1889
1890 // Verify shader source with a fixed length that is less than the null-terminated length will
1891 // compile.
TEST_P(GLSLTest,FixedShaderLength)1892 TEST_P(GLSLTest, FixedShaderLength)
1893 {
1894 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1895
1896 const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
1897 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1898 const char *sourceArray[1] = {source.c_str()};
1899 GLint lengths[1] = {static_cast<GLint>(source.length() - appendGarbage.length())};
1900 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1901 glCompileShader(shader);
1902
1903 GLint compileResult;
1904 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1905 EXPECT_NE(compileResult, 0);
1906 }
1907
1908 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)1909 TEST_P(GLSLTest, NegativeShaderLength)
1910 {
1911 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1912
1913 const char *sourceArray[1] = {essl1_shaders::fs::Red()};
1914 GLint lengths[1] = {-10};
1915 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1916 glCompileShader(shader);
1917
1918 GLint compileResult;
1919 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1920 EXPECT_NE(compileResult, 0);
1921 }
1922
1923 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)1924 TEST_P(GLSLTest, InvalidFieldFirstChar)
1925 {
1926 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1927 const char *source = "void main() {vec4 x; x.}";
1928 glShaderSource(shader, 1, &source, 0);
1929 glCompileShader(shader);
1930
1931 GLint compileResult;
1932 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1933 EXPECT_EQ(0, compileResult);
1934 }
1935
1936 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)1937 TEST_P(GLSLTest, MixedShaderLengths)
1938 {
1939 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1940
1941 const char *sourceArray[] = {
1942 "void main()",
1943 "{",
1944 " gl_FragColor = vec4(0, 0, 0, 0);",
1945 "}",
1946 };
1947 GLint lengths[] = {
1948 -10,
1949 1,
1950 static_cast<GLint>(strlen(sourceArray[2])),
1951 -1,
1952 };
1953 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1954
1955 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1956 glCompileShader(shader);
1957
1958 GLint compileResult;
1959 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1960 EXPECT_NE(compileResult, 0);
1961 }
1962
1963 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)1964 TEST_P(GLSLTest, ZeroShaderLength)
1965 {
1966 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1967
1968 const char *sourceArray[] = {
1969 "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
1970 };
1971 GLint lengths[] = {
1972 0, 0, -1, 0, 0,
1973 };
1974 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1975
1976 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
1977 glCompileShader(shader);
1978
1979 GLint compileResult;
1980 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1981 EXPECT_NE(compileResult, 0);
1982 }
1983
1984 // Tests that bad index expressions don't crash ANGLE's translator.
1985 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)1986 TEST_P(GLSLTest, BadIndexBug)
1987 {
1988 constexpr char kFSSourceVec[] =
1989 "precision mediump float;\n"
1990 "uniform vec4 uniformVec;\n"
1991 "void main()\n"
1992 "{\n"
1993 " gl_FragColor = vec4(uniformVec[int()]);\n"
1994 "}";
1995
1996 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
1997 EXPECT_EQ(0u, shader);
1998
1999 if (shader != 0)
2000 {
2001 glDeleteShader(shader);
2002 }
2003
2004 constexpr char kFSSourceMat[] =
2005 "precision mediump float;\n"
2006 "uniform mat4 uniformMat;\n"
2007 "void main()\n"
2008 "{\n"
2009 " gl_FragColor = vec4(uniformMat[int()]);\n"
2010 "}";
2011
2012 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2013 EXPECT_EQ(0u, shader);
2014
2015 if (shader != 0)
2016 {
2017 glDeleteShader(shader);
2018 }
2019
2020 constexpr char kFSSourceArray[] =
2021 "precision mediump float;\n"
2022 "uniform vec4 uniformArray;\n"
2023 "void main()\n"
2024 "{\n"
2025 " gl_FragColor = vec4(uniformArray[int()]);\n"
2026 "}";
2027
2028 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2029 EXPECT_EQ(0u, shader);
2030
2031 if (shader != 0)
2032 {
2033 glDeleteShader(shader);
2034 }
2035 }
2036
2037 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2038 TEST_P(GLSLTest, StructSpecifiersUniforms)
2039 {
2040 constexpr char kFS[] = R"(precision mediump float;
2041
2042 uniform struct S { float field; } s;
2043
2044 void main()
2045 {
2046 gl_FragColor = vec4(1, 0, 0, 1);
2047 gl_FragColor.a += s.field;
2048 })";
2049
2050 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2051 EXPECT_NE(0u, program);
2052 }
2053
2054 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2055 TEST_P(GLSLTest, StructWithInitializer)
2056 {
2057 constexpr char kFS[] = R"(precision mediump float;
2058
2059 struct S { float a; } s = S(1.0);
2060
2061 void main()
2062 {
2063 gl_FragColor = vec4(0, 0, 0, 1);
2064 gl_FragColor.r += s.a;
2065 })";
2066
2067 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2068 glUseProgram(program);
2069
2070 // Test drawing, should be red.
2071 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2072
2073 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2074 EXPECT_GL_NO_ERROR();
2075 }
2076
2077 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2078 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2079 {
2080 constexpr char kFS[] = R"(precision mediump float;
2081
2082 struct S { float a; };
2083 uniform S u_s;
2084
2085 void main()
2086 {
2087 gl_FragColor = vec4(u_s.a);
2088 })";
2089
2090 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2091 glUseProgram(program);
2092
2093 // Test drawing, should be red.
2094 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2095
2096 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2097 EXPECT_GL_NO_ERROR();
2098 }
2099
2100 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2101 TEST_P(GLSLTest, StructWithUniformInitializer)
2102 {
2103 constexpr char kFS[] = R"(precision mediump float;
2104
2105 struct S { float a; } s = S(1.0);
2106 uniform S us;
2107
2108 void main()
2109 {
2110 gl_FragColor = vec4(0, 0, 0, 1);
2111 gl_FragColor.r += s.a;
2112 gl_FragColor.g += us.a;
2113 })";
2114
2115 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2116 glUseProgram(program);
2117
2118 // Test drawing, should be red.
2119 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2120
2121 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2122 EXPECT_GL_NO_ERROR();
2123 }
2124
2125 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2126 // beginning with "gl_" are filtered out by our validation logic, we must
2127 // bypass the validation to test the behaviour of the implementation.
2128 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2129 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2130 {
2131 constexpr char kFS[] = R"(precision mediump float;
2132
2133 void main()
2134 {
2135 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2136 })";
2137
2138 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2139
2140 // We need to bypass validation for this call.
2141 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
2142 EXPECT_EQ(-1, nearIndex);
2143
2144 // Test drawing does not throw an exception.
2145 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2146
2147 EXPECT_GL_NO_ERROR();
2148 }
2149
GenerateSmallPowShader(double base,double exponent)2150 std::string GenerateSmallPowShader(double base, double exponent)
2151 {
2152 std::stringstream stream;
2153
2154 stream.precision(8);
2155
2156 double result = pow(base, exponent);
2157
2158 stream << "precision highp float;\n"
2159 << "float fun(float arg)\n"
2160 << "{\n"
2161 << " return pow(arg, " << std::fixed << exponent << ");\n"
2162 << "}\n"
2163 << "\n"
2164 << "void main()\n"
2165 << "{\n"
2166 << " const float a = " << std::scientific << base << ";\n"
2167 << " float b = fun(a);\n"
2168 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2169 << " {\n"
2170 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2171 << " }\n"
2172 << " else\n"
2173 << " {\n"
2174 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2175 << " }\n"
2176 << "}\n";
2177
2178 return stream.str();
2179 }
2180
2181 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2182 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)2183 TEST_P(GLSLTest, PowOfSmallConstant)
2184 {
2185 // Test with problematic exponents that are close to an integer.
2186 std::vector<double> testExponents;
2187 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2188 for (double epsilonMultiplier : epsilonMultipliers)
2189 {
2190 for (int i = -4; i <= 5; ++i)
2191 {
2192 if (i >= -1 && i <= 1)
2193 continue;
2194 const double epsilon = 1.0e-8;
2195 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
2196 testExponents.push_back(bad);
2197 }
2198 }
2199
2200 // Also test with a few exponents that are not close to an integer.
2201 testExponents.push_back(3.6);
2202 testExponents.push_back(3.4);
2203
2204 for (double testExponent : testExponents)
2205 {
2206 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2207
2208 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2209
2210 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2211
2212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2213 EXPECT_GL_NO_ERROR();
2214 }
2215 }
2216
2217 // Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
2218 // below
2219 // fail with a specific error message.
2220 // Additionally test that the same fragment shader compiles successfully with feature levels greater
2221 // than FL9_3.
TEST_P(GLSLTest,LoopIndexingValidation)2222 TEST_P(GLSLTest, LoopIndexingValidation)
2223 {
2224 constexpr char kFS[] = R"(precision mediump float;
2225
2226 uniform float loopMax;
2227
2228 void main()
2229 {
2230 gl_FragColor = vec4(1, 0, 0, 1);
2231 for (float l = 0.0; l < loopMax; l++)
2232 {
2233 if (loopMax > 3.0)
2234 {
2235 gl_FragColor.a += 0.1;
2236 }
2237 }
2238 })";
2239
2240 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2241
2242 const char *sourceArray[1] = {kFS};
2243 glShaderSource(shader, 1, sourceArray, nullptr);
2244 glCompileShader(shader);
2245
2246 GLint compileResult;
2247 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2248
2249 // If the test is configured to run limited to Feature Level 9_3, then it is
2250 // assumed that shader compilation will fail with an expected error message containing
2251 // "Loop index cannot be compared with non-constant expression"
2252 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
2253 {
2254 if (compileResult != 0)
2255 {
2256 FAIL() << "Shader compilation succeeded, expected failure";
2257 }
2258 else
2259 {
2260 GLint infoLogLength;
2261 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2262
2263 std::string infoLog;
2264 infoLog.resize(infoLogLength);
2265 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2266
2267 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2268 std::string::npos)
2269 {
2270 FAIL() << "Shader compilation failed with unexpected error message";
2271 }
2272 }
2273 }
2274 else
2275 {
2276 EXPECT_NE(0, compileResult);
2277 }
2278
2279 if (shader != 0)
2280 {
2281 glDeleteShader(shader);
2282 }
2283 }
2284
2285 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2286 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2287 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2288 {
2289 // crbug.com/680631
2290 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2291
2292 int maxUniforms = 10000;
2293 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2294 EXPECT_GL_NO_ERROR();
2295 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2296
2297 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2298 }
2299
2300 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2301 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2302 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2303 {
2304 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2305
2306 // Times out on D3D11 on test infra. http://anglebug.com/5076
2307 ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2308
2309 int maxUniforms = 10000;
2310 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2311 EXPECT_GL_NO_ERROR();
2312 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2313
2314 int maxTextureImageUnits = 0;
2315 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2316
2317 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2318 }
2319
2320 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2321 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2322 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2323 {
2324 int maxUniforms = 10000;
2325 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2326 EXPECT_GL_NO_ERROR();
2327 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2328
2329 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2330 }
2331
2332 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2333 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2334 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2335 {
2336 // crbug.com/680631
2337 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2338
2339 int maxUniforms = 10000;
2340 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2341 EXPECT_GL_NO_ERROR();
2342 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2343
2344 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2345 }
2346
2347 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2348 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2349 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2350 {
2351 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2352
2353 int maxUniforms = 10000;
2354 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2355 EXPECT_GL_NO_ERROR();
2356
2357 int maxTextureImageUnits = 0;
2358 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2359
2360 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2361 }
2362
2363 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2364 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2365 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2366 {
2367 int maxUniforms = 10000;
2368 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2369 EXPECT_GL_NO_ERROR();
2370 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2371 << std::endl;
2372
2373 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2374 }
2375
2376 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2377 TEST_P(GLSLTest, TextureLOD)
2378 {
2379 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2380
2381 constexpr char kFS[] =
2382 "#extension GL_EXT_shader_texture_lod : require\n"
2383 "uniform sampler2D u_texture;\n"
2384 "void main() {\n"
2385 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2386 "0.0));\n"
2387 "}\n";
2388
2389 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2390 ASSERT_NE(0u, shader);
2391 glDeleteShader(shader);
2392 }
2393
2394 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2395 // function calls to use them in vertex shaders. http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2396 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2397 {
2398 constexpr char kVS[] = R"(
2399 precision highp float;
2400 uniform int uni;
2401 uniform sampler2D texture;
2402
2403 vec4 A();
2404
2405 vec4 B() {
2406 vec4 a;
2407 for(int r=0; r<14; r++){
2408 if (r < uni) return vec4(0.0);
2409 a = A();
2410 }
2411 return a;
2412 }
2413
2414 vec4 A() {
2415 return texture2D(texture, vec2(0.0, 0.0));
2416 }
2417
2418 void main() {
2419 gl_Position = B();
2420 })";
2421
2422 constexpr char kFS[] = R"(
2423 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
2424 )";
2425
2426 ANGLE_GL_PROGRAM(program, kVS, kFS);
2427 }
2428
2429 // Test to verify the a shader can have a sampler unused in a vertex shader
2430 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)2431 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
2432 {
2433 constexpr char kVS[] = R"(
2434 attribute vec2 position;
2435 varying mediump vec2 texCoord;
2436 uniform sampler2D tex;
2437 void main()
2438 {
2439 gl_Position = vec4(position, 0, 1);
2440 texCoord = position * 0.5 + vec2(0.5);
2441 })";
2442
2443 constexpr char kFS[] = R"(
2444 varying mediump vec2 texCoord;
2445 uniform sampler2D tex;
2446 void main()
2447 {
2448 gl_FragColor = texture2D(tex, texCoord);
2449 })";
2450
2451 ANGLE_GL_PROGRAM(program, kVS, kFS);
2452
2453 // Initialize basic red texture.
2454 const std::vector<GLColor> redColors(4, GLColor::red);
2455 GLTexture texture;
2456 glBindTexture(GL_TEXTURE_2D, texture);
2457 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
2458 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2460 ASSERT_GL_NO_ERROR();
2461
2462 drawQuad(program, "position", 0.0f);
2463
2464 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
2465 }
2466
2467 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)2468 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
2469 {
2470 constexpr char kFS[] =
2471 "precision mediump float;\n"
2472 "struct Data { mediump sampler2D data[2]; };\n"
2473 "uniform Data test[2];\n"
2474 "void main() {\n"
2475 " gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
2476 " texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
2477 " texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
2478 " texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
2479 "}\n";
2480
2481 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2482 glUseProgram(program.get());
2483 GLTexture textures[4];
2484 GLColor expected = MakeGLColor(32, 64, 96, 255);
2485 GLubyte data[8] = {}; // 4 bytes of padding, so that texture can be initialized with 4 bytes
2486 memcpy(data, expected.data(), sizeof(expected));
2487 for (int i = 0; i < 4; i++)
2488 {
2489 int outerIdx = i % 2;
2490 int innerIdx = i / 2;
2491 glActiveTexture(GL_TEXTURE0 + i);
2492 glBindTexture(GL_TEXTURE_2D, textures[i]);
2493 // Each element provides two components.
2494 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
2495 std::stringstream uniformName;
2496 uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
2497 // Then send it as a uniform
2498 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
2499 // The uniform should be active.
2500 EXPECT_NE(uniformLocation, -1);
2501
2502 glUniform1i(uniformLocation, 3 - i);
2503 }
2504 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2505 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
2506 }
2507
2508 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
2509 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)2510 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
2511 {
2512 constexpr const char *kFS = R"(
2513 #if __VERSION__ >= 300
2514 inout mediump vec4 fragData;
2515 #else
2516 #extension GL_EXT_shader_texture_lod :enable
2517 #endif
2518
2519 void main()
2520 {
2521 }
2522 )";
2523
2524 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2525 EXPECT_NE(0u, shader);
2526 }
2527
2528 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
2529 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)2530 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
2531 {
2532 constexpr char kVS[] =
2533 "#version 300 es\n"
2534 "precision highp float;\n"
2535 "in vec4 a_vec;\n"
2536 "in mat2 a_mat;\n"
2537 "void main()\n"
2538 "{\n"
2539 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
2540 "}";
2541
2542 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2543 EXPECT_NE(0u, program);
2544 }
2545
2546 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
2547 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
2548 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)2549 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
2550 {
2551 constexpr char kVS[] =
2552 "#version 300 es\n"
2553 "precision highp float;\n"
2554 "in mat3x2 a_matA;\n"
2555 "in mat2x3 a_matB;\n"
2556 "void main()\n"
2557 "{\n"
2558 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
2559 "}";
2560
2561 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2562 EXPECT_NE(0u, program);
2563 }
2564
2565 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)2566 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
2567 {
2568 constexpr char kVS[] =
2569 "#version 300 es\n"
2570 "precision highp float;\n"
2571 "in vec4 a_vec;\n"
2572 "in mat2 a_mat;\n"
2573 "vec4 foo(vec4 a)\n"
2574 "{\n"
2575 " return a;\n"
2576 "}\n"
2577 "vec4 foo(mat2 a)\n"
2578 "{\n"
2579 " return vec4(a[0][0]);\n"
2580 "}\n"
2581 "void main()\n"
2582 "{\n"
2583 " gl_Position = foo(a_vec) + foo(a_mat);\n"
2584 "}";
2585
2586 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2587 EXPECT_NE(0u, program);
2588 }
2589
2590 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)2591 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
2592 {
2593 constexpr char kFS[] = R"(#version 300 es
2594 precision highp float;
2595 out vec4 color;
2596
2597 uniform int i;
2598 uniform uint u;
2599
2600 void main()
2601 {
2602 bool b = i > 10;
2603
2604 mat3x2 mi = mat3x2(i);
2605 mat4 mu = mat4(u);
2606 mat2x4 mb = mat2x4(b);
2607
2608 mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
2609
2610 color = vec4(mi[0][0] == float(i) ? 1 : 0,
2611 mu[2][2] == float(u) ? 1 : 0,
2612 mb[1][1] == float(b) ? 1 : 0,
2613 m[0][1] == float(i) && m[1][0] == float(u) && m[2][0] == float(b) ? 1 : 0);
2614 })";
2615
2616 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2617 glUseProgram(program);
2618
2619 GLint iloc = glGetUniformLocation(program, "i");
2620 GLint uloc = glGetUniformLocation(program, "u");
2621 ASSERT_NE(iloc, -1);
2622 ASSERT_NE(uloc, -1);
2623 glUniform1i(iloc, -123);
2624 glUniform1ui(uloc, 456);
2625
2626 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2627 EXPECT_GL_NO_ERROR();
2628
2629 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2630 }
2631
2632 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)2633 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
2634 {
2635 constexpr char kFS[] = R"(#version 300 es
2636 precision highp float;
2637 out vec4 color;
2638
2639 uniform float f;
2640
2641 void main()
2642 {
2643 mat4 m = mat4(f);
2644 ivec3 vi = ivec3(m);
2645 uvec2 vu = uvec2(m);
2646 bvec4 vb = bvec4(m);
2647
2648 color = vec4(vi.x == int(f) ? 1 : 0,
2649 vu.x == uint(f) ? 1 : 0,
2650 vb.x == bool(f) ? 1 : 0,
2651 1);
2652 })";
2653
2654 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2655 glUseProgram(program);
2656
2657 GLint floc = glGetUniformLocation(program, "f");
2658 ASSERT_NE(floc, -1);
2659 glUniform1f(floc, 123);
2660
2661 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2662 EXPECT_GL_NO_ERROR();
2663
2664 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2665 }
2666
2667 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)2668 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
2669 {
2670 constexpr char kFS[] = R"(#version 300 es
2671 precision highp float;
2672 out vec4 color;
2673
2674 uniform float f;
2675 uniform int i;
2676 uniform uint u;
2677
2678 void main()
2679 {
2680 mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
2681 mat3x2 m32_2 = mat3x2(m32_1);
2682 mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
2683 mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
2684 mat2x3 m23_2 = mat2x3(m23_1);
2685 mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
2686 vec2 v2_1 = m32_1[0];
2687 vec2 v2_2 = m32_2[0];
2688 ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
2689 ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
2690 uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
2691 uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
2692
2693 color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
2694 v2_1 == v2_2 ? 1 : 0,
2695 (v3_1 == v3_2 ? 0.5 : 0.0) +
2696 (v4_1 == v4_2 ? 0.5 : 0.0),
2697 (m32_1 != m32_3 ? 0.125 : 0.0) +
2698 (m23_1 != m23_3 ? 0.125 : 0.0) +
2699 (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
2700 (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
2701 (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
2702 })";
2703
2704 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2705 glUseProgram(program);
2706
2707 GLint floc = glGetUniformLocation(program, "f");
2708 GLint iloc = glGetUniformLocation(program, "i");
2709 GLint uloc = glGetUniformLocation(program, "u");
2710 ASSERT_NE(floc, -1);
2711 ASSERT_NE(iloc, -1);
2712 ASSERT_NE(uloc, -1);
2713 glUniform1f(floc, 1.5);
2714 glUniform1i(iloc, -123);
2715 glUniform1ui(uloc, 456);
2716
2717 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2718 EXPECT_GL_NO_ERROR();
2719
2720 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2721 }
2722
2723 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)2724 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
2725 {
2726 constexpr char kFS[] = R"(#version 310 es
2727 precision highp float;
2728 out vec4 color;
2729
2730 uniform float f;
2731 uniform int i;
2732 uniform uint u;
2733
2734 struct S
2735 {
2736 float f;
2737 int i;
2738 uint u;
2739 vec4 v;
2740 ivec3 iv;
2741 uvec2 uv;
2742 mat3x2 m32;
2743 mat2x3 m23;
2744 float fa[3][4][5];
2745 int ia[4];
2746 uint ua[6][2];
2747 };
2748
2749 struct T
2750 {
2751 S s1;
2752 S s2[3][2];
2753 };
2754
2755 void main()
2756 {
2757 float fa[5] = float[5](f, f, f, f, f);
2758 int ia[4] = int[4](i, i, i, i);
2759 uint ua[2] = uint[2](u, u);
2760
2761 S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
2762 mat3x2(vec2(f), vec2(i), vec2(u)),
2763 mat2x3(vec3(f), vec3(i)),
2764 float[3][4][5](
2765 float[4][5](fa, fa, fa, fa),
2766 float[4][5](fa, fa, fa, fa),
2767 float[4][5](fa, fa, fa, fa)),
2768 ia,
2769 uint[6][2](ua, ua, ua, ua, ua, ua));
2770
2771 S s2[2] = S[2](s1, s1);
2772 s2[1].fa[0][1][2] = float(i);
2773
2774 T t1 = T(s1, S[3][2](s2, s2, s2));
2775 T t2 = T(s2[1], S[3][2](s2, s2, s2));
2776
2777 T ta1[2] = T[2](t1, t2);
2778 T ta2[2] = T[2](t1, t2);
2779 T ta3[2] = T[2](t2, t1);
2780
2781 color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
2782 (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
2783 (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
2784 (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
2785 })";
2786
2787 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
2788 glUseProgram(program);
2789
2790 GLint floc = glGetUniformLocation(program, "f");
2791 GLint iloc = glGetUniformLocation(program, "i");
2792 GLint uloc = glGetUniformLocation(program, "u");
2793 ASSERT_NE(floc, -1);
2794 ASSERT_NE(iloc, -1);
2795 ASSERT_NE(uloc, -1);
2796 glUniform1f(floc, 1.5);
2797 glUniform1i(iloc, -123);
2798 glUniform1ui(uloc, 456);
2799
2800 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2801 EXPECT_GL_NO_ERROR();
2802
2803 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
2804 }
2805
2806 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
2807 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)2808 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
2809 {
2810 std::stringstream vertexShaderStream;
2811 // Note: SPIR-V doesn't allow more than 255 parameters to a function.
2812 const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
2813
2814 vertexShaderStream << "#version 300 es\n"
2815 "precision highp float;\n"
2816 "in vec4 a_vec;\n"
2817 "vec4 lotsOfVec4Parameters(";
2818 for (unsigned int i = 0; i < paramCount - 1; ++i)
2819 {
2820 vertexShaderStream << "vec4 a" << i << ", ";
2821 }
2822 vertexShaderStream << "vec4 aLast)\n"
2823 "{\n"
2824 " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
2825 for (unsigned int i = 0; i < paramCount - 1; ++i)
2826 {
2827 vertexShaderStream << " sum += a" << i << ";\n";
2828 }
2829 vertexShaderStream << " sum += aLast;\n"
2830 " return sum;\n "
2831 "}\n"
2832 "void main()\n"
2833 "{\n"
2834 " gl_Position = lotsOfVec4Parameters(";
2835 for (unsigned int i = 0; i < paramCount - 1; ++i)
2836 {
2837 vertexShaderStream << "a_vec, ";
2838 }
2839 vertexShaderStream << "a_vec);\n"
2840 "}";
2841
2842 GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
2843 EXPECT_NE(0u, program);
2844 }
2845
2846 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
2847 // Test a shader where a global constant array is initialized with an expression containing array
2848 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2849 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
2850 // Also includes multiple array initializers in one declaration, where only the second one has
2851 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
2852 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)2853 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2854 {
2855 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2856 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2857
2858 constexpr char kFS[] =
2859 "#version 300 es\n"
2860 "precision highp float;\n"
2861 "out vec4 my_FragColor;\n"
2862 "const highp float f[2] = float[2](0.1, 0.2);\n"
2863 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2864 "void main()\n"
2865 "{\n"
2866 " my_FragColor = vec4(h[1]);\n"
2867 "}";
2868
2869 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2870 EXPECT_NE(0u, program);
2871 }
2872
2873 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)2874 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2875 {
2876 ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
2877
2878 constexpr char kFS[] =
2879 "precision mediump float;\n"
2880 "uniform sampler2D uni[2];\n"
2881 "\n"
2882 "float zero(int x)\n"
2883 "{\n"
2884 " return float(x) - float(x);\n"
2885 "}\n"
2886 "\n"
2887 "void main()\n"
2888 "{\n"
2889 " vec4 c = vec4(0,0,0,0);\n"
2890 " for (int ii = 1; ii < 3; ++ii) {\n"
2891 " if (c.x > 255.0) {\n"
2892 " c.x = 255.0 + zero(ii);\n"
2893 " break;\n"
2894 " }\n"
2895 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2896 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2897 // without an extension.
2898 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2899 " }\n"
2900 " gl_FragColor = c;\n"
2901 "}";
2902
2903 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2904 EXPECT_NE(0u, program);
2905 }
2906
2907 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2908 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2909 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)2910 TEST_P(GLSLTest, PragmaDirective)
2911 {
2912 constexpr char kVS[] =
2913 "#pragma STDGL invariant(all)\n"
2914 "void main()\n"
2915 "{\n"
2916 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2917 "}\n";
2918
2919 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2920 EXPECT_NE(0u, program);
2921 }
2922
2923 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2924 // The function call that returns the array needs to be evaluated after ++j for the expression to
2925 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)2926 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2927 {
2928 constexpr char kFS[] =
2929 "#version 300 es\n"
2930 "precision mediump float;\n"
2931 "out vec4 my_FragColor; \n"
2932 "int[2] func(int param) {\n"
2933 " return int[2](param, param);\n"
2934 "}\n"
2935 "void main() {\n"
2936 " int a[2]; \n"
2937 " for (int i = 0; i < 2; ++i) {\n"
2938 " a[i] = 1;\n"
2939 " }\n"
2940 " int j = 0; \n"
2941 " bool result = ((++j), (a == func(j)));\n"
2942 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2943 "}\n";
2944
2945 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2946 ASSERT_NE(0u, program);
2947
2948 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2949
2950 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2951 }
2952
2953 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2954 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2955 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)2956 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2957 {
2958 constexpr char kFS[] =
2959 "#version 300 es\n"
2960 "precision mediump float;\n"
2961 "out vec4 my_FragColor; \n"
2962 "void main() {\n"
2963 " int j = 0; \n"
2964 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2965 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2966 "}\n";
2967
2968 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2969 ASSERT_NE(0u, program);
2970
2971 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2972
2973 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2974 }
2975
2976 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2977 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)2978 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2979 {
2980 constexpr char kFS[] =
2981 "#version 300 es\n"
2982 "precision mediump float;\n"
2983 "out vec4 my_FragColor;\n"
2984 "uniform int u_zero;\n"
2985 "int sideEffectCount = 0;\n"
2986 "float func() {\n"
2987 " ++sideEffectCount;\n"
2988 " return -1.0;\n"
2989 "}\n"
2990 "void main() {\n"
2991 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2992 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2993 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2994 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2995 "}\n";
2996
2997 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
2998 ASSERT_NE(0u, program);
2999
3000 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3001
3002 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3003 }
3004
3005 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3006 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3007 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)3008 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3009 {
3010 constexpr char kVS[] =
3011 "attribute vec2 aPosition;\n"
3012 "void main()\n"
3013 "{\n"
3014 " gl_Position = vec4(aPosition, 0, 1);\n"
3015 " gl_PointSize = 1.0;\n"
3016 "}";
3017 constexpr char kFS[] =
3018 "void main()\n"
3019 "{\n"
3020 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3021 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3022 "}";
3023
3024 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3025 drawQuad(prog.get(), "aPosition", 0.5f);
3026 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3027 }
3028
3029 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3030 TEST_P(GLSLTest, NestedPowStatements)
3031 {
3032 // https://crbug.com/1127866 - possible NVIDIA driver issue
3033 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3034
3035 constexpr char kFS[] =
3036 "precision mediump float;\n"
3037 "float func(float v)\n"
3038 "{\n"
3039 " float f1 = pow(v, 2.0);\n"
3040 " return pow(f1 + v, 2.0);\n"
3041 "}\n"
3042 "void main()\n"
3043 "{\n"
3044 " float v = func(2.0);\n"
3045 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3046 "}";
3047
3048 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3049 drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3050 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3051 }
3052
3053 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3054 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3055 {
3056 constexpr char kFS[] =
3057 "#version 300 es\n"
3058 "out highp vec4 o_color;\n"
3059 "void main() {\n"
3060 " highp float f = -1.0;\n"
3061 " // atan(tan(0.5), -f) should be 0.5.\n"
3062 " highp float v = atan(tan(0.5), -f);\n"
3063 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3064 "}\n";
3065
3066 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3067 drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3068 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3069 }
3070
3071 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3072 TEST_P(GLSLTest_ES3, AtanVec2)
3073 {
3074 constexpr char kFS[] =
3075 "#version 300 es\n"
3076 "out highp vec4 o_color;\n"
3077 "void main() {\n"
3078 " highp float f = 1.0;\n"
3079 " // atan(tan(0.5), f) should be 0.5.\n"
3080 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3081 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3082 "vec4(1, 0, 0, 1);\n"
3083 "}\n";
3084
3085 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3086 drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3087 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3088 }
3089
3090 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3091 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3092 {
3093 // http://anglebug.com/5242
3094 ANGLE_SKIP_TEST_IF(IsMetal() && IsIntel());
3095
3096 constexpr char kVS[] =
3097 "#version 300 es\n"
3098 "in highp vec4 position;\n"
3099 "out mediump vec4 v_color;\n"
3100 "uniform int ui_one;\n"
3101 "uniform int ui_two;\n"
3102 "uniform int ui_three;\n"
3103 "void main() {\n"
3104 " int s[3];\n"
3105 " s[0] = ui_one;\n"
3106 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
3107 " s[2] = ui_three;\n"
3108 " int result = 0;\n"
3109 " for (int i = 0; i < ui_three; i++) {\n"
3110 " result += s[i];\n"
3111 " }\n"
3112 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3113 " gl_Position = position;\n"
3114 "}\n";
3115 constexpr char kFS[] =
3116 "#version 300 es\n"
3117 "in mediump vec4 v_color;\n"
3118 "layout(location=0) out mediump vec4 o_color;\n"
3119 "void main() {\n"
3120 " o_color = v_color;\n"
3121 "}\n";
3122
3123 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3124
3125 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3126 ASSERT_NE(-1, oneIndex);
3127 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3128 ASSERT_NE(-1, twoIndex);
3129 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3130 ASSERT_NE(-1, threeIndex);
3131 glUseProgram(prog.get());
3132 glUniform1i(oneIndex, 1);
3133 glUniform1i(twoIndex, 2);
3134 glUniform1i(threeIndex, 3);
3135
3136 drawQuad(prog.get(), "position", 0.5f);
3137 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3138 }
3139
3140 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3141 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3142 {
3143 // http://anglebug.com/5242
3144 ANGLE_SKIP_TEST_IF(IsMetal() && IsIntel());
3145
3146 constexpr char kVS[] =
3147 "#version 300 es\n"
3148 "in highp vec4 position;\n"
3149 "out mediump vec4 v_color;\n"
3150 "uniform uint ui_one;\n"
3151 "uniform uint ui_two;\n"
3152 "uniform uint ui_three;\n"
3153 "void main() {\n"
3154 " uint s[3];\n"
3155 " s[0] = ui_one;\n"
3156 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
3157 " s[2] = ui_three;\n"
3158 " uint result = 0u;\n"
3159 " for (uint i = 0u; i < ui_three; i++) {\n"
3160 " result += s[i];\n"
3161 " }\n"
3162 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3163 " gl_Position = position;\n"
3164 "}\n";
3165 constexpr char kFS[] =
3166 "#version 300 es\n"
3167 "in mediump vec4 v_color;\n"
3168 "layout(location=0) out mediump vec4 o_color;\n"
3169 "void main() {\n"
3170 " o_color = v_color;\n"
3171 "}\n";
3172
3173 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3174
3175 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3176 ASSERT_NE(-1, oneIndex);
3177 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3178 ASSERT_NE(-1, twoIndex);
3179 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3180 ASSERT_NE(-1, threeIndex);
3181 glUseProgram(prog.get());
3182 glUniform1ui(oneIndex, 1u);
3183 glUniform1ui(twoIndex, 2u);
3184 glUniform1ui(threeIndex, 3u);
3185
3186 drawQuad(prog.get(), "position", 0.5f);
3187 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3188 }
3189
3190 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3191 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3192 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3193 {
3194 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3195 // its default value false.
3196 constexpr char kFS[] =
3197 "precision mediump float;\n"
3198 "uniform bool keep_flop_positive;\n"
3199 "float flop;\n"
3200 "void main() {\n"
3201 " flop = -1.0,\n"
3202 " (flop *= -1.0,\n"
3203 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3204 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
3205 "}";
3206
3207 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3208 drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3209 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3210 }
3211
3212 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)3213 TEST_P(GLSLTest, ExternalAnd2DSampler)
3214 {
3215 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
3216
3217 constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
3218 precision mediump float;
3219 uniform samplerExternalOES tex0;
3220 uniform sampler2D tex1;
3221 void main(void)
3222 {
3223 vec2 uv = vec2(0.0, 0.0);
3224 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
3225 })";
3226
3227 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3228 }
3229
3230 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)3231 TEST_P(GLSLTest, VaryingMatrixArray)
3232 {
3233 constexpr char kVS[] =
3234 "uniform vec2 u_a1;\n"
3235 "uniform vec2 u_a2;\n"
3236 "attribute vec4 a_position;\n"
3237 "varying mat2 v_mat[2];\n"
3238 "void main() {\n"
3239 " v_mat[0] = mat2(u_a1, u_a2);\n"
3240 " v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
3241 " gl_Position = a_position;\n"
3242 "}";
3243
3244 constexpr char kFS[] =
3245 "precision mediump float;\n"
3246 "varying mat2 v_mat[2];\n"
3247 "void main(void)\n"
3248 "{\n"
3249 " gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
3250 "}";
3251
3252 ANGLE_GL_PROGRAM(program, kVS, kFS);
3253
3254 GLint oneIndex = glGetUniformLocation(program, "u_a1");
3255 ASSERT_NE(-1, oneIndex);
3256 GLint twoIndex = glGetUniformLocation(program, "u_a2");
3257 ASSERT_NE(-1, twoIndex);
3258 glUseProgram(program);
3259 glUniform2f(oneIndex, 1, 0.5f);
3260 glUniform2f(twoIndex, 0.25f, 0.125f);
3261
3262 drawQuad(program, "a_position", 0.5f);
3263 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3264 }
3265
3266 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)3267 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
3268 {
3269 // TODO(anglebug.com/5491): Skipping initial failures so we can set up a passing iOS test bot.
3270 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
3271
3272 constexpr char kVS[] =
3273 "#version 300 es\n"
3274 "uniform vec2 u_a1;\n"
3275 "uniform vec2 u_a2;\n"
3276 "in vec4 a_position;\n"
3277 "centroid out mat3x2 v_mat[2];\n"
3278 "void main() {\n"
3279 " v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
3280 " v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
3281 " gl_Position = a_position;\n"
3282 "}";
3283
3284 constexpr char kFS[] =
3285 "#version 300 es\n"
3286 "precision mediump float;\n"
3287 "centroid in mat3x2 v_mat[2];\n"
3288 "layout(location = 0) out vec4 out_color;\n"
3289 "void main(void)\n"
3290 "{\n"
3291 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
3292 "}";
3293
3294 ANGLE_GL_PROGRAM(program, kVS, kFS);
3295
3296 GLint oneIndex = glGetUniformLocation(program, "u_a1");
3297 ASSERT_NE(-1, oneIndex);
3298 GLint twoIndex = glGetUniformLocation(program, "u_a2");
3299 ASSERT_NE(-1, twoIndex);
3300 glUseProgram(program);
3301 glUniform2f(oneIndex, 1, 0.5f);
3302 glUniform2f(twoIndex, 0.25f, 0.125f);
3303
3304 drawQuad(program, "a_position", 0.5f);
3305 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3306 }
3307
3308 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)3309 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
3310 {
3311 constexpr char kVS[] =
3312 "#version 300 es\n"
3313 "uniform vec2 u_a1;\n"
3314 "uniform vec2 u_a2;\n"
3315 "in vec4 a_position;\n"
3316 "flat out mat2 v_mat[2];\n"
3317 "void main() {\n"
3318 " v_mat[0] = mat2(u_a1, u_a2);\n"
3319 " v_mat[1] = mat2(u_a2, u_a1);\n"
3320 " gl_Position = a_position;\n"
3321 "}";
3322
3323 constexpr char kFS[] =
3324 "#version 300 es\n"
3325 "precision mediump float;\n"
3326 "flat in mat2 v_mat[2];\n"
3327 "layout(location = 0) out vec4 out_color;\n"
3328 "void main(void)\n"
3329 "{\n"
3330 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
3331 "}";
3332
3333 ANGLE_GL_PROGRAM(program, kVS, kFS);
3334
3335 GLint oneIndex = glGetUniformLocation(program, "u_a1");
3336 ASSERT_NE(-1, oneIndex);
3337 GLint twoIndex = glGetUniformLocation(program, "u_a2");
3338 ASSERT_NE(-1, twoIndex);
3339 glUseProgram(program);
3340 glUniform2f(oneIndex, 1, 0.5f);
3341 glUniform2f(twoIndex, 0.25f, 0.125f);
3342
3343 drawQuad(program, "a_position", 0.5f);
3344 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
3345 }
3346
3347 // Test that literal infinity can be written out from the shader translator.
3348 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralInfinityOutput)3349 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
3350 {
3351 constexpr char kFS[] =
3352 "#version 300 es\n"
3353 "precision highp float;\n"
3354 "out vec4 out_color;\n"
3355 "uniform float u;\n"
3356 "void main()\n"
3357 "{\n"
3358 " float infVar = 1.0e40 - u;\n"
3359 " bool correct = isinf(infVar) && infVar > 0.0;\n"
3360 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3361 "}\n";
3362
3363 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3364 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3365 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3366 }
3367
3368 // Test that literal negative infinity can be written out from the shader translator.
3369 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralNegativeInfinityOutput)3370 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
3371 {
3372 constexpr char kFS[] =
3373 "#version 300 es\n"
3374 "precision highp float;\n"
3375 "out vec4 out_color;\n"
3376 "uniform float u;\n"
3377 "void main()\n"
3378 "{\n"
3379 " float infVar = -1.0e40 + u;\n"
3380 " bool correct = isinf(infVar) && infVar < 0.0;\n"
3381 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3382 "}\n";
3383
3384 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3385 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3387 }
3388
3389 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
3390 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
3391 // a unittest for them. Instead we add the tests as end2end so will in particular test
3392 // TranslatorHLSL when run on Windows.
3393
3394 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)3395 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
3396 {
3397 constexpr char kFS[] = R"(#version 300 es
3398 precision mediump float;
3399 out vec4 color;
3400
3401 uniform float u;
3402 float c = 0.0;
3403 float sideEffect()
3404 {
3405 c = u;
3406 return c;
3407 }
3408
3409 void main(void)
3410 {
3411 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
3412 color = vec4(b + c);
3413 })";
3414
3415 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3416 }
3417
3418 // Test that passes splitting multiple declarations and comma operators and for loops are
3419 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)3420 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
3421 {
3422 constexpr char kFS[] = R"(#version 300 es
3423 precision mediump float;
3424 out vec4 color;
3425
3426 uniform float u;
3427 float c = 0.0;
3428 float sideEffect()
3429 {
3430 c = u;
3431 return c;
3432 }
3433
3434 void main(void)
3435 {
3436 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
3437 {
3438 b += 1.0;
3439 color = vec4(b);
3440 }
3441 })";
3442
3443 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3444 }
3445
3446 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)3447 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
3448 {
3449 constexpr char kFS[] =
3450 "#version 300 es\n"
3451 "precision mediump float;\n"
3452 "out vec4 color;\n"
3453 "void main(void)\n"
3454 "{\n"
3455 " for(float a = 0.0, b = 1.0;; a++)\n"
3456 " {\n"
3457 " b += 1.0;\n"
3458 " if (a > 10.0) {break;}\n"
3459 " color = vec4(b);\n"
3460 " }\n"
3461 "}\n";
3462
3463 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3464 }
3465
3466 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)3467 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
3468 {
3469 constexpr char kFS[] =
3470 "#version 300 es\n"
3471 "precision mediump float;\n"
3472 "out vec4 color;\n"
3473 "void main(void)\n"
3474 "{\n"
3475 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
3476 " {\n"
3477 " b += 1.0;\n"
3478 " a += 1.0;\n"
3479 " color = vec4(b);\n"
3480 " }\n"
3481 "}\n";
3482
3483 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3484 }
3485
3486 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
3487 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)3488 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
3489 {
3490 constexpr char kFS[] =
3491 "#version 300 es\n"
3492 "precision mediump float;\n"
3493 "out vec4 my_FragColor;\n"
3494 "uniform int u_zero;\n"
3495 "void main() {\n"
3496 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
3497 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
3498 " float f = m[1][1];\n"
3499 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
3500 "}\n";
3501
3502 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3503 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3504 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3505 }
3506
3507 class WebGLGLSLTest : public GLSLTest
3508 {
3509 protected:
WebGLGLSLTest()3510 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
3511 };
3512
3513 class WebGL2GLSLTest : public GLSLTest
3514 {
3515 protected:
WebGL2GLSLTest()3516 WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
3517 };
3518
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)3519 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
3520 {
3521 GLint maxVaryings = 0;
3522 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3523
3524 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
3525 // This test should fail, since we are really using (maxVaryings + 1) varyings.
3526 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
3527 }
3528
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)3529 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
3530 {
3531 GLint maxVaryings = 0;
3532 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3533
3534 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
3535 // This test should fail, since we are really using (maxVaryings + 1) varyings.
3536 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
3537 }
3538
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)3539 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
3540 {
3541 GLint maxVaryings = 0;
3542 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3543
3544 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
3545 }
3546
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)3547 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
3548 {
3549 GLint maxVaryings = 0;
3550 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3551
3552 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
3553 }
3554
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)3555 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
3556 {
3557 GLint maxVaryings = 0;
3558 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3559
3560 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
3561 }
3562
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)3563 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
3564 {
3565 GLint maxVaryings = 0;
3566 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3567
3568 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
3569 }
3570
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)3571 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
3572 {
3573 GLint maxVaryings = 0;
3574 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
3575
3576 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
3577 false);
3578 }
3579
3580 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)3581 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
3582 {
3583 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
3584 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
3585
3586 // Failing on N5X Oreo http://anglebug.com/2304
3587 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3588
3589 constexpr char kFS[] =
3590 "#version 310 es\n"
3591 "precision mediump float;\n"
3592 "out vec4 my_FragColor;\n"
3593 "uniform int u_zero;\n"
3594 "void main() {\n"
3595 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
3596 " {\n"
3597 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3598 " }\n"
3599 " else\n"
3600 " {\n"
3601 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
3602 " }\n"
3603 "}\n";
3604
3605 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3606 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3607 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3608 }
3609
3610 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)3611 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
3612 {
3613 // http://anglebug.com/1924
3614 ANGLE_SKIP_TEST_IF(IsOpenGL());
3615
3616 // The shader first assigns v.x to v.z (1.0)
3617 // Then v.y to v.y (2.0)
3618 // Then v.z to v.x (1.0)
3619 constexpr char kFS[] =
3620 "#version 300 es\n"
3621 "precision highp float;\n"
3622 "out vec4 my_FragColor;\n"
3623 "void main() {\n"
3624 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
3625 " for (int i = 0; i < 3; i++) {\n"
3626 " v.zyx[i] = v[i];\n"
3627 " }\n"
3628 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
3629 "0, 0, 1);\n"
3630 "}\n";
3631
3632 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3633 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
3634 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3635 }
3636
3637 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)3638 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
3639 {
3640 // Crashes on an assertion. The driver reports no atomic counter buffers when queried from the
3641 // program, but ANGLE believes there to be one.
3642 //
3643 // This is likely due to the fact that ANGLE generates the following code, as a side effect of
3644 // the code on which .length() is being called:
3645 //
3646 // _uac1[(_uvalue = _utestSideEffectValue)];
3647 //
3648 // The driver is optimizing the subscription out, and calling the atomic counter inactive. This
3649 // was observed on nvidia, mesa and amd/windows.
3650 //
3651 // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
3652 // driver says don't.
3653 //
3654 // http://anglebug.com/3782
3655 ANGLE_SKIP_TEST_IF(IsOpenGL());
3656
3657 constexpr char kCS[] = R"(#version 310 es
3658 precision mediump float;
3659 layout(local_size_x=1) in;
3660
3661 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
3662 uniform uint testSideEffectValue;
3663
3664 layout(binding = 1, std140) buffer Result
3665 {
3666 uint value;
3667 } result;
3668
3669 void main() {
3670 bool passed = true;
3671 if (ac1.length() != 2)
3672 {
3673 passed = false;
3674 }
3675 uint value = 0u;
3676 if (ac1[value = testSideEffectValue].length() != 3)
3677 {
3678 passed = false;
3679 }
3680 if (value != testSideEffectValue)
3681 {
3682 passed = false;
3683 }
3684 if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
3685 {
3686 passed = false;
3687 }
3688 if (value != testSideEffectValue + 1u)
3689 {
3690 passed = false;
3691 }
3692 result.value = passed ? 255u : 127u;
3693 })";
3694
3695 constexpr unsigned int kUniformTestValue = 17;
3696 constexpr unsigned int kExpectedSuccessValue = 255;
3697 constexpr unsigned int kAtomicCounterRows = 2;
3698 constexpr unsigned int kAtomicCounterCols = 3;
3699
3700 GLint maxAtomicCounters = 0;
3701 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
3702 EXPECT_GL_NO_ERROR();
3703
3704 // Required minimum is 8 by the spec
3705 EXPECT_GE(maxAtomicCounters, 8);
3706 ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
3707 kAtomicCounterRows * kAtomicCounterCols);
3708
3709 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3710 glUseProgram(program.get());
3711
3712 constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
3713 GLBuffer atomicCounterBuffer;
3714 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
3715 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
3716 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
3717
3718 constexpr unsigned int kOutputInitValue = 0;
3719 GLBuffer shaderStorageBuffer;
3720 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3721 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
3722 GL_STATIC_DRAW);
3723 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
3724
3725 GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
3726 EXPECT_NE(uniformLocation, -1);
3727 glUniform1ui(uniformLocation, kUniformTestValue);
3728 EXPECT_GL_NO_ERROR();
3729
3730 glDispatchCompute(1, 1, 1);
3731
3732 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3733
3734 const GLuint *ptr = reinterpret_cast<const GLuint *>(
3735 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
3736 EXPECT_EQ(*ptr, kExpectedSuccessValue);
3737 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3738 }
3739
3740 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)3741 TEST_P(GLSLTest_ES31, InactiveImages)
3742 {
3743 ANGLE_SKIP_TEST_IF(IsD3D11());
3744
3745 constexpr char kCS[] = R"(#version 310 es
3746 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3747 layout(rgba32ui) uniform highp readonly uimage2D image1;
3748 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
3749 void main()
3750 {
3751 })";
3752
3753 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3754
3755 glUseProgram(program.get());
3756 glDispatchCompute(1, 1, 1);
3757 EXPECT_GL_NO_ERROR();
3758
3759 // Verify that the images are indeed inactive.
3760 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
3761 EXPECT_GL_NO_ERROR();
3762 EXPECT_EQ(GL_INVALID_INDEX, index);
3763
3764 index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
3765 EXPECT_GL_NO_ERROR();
3766 EXPECT_EQ(GL_INVALID_INDEX, index);
3767 }
3768
3769 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)3770 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
3771 {
3772 constexpr char kCS[] = R"(#version 310 es
3773 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3774 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
3775 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
3776 void main()
3777 {
3778 })";
3779
3780 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3781
3782 glUseProgram(program.get());
3783 glDispatchCompute(1, 1, 1);
3784 EXPECT_GL_NO_ERROR();
3785
3786 // Verify that the atomic counters are indeed inactive.
3787 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
3788 EXPECT_GL_NO_ERROR();
3789 EXPECT_EQ(GL_INVALID_INDEX, index);
3790
3791 index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
3792 EXPECT_GL_NO_ERROR();
3793 EXPECT_EQ(GL_INVALID_INDEX, index);
3794 }
3795
3796 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)3797 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
3798 {
3799 constexpr char kCS[] = R"(#version 310 es
3800 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3801 struct S
3802 {
3803 vec4 v;
3804 sampler2D t[10];
3805 };
3806 uniform S s;
3807 void main()
3808 {
3809 })";
3810
3811 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3812
3813 glUseProgram(program.get());
3814 glDispatchCompute(1, 1, 1);
3815 EXPECT_GL_NO_ERROR();
3816 }
3817
3818 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)3819 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
3820 {
3821 constexpr char kFS[] =
3822 "#version 310 es\n"
3823 "precision mediump float;\n"
3824 "out vec4 my_FragColor;\n"
3825 "uniform ivec2 test[2][2];\n"
3826 "void main() {\n"
3827 " bool passed = true;\n"
3828 " for (int i = 0; i < 2; i++) {\n"
3829 " for (int j = 0; j < 2; j++) {\n"
3830 " if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
3831 " passed = false;\n"
3832 " }\n"
3833 " }\n"
3834 " }\n"
3835 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3836 "}\n";
3837
3838 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3839 glUseProgram(program.get());
3840 for (int i = 0; i < 2; i++)
3841 {
3842 for (int j = 0; j < 2; j++)
3843 {
3844 std::stringstream uniformName;
3845 uniformName << "test[" << i << "][" << j << "]";
3846 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3847 // All array indices should be used.
3848 EXPECT_NE(uniformLocation, -1);
3849 glUniform2i(uniformLocation, i + 1, j + 1);
3850 }
3851 }
3852 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3853 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3854 }
3855
3856 // Test that array indices for arrays of arrays of basic types work as expected
3857 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)3858 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
3859 {
3860 // anglebug.com/3821 - fails on AMD Windows
3861 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3862 constexpr char kFS[] =
3863 "#version 310 es\n"
3864 "precision mediump float;\n"
3865 "out vec4 my_FragColor;\n"
3866 "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
3867 "void main() {\n"
3868 " bool passed = true;\n"
3869 " for (int i = 0; i < 2; i++) {\n"
3870 " for (int j = 0; j < 2; j++) {\n"
3871 " if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
3872 " passed = false;\n"
3873 " }\n"
3874 " }\n"
3875 " }\n"
3876 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3877 "}\n";
3878
3879 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3880 glUseProgram(program.get());
3881 // Use interface queries to determine buffer size and offset
3882 GLuint uboBlockIndex = glGetProgramResourceIndex(program.get(), GL_UNIFORM_BLOCK, "UBO");
3883 GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
3884 GLint uboDataSize;
3885 glGetProgramResourceiv(program.get(), GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
3886 nullptr, &uboDataSize);
3887 std::unique_ptr<char[]> uboData(new char[uboDataSize]);
3888 for (int i = 0; i < 2; i++)
3889 {
3890 std::stringstream resourceName;
3891 resourceName << "UBO.test[" << i << "][0]";
3892 GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
3893 struct
3894 {
3895 GLint stride;
3896 GLint offset;
3897 } values;
3898 GLuint resourceIndex =
3899 glGetProgramResourceIndex(program.get(), GL_UNIFORM, resourceName.str().c_str());
3900 ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
3901 glGetProgramResourceiv(program.get(), GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2,
3902 nullptr, &values.stride);
3903 for (int j = 0; j < 2; j++)
3904 {
3905 GLint(&dataPtr)[2] =
3906 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
3907 dataPtr[0] = i + 1;
3908 dataPtr[1] = j + 1;
3909 }
3910 }
3911 GLBuffer ubo;
3912 glBindBuffer(GL_UNIFORM_BUFFER, ubo.get());
3913 glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
3914 GLuint ubo_index = glGetUniformBlockIndex(program.get(), "UBO");
3915 ASSERT_NE(ubo_index, GL_INVALID_INDEX);
3916 glUniformBlockBinding(program.get(), ubo_index, 5);
3917 glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo.get());
3918 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3919 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3920 }
3921
3922 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)3923 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
3924 {
3925 constexpr char kFS[] =
3926 "#version 310 es\n"
3927 "precision mediump float;\n"
3928 "out vec4 my_FragColor;\n"
3929 "uniform mediump isampler2D test[2][2];\n"
3930 "void main() {\n"
3931 " bool passed = true;\n"
3932 "#define DO_CHECK(i,j) \\\n"
3933 " if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
3934 " passed = false; \\\n"
3935 " }\n"
3936 " DO_CHECK(0, 0)\n"
3937 " DO_CHECK(0, 1)\n"
3938 " DO_CHECK(1, 0)\n"
3939 " DO_CHECK(1, 1)\n"
3940 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
3941 "}\n";
3942
3943 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3944 glUseProgram(program.get());
3945 GLTexture textures[2][2];
3946 for (int i = 0; i < 2; i++)
3947 {
3948 for (int j = 0; j < 2; j++)
3949 {
3950 // First generate the texture
3951 int textureUnit = i * 2 + j;
3952 glActiveTexture(GL_TEXTURE0 + textureUnit);
3953 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
3954 GLint texData[2] = {i + 1, j + 1};
3955 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
3956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3958 // Then send it as a uniform
3959 std::stringstream uniformName;
3960 uniformName << "test[" << i << "][" << j << "]";
3961 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3962 // All array indices should be used.
3963 EXPECT_NE(uniformLocation, -1);
3964 glUniform1i(uniformLocation, textureUnit);
3965 }
3966 }
3967 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
3968 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3969 }
3970
3971 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)3972 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
3973 {
3974 // http://anglebug.com/5072
3975 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3976
3977 // Fails on D3D due to mistranslation.
3978 ANGLE_SKIP_TEST_IF(IsD3D());
3979
3980 // Fails on Android on GLES.
3981 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3982
3983 GLint maxTextures, maxComputeImageUniforms;
3984 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
3985 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
3986 ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
3987 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
3988
3989 constexpr char kComputeShader[] = R"(#version 310 es
3990 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3991 layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
3992 layout(binding = 1, std430) buffer Output {
3993 uint image_value;
3994 } outbuf;
3995
3996 void main(void)
3997 {
3998 outbuf.image_value = uint(0.0);
3999 outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
4000 outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
4001 outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
4002 outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
4003 outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
4004 outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
4005 })";
4006 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4007 EXPECT_GL_NO_ERROR();
4008
4009 glUseProgram(program);
4010
4011 GLuint outputInitData[1] = {10};
4012 GLBuffer outputBuffer;
4013 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4014 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
4015 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
4016 EXPECT_GL_NO_ERROR();
4017
4018 GLuint imageData = 200u;
4019 GLTexture images[1][2][3];
4020 for (int i = 0; i < 1; i++)
4021 {
4022 for (int j = 0; j < 2; j++)
4023 {
4024 for (int k = 0; k < 3; k++)
4025 {
4026 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
4027 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4028 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4029 &imageData);
4030 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
4031 GL_R32UI);
4032 EXPECT_GL_NO_ERROR();
4033 }
4034 }
4035 }
4036
4037 glDispatchCompute(1, 1, 1);
4038 EXPECT_GL_NO_ERROR();
4039
4040 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4041
4042 // read back
4043 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4044 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
4045 memcpy(outputInitData, ptr, sizeof(outputInitData));
4046 EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
4047 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4048 }
4049
4050 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)4051 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
4052 {
4053 // http://anglebug.com/5072
4054 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4055
4056 // Fails on D3D due to mistranslation.
4057 ANGLE_SKIP_TEST_IF(IsD3D());
4058
4059 constexpr GLsizei kImage1Layers = 3;
4060 constexpr GLsizei kImage1Rows = 2;
4061 constexpr GLsizei kImage1Cols = 1;
4062 constexpr GLsizei kImage2Rows = 2;
4063 constexpr GLsizei kImage2Cols = 4;
4064
4065 constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
4066 constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
4067 constexpr GLsizei kImage3Units = 1;
4068
4069 constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
4070
4071 GLint maxTextures, maxComputeImageUniforms;
4072 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4073 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4074 ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
4075 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
4076
4077 constexpr char kComputeShader[] = R"(#version 310 es
4078 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4079 layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
4080 layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
4081 layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
4082 layout(binding = 0, std430) buffer Output {
4083 uint image_value;
4084 } outbuf;
4085
4086 void main(void)
4087 {
4088 outbuf.image_value = uint(0.0);
4089
4090 outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
4091 outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
4092 outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
4093 outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
4094 outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
4095 outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
4096
4097 outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
4098 outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
4099 outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
4100 outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
4101 outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
4102 outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
4103 outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
4104 outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
4105
4106 outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
4107 })";
4108 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4109 EXPECT_GL_NO_ERROR();
4110
4111 glUseProgram(program);
4112
4113 constexpr GLuint kOutputInitData = 10;
4114 GLBuffer outputBuffer;
4115 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4116 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
4117 GL_STATIC_DRAW);
4118 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4119 EXPECT_GL_NO_ERROR();
4120
4121 constexpr GLsizei kImage1Binding = 0;
4122 constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
4123 constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
4124
4125 constexpr GLuint kImage1Data = 13;
4126 GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
4127 for (int layer = 0; layer < kImage1Layers; layer++)
4128 {
4129 for (int row = 0; row < kImage1Rows; row++)
4130 {
4131 for (int col = 0; col < kImage1Cols; col++)
4132 {
4133 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
4134 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4135 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4136 &kImage1Data);
4137 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
4138 images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
4139 GL_R32UI);
4140 EXPECT_GL_NO_ERROR();
4141 }
4142 }
4143 }
4144
4145 constexpr GLuint kImage2Data = 17;
4146 GLTexture images2[kImage2Rows][kImage2Cols];
4147 for (int row = 0; row < kImage2Rows; row++)
4148 {
4149 for (int col = 0; col < kImage2Cols; col++)
4150 {
4151 glBindTexture(GL_TEXTURE_2D, images2[row][col]);
4152 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4153 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4154 &kImage2Data);
4155 glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
4156 GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4157 EXPECT_GL_NO_ERROR();
4158 }
4159 }
4160
4161 constexpr GLuint kImage3Data = 19;
4162 GLTexture image3;
4163 glBindTexture(GL_TEXTURE_2D, image3);
4164 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4165 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
4166 glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4167 EXPECT_GL_NO_ERROR();
4168
4169 glDispatchCompute(1, 1, 1);
4170 EXPECT_GL_NO_ERROR();
4171
4172 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4173
4174 // read back
4175 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4176 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4177 EXPECT_EQ(*ptr,
4178 kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
4179 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4180 }
4181
4182 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)4183 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
4184 {
4185 // Skip if GL_OES_shader_image_atomic is not enabled.
4186 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
4187
4188 // http://anglebug.com/5072
4189 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4190
4191 // Fails on D3D due to mistranslation.
4192 ANGLE_SKIP_TEST_IF(IsD3D());
4193
4194 // Fails on Android on GLES.
4195 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4196
4197 // http://anglebug.com/5353
4198 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
4199
4200 GLint maxComputeImageUniforms;
4201 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4202 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
4203
4204 constexpr char kComputeShader[] = R"(#version 310 es
4205 #extension GL_OES_shader_image_atomic : require
4206
4207 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4208 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
4209 layout(binding = 6, r32f) uniform highp image2D image2;
4210
4211 void testFunction(image2D imageOut[2][3])
4212 {
4213 // image1 is an array of 1x1 images.
4214 // image2 is a 1x4 image with the following data:
4215 //
4216 // (0, 0): 234.5
4217 // (0, 1): 4.0
4218 // (0, 2): 456.0
4219 // (0, 3): 987.0
4220
4221
4222 // Write to [0][0]
4223 imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
4224
4225 // Write to [0][1]
4226 imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
4227
4228 // Write to [0][2]
4229 imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
4230
4231 // Write to [1][0]
4232 imageStore(imageOut[1][0], ivec2(0,
4233 imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
4234 ), vec4(678.0));
4235
4236 // Write to [1][1]
4237 imageStore(imageOut[1][1], ivec2(0, 0),
4238 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
4239
4240 // Write to [1][2]
4241 imageStore(imageOut[1][2], ivec2(0, 0),
4242 imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
4243 }
4244
4245 void main(void)
4246 {
4247 testFunction(image1);
4248 })";
4249 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4250 EXPECT_GL_NO_ERROR();
4251
4252 glUseProgram(program);
4253
4254 constexpr GLsizei kImageRows = 2;
4255 constexpr GLsizei kImageCols = 3;
4256 constexpr GLfloat kImageData = 0;
4257 GLTexture images[kImageRows][kImageCols];
4258 for (size_t row = 0; row < kImageRows; row++)
4259 {
4260 for (size_t col = 0; col < kImageCols; col++)
4261 {
4262 glBindTexture(GL_TEXTURE_2D, images[row][col]);
4263 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
4264 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
4265 glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
4266 GL_READ_WRITE, GL_R32F);
4267 EXPECT_GL_NO_ERROR();
4268 }
4269 }
4270
4271 constexpr GLsizei kImage2Size = 4;
4272 constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
4273 234.5f,
4274 4.0f,
4275 456.0f,
4276 987.0f,
4277 };
4278 GLTexture image2;
4279 glBindTexture(GL_TEXTURE_2D, image2);
4280 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
4281 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
4282 glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4283 EXPECT_GL_NO_ERROR();
4284
4285 glDispatchCompute(1, 1, 1);
4286 EXPECT_GL_NO_ERROR();
4287
4288 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4289
4290 // Verify the previous dispatch with another dispatch
4291 constexpr char kVerifyShader[] = R"(#version 310 es
4292 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4293 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
4294 layout(binding = 6, r32f) uniform highp readonly image2D image2;
4295 layout(binding = 0, std430) buffer Output {
4296 float image2Data[4];
4297 float image1Data[6];
4298 } outbuf;
4299
4300 void main(void)
4301 {
4302 for (int i = 0; i < 4; ++i)
4303 {
4304 outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
4305 }
4306 outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
4307 outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
4308 outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
4309 outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
4310 outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
4311 outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
4312 })";
4313 ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
4314 EXPECT_GL_NO_ERROR();
4315
4316 glUseProgram(verifyProgram);
4317
4318 constexpr std::array<GLfloat, kImage2Size + kImageRows *kImageCols> kOutputInitData = {};
4319 GLBuffer outputBuffer;
4320 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4321 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4322 GL_STATIC_DRAW);
4323 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4324 EXPECT_GL_NO_ERROR();
4325
4326 glDispatchCompute(1, 1, 1);
4327 EXPECT_GL_NO_ERROR();
4328
4329 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4330
4331 // Verify
4332 const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
4333 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4334
4335 EXPECT_EQ(ptr[0], kImage2Data[0]);
4336 EXPECT_EQ(ptr[1], kImage2Data[1]);
4337 EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
4338 EXPECT_EQ(ptr[3], kImage2Data[3]);
4339
4340 EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
4341 EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
4342 EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
4343 EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
4344 EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
4345 EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
4346
4347 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4348 }
4349
4350 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)4351 TEST_P(GLSLTest_ES31, StructArraySampler)
4352 {
4353 constexpr char kFS[] =
4354 "#version 310 es\n"
4355 "precision mediump float;\n"
4356 "out vec4 my_FragColor;\n"
4357 "struct Data { mediump sampler2D data[2]; };\n"
4358 "uniform Data test;\n"
4359 "void main() {\n"
4360 " my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
4361 " texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
4362 "}\n";
4363
4364 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4365 glUseProgram(program.get());
4366 GLTexture textures[2];
4367 GLColor expected = MakeGLColor(32, 64, 96, 255);
4368 GLubyte data[6] = {}; // Two bytes of padding, so that texture can be initialized with 4 bytes
4369 memcpy(data, expected.data(), sizeof(expected));
4370 for (int i = 0; i < 2; i++)
4371 {
4372 glActiveTexture(GL_TEXTURE0 + i);
4373 glBindTexture(GL_TEXTURE_2D, textures[i]);
4374 // Each element provides two components.
4375 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
4376 std::stringstream uniformName;
4377 uniformName << "test.data[" << i << "]";
4378 // Then send it as a uniform
4379 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4380 // The uniform should be active.
4381 EXPECT_NE(uniformLocation, -1);
4382 glUniform1i(uniformLocation, i);
4383 }
4384 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4385 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
4386 }
4387
4388 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)4389 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
4390 {
4391 constexpr char kFS[] =
4392 "#version 310 es\n"
4393 "precision mediump float;\n"
4394 "out vec4 my_FragColor;\n"
4395 "struct Data { mediump isampler2D data[2][2]; };\n"
4396 "uniform Data test;\n"
4397 "void main() {\n"
4398 " bool passed = true;\n"
4399 "#define DO_CHECK(i,j) \\\n"
4400 " if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4401 " passed = false; \\\n"
4402 " }\n"
4403 " DO_CHECK(0, 0)\n"
4404 " DO_CHECK(0, 1)\n"
4405 " DO_CHECK(1, 0)\n"
4406 " DO_CHECK(1, 1)\n"
4407 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4408 "}\n";
4409
4410 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4411 glUseProgram(program.get());
4412 GLTexture textures[2][2];
4413 for (int i = 0; i < 2; i++)
4414 {
4415 for (int j = 0; j < 2; j++)
4416 {
4417 // First generate the texture
4418 int textureUnit = i * 2 + j;
4419 glActiveTexture(GL_TEXTURE0 + textureUnit);
4420 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4421 GLint texData[2] = {i + 1, j + 1};
4422 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4425 // Then send it as a uniform
4426 std::stringstream uniformName;
4427 uniformName << "test.data[" << i << "][" << j << "]";
4428 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4429 // All array indices should be used.
4430 EXPECT_NE(uniformLocation, -1);
4431 glUniform1i(uniformLocation, textureUnit);
4432 }
4433 }
4434 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4435 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4436 }
4437
4438 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)4439 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
4440 {
4441 GLint numTextures;
4442 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4443 ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
4444 constexpr char kFS[] =
4445 "#version 310 es\n"
4446 "precision mediump float;\n"
4447 "out vec4 my_FragColor;\n"
4448 "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
4449 "uniform Data test[2];\n"
4450 "void main() {\n"
4451 " bool passed = true;\n"
4452 "#define DO_CHECK_ikl(i,k,l) \\\n"
4453 " if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
4454 " passed = false; \\\n"
4455 " } \\\n"
4456 " if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
4457 " passed = false; \\\n"
4458 " }\n"
4459 "#define DO_CHECK_ik(i,k) \\\n"
4460 " DO_CHECK_ikl(i, k, 0) \\\n"
4461 " DO_CHECK_ikl(i, k, 1)\n"
4462 "#define DO_CHECK_i(i) \\\n"
4463 " DO_CHECK_ik(i, 0) \\\n"
4464 " DO_CHECK_ik(i, 1)\n"
4465 " DO_CHECK_i(0)\n"
4466 " DO_CHECK_i(1)\n"
4467 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4468 "}\n";
4469
4470 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4471 glUseProgram(program.get());
4472 GLTexture textures[2][2][2][2];
4473 for (int i = 0; i < 2; i++)
4474 {
4475 for (int j = 0; j < 2; j++)
4476 {
4477 for (int k = 0; k < 2; k++)
4478 {
4479 for (int l = 0; l < 2; l++)
4480 {
4481 // First generate the texture
4482 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
4483 glActiveTexture(GL_TEXTURE0 + textureUnit);
4484 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
4485 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
4486 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4487 &texData[0]);
4488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4490 // Then send it as a uniform
4491 std::stringstream uniformName;
4492 uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
4493 GLint uniformLocation =
4494 glGetUniformLocation(program.get(), uniformName.str().c_str());
4495 // All array indices should be used.
4496 EXPECT_NE(uniformLocation, -1);
4497 glUniform1i(uniformLocation, textureUnit);
4498 }
4499 }
4500 }
4501 }
4502 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4503 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4504 }
4505
4506 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)4507 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
4508 {
4509 GLint numTextures;
4510 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4511 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
4512 constexpr char kFS[] =
4513 "#version 310 es\n"
4514 "precision mediump float;\n"
4515 "out vec4 my_FragColor;\n"
4516 "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
4517 "uniform Data test[2][3];\n"
4518 "const vec2 ZERO = vec2(0.0, 0.0);\n"
4519 "void main() {\n"
4520 " bool passed = true;\n"
4521 "#define DO_CHECK_INNER0(i,j,l) \\\n"
4522 " if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
4523 " passed = false; \\\n"
4524 " }\n"
4525 "#define DO_CHECK_INNER1(i,j,l) \\\n"
4526 " if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
4527 " passed = false; \\\n"
4528 " }\n"
4529 "#define DO_CHECK(i,j) \\\n"
4530 " DO_CHECK_INNER0(i, j, 0) \\\n"
4531 " DO_CHECK_INNER0(i, j, 1) \\\n"
4532 " DO_CHECK_INNER1(i, j, 0) \\\n"
4533 " DO_CHECK_INNER1(i, j, 1) \\\n"
4534 " DO_CHECK_INNER1(i, j, 2)\n"
4535 " DO_CHECK(0, 0)\n"
4536 " DO_CHECK(0, 1)\n"
4537 " DO_CHECK(0, 2)\n"
4538 " DO_CHECK(1, 0)\n"
4539 " DO_CHECK(1, 1)\n"
4540 " DO_CHECK(1, 2)\n"
4541 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4542 "}\n";
4543
4544 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4545 glUseProgram(program.get());
4546 struct Data
4547 {
4548 GLTexture data1[2];
4549 GLTexture data2[3];
4550 };
4551 Data textures[2][3];
4552 for (int i = 0; i < 2; i++)
4553 {
4554 for (int j = 0; j < 3; j++)
4555 {
4556 GLTexture *arrays[] = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
4557 size_t arrayLengths[] = {2, 3};
4558 size_t arrayOffsets[] = {0, 2};
4559 size_t totalArrayLength = 5;
4560 for (int k = 0; k < 2; k++)
4561 {
4562 GLTexture *array = arrays[k];
4563 size_t arrayLength = arrayLengths[k];
4564 size_t arrayOffset = arrayOffsets[k];
4565 for (int l = 0; l < static_cast<int>(arrayLength); l++)
4566 {
4567 // First generate the texture
4568 int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
4569 glActiveTexture(GL_TEXTURE0 + textureUnit);
4570 glBindTexture(GL_TEXTURE_2D, array[l]);
4571 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
4572 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4573 &texData[0]);
4574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4576 // Then send it as a uniform
4577 std::stringstream uniformName;
4578 uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
4579 GLint uniformLocation =
4580 glGetUniformLocation(program.get(), uniformName.str().c_str());
4581 // All array indices should be used.
4582 EXPECT_NE(uniformLocation, -1);
4583 glUniform1i(uniformLocation, textureUnit);
4584 }
4585 }
4586 }
4587 }
4588 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4589 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4590 }
4591
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)4592 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
4593 {
4594 GLint numTextures;
4595 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4596 ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
4597 constexpr char kFS[] =
4598 "#version 310 es\n"
4599 "precision mediump float;\n"
4600 "out vec4 my_FragColor;\n"
4601 "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
4602 "uniform Data test[3];\n"
4603 "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
4604 "void main() {\n"
4605 " bool passed = true;\n"
4606 "#define DO_CHECK_ik(i,k) \\\n"
4607 " if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
4608 " passed = false; \\\n"
4609 " } \\\n"
4610 " if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
4611 " passed = false; \\\n"
4612 " }\n"
4613 "#define DO_CHECK_i(i) \\\n"
4614 " DO_CHECK_ik(i, 0) \\\n"
4615 " DO_CHECK_ik(i, 1)\n"
4616 " DO_CHECK_i(0)\n"
4617 " DO_CHECK_i(1)\n"
4618 " DO_CHECK_i(2)\n"
4619 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4620 "}\n";
4621
4622 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4623 glUseProgram(program.get());
4624 GLTexture textures[3][2][2];
4625 for (int i = 0; i < 3; i++)
4626 {
4627 for (int j = 0; j < 2; j++)
4628 {
4629 for (int k = 0; k < 2; k++)
4630 {
4631 // First generate the texture
4632 int textureUnit = k + 2 * (j + 2 * i);
4633 glActiveTexture(GL_TEXTURE0 + textureUnit);
4634 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
4635 GLint texData[4] = {i + 1, j + 1, k + 1, 1};
4636 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
4637 static_cast<GLubyte>((j + 1) * 64 - 1),
4638 static_cast<GLubyte>((k + 1) * 64 - 1), 64};
4639 if (j == 0)
4640 {
4641 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4642 &texData[0]);
4643 }
4644 else
4645 {
4646 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4647 &texDataFloat[0]);
4648 }
4649 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4650 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4651 // Then send it as a uniform
4652 std::stringstream uniformName;
4653 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
4654 GLint uniformLocation =
4655 glGetUniformLocation(program.get(), uniformName.str().c_str());
4656 // All array indices should be used.
4657 EXPECT_NE(uniformLocation, -1);
4658 glUniform1i(uniformLocation, textureUnit);
4659 }
4660 }
4661 }
4662 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4663 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4664 }
4665
4666 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)4667 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
4668 {
4669 // anglebug.com/3832 - no sampler array params on Android
4670 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4671
4672 constexpr char kFS[] =
4673 "#version 310 es\n"
4674 "precision mediump float;\n"
4675 "out vec4 my_FragColor;\n"
4676 "uniform mediump isampler2D test[2][3];\n"
4677 "const vec2 ZERO = vec2(0.0, 0.0);\n"
4678 "\n"
4679 "bool check(isampler2D data[2][3]);\n"
4680 "bool check(isampler2D data[2][3]) {\n"
4681 "#define DO_CHECK(i,j) \\\n"
4682 " if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
4683 " return false; \\\n"
4684 " }\n"
4685 " DO_CHECK(0, 0)\n"
4686 " DO_CHECK(0, 1)\n"
4687 " DO_CHECK(0, 2)\n"
4688 " DO_CHECK(1, 0)\n"
4689 " DO_CHECK(1, 1)\n"
4690 " DO_CHECK(1, 2)\n"
4691 " return true;\n"
4692 "}\n"
4693 "void main() {\n"
4694 " bool passed = check(test);\n"
4695 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4696 "}\n";
4697
4698 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4699 glUseProgram(program.get());
4700 GLTexture textures[2][3];
4701 for (int i = 0; i < 2; i++)
4702 {
4703 for (int j = 0; j < 3; j++)
4704 {
4705 // First generate the texture
4706 int textureUnit = i * 3 + j;
4707 glActiveTexture(GL_TEXTURE0 + textureUnit);
4708 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4709 GLint texData[2] = {i + 1, j + 1};
4710 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4712 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4713 // Then send it as a uniform
4714 std::stringstream uniformName;
4715 uniformName << "test[" << i << "][" << j << "]";
4716 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4717 // All array indices should be used.
4718 EXPECT_NE(uniformLocation, -1);
4719 glUniform1i(uniformLocation, textureUnit);
4720 }
4721 }
4722 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4723 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4724 }
4725
4726 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)4727 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
4728 {
4729 // anglebug.com/3832 - no sampler array params on Android
4730 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4731
4732 constexpr char kFS[] =
4733 "#version 310 es\n"
4734 "precision mediump float;\n"
4735 "out vec4 my_FragColor;\n"
4736 "struct Data { mediump isampler2D data[2][3]; };\n"
4737 "uniform Data test;\n"
4738 "const vec2 ZERO = vec2(0.0, 0.0);\n"
4739 "\n"
4740 "bool check(Data data) {\n"
4741 "#define DO_CHECK(i,j) \\\n"
4742 " if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
4743 " return false; \\\n"
4744 " }\n"
4745 " DO_CHECK(0, 0)\n"
4746 " DO_CHECK(0, 1)\n"
4747 " DO_CHECK(0, 2)\n"
4748 " DO_CHECK(1, 0)\n"
4749 " DO_CHECK(1, 1)\n"
4750 " DO_CHECK(1, 2)\n"
4751 " return true;\n"
4752 "}\n"
4753 "void main() {\n"
4754 " bool passed = check(test);\n"
4755 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4756 "}\n";
4757
4758 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4759 glUseProgram(program.get());
4760 GLTexture textures[2][3];
4761 for (int i = 0; i < 2; i++)
4762 {
4763 for (int j = 0; j < 3; j++)
4764 {
4765 // First generate the texture
4766 int textureUnit = i * 3 + j;
4767 glActiveTexture(GL_TEXTURE0 + textureUnit);
4768 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4769 GLint texData[2] = {i + 1, j + 1};
4770 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4771 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4773 // Then send it as a uniform
4774 std::stringstream uniformName;
4775 uniformName << "test.data[" << i << "][" << j << "]";
4776 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4777 // All array indices should be used.
4778 EXPECT_NE(uniformLocation, -1);
4779 glUniform1i(uniformLocation, textureUnit);
4780 }
4781 }
4782 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4783 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4784 }
4785
4786 // Test that arrays of arrays of structs with arrays of arrays of samplers
4787 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)4788 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
4789 {
4790 // anglebug.com/3832 - no sampler array params on Android
4791 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4792
4793 GLint numTextures;
4794 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4795 ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
4796 constexpr char kFS[] =
4797 "#version 310 es\n"
4798 "precision mediump float;\n"
4799 "out vec4 my_FragColor;\n"
4800 "struct Data { mediump isampler2D data[2][2]; };\n"
4801 "uniform Data test[3][2];\n"
4802 "const vec2 ZERO = vec2(0.0, 0.0);\n"
4803 "\n"
4804 "bool check(Data data[3][2]) {\n"
4805 "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
4806 " if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
4807 " return false; \\\n"
4808 " }\n"
4809 "#define DO_CHECK_ij(i,j) \\\n"
4810 " DO_CHECK_ijkl(i, j, 0, 0) \\\n"
4811 " DO_CHECK_ijkl(i, j, 0, 1) \\\n"
4812 " DO_CHECK_ijkl(i, j, 1, 0) \\\n"
4813 " DO_CHECK_ijkl(i, j, 1, 1)\n"
4814 " DO_CHECK_ij(0, 0)\n"
4815 " DO_CHECK_ij(1, 0)\n"
4816 " DO_CHECK_ij(2, 0)\n"
4817 " DO_CHECK_ij(0, 1)\n"
4818 " DO_CHECK_ij(1, 1)\n"
4819 " DO_CHECK_ij(2, 1)\n"
4820 " return true;\n"
4821 "}\n"
4822 "void main() {\n"
4823 " bool passed = check(test);\n"
4824 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4825 "}\n";
4826
4827 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4828 glUseProgram(program.get());
4829 GLTexture textures[3][2][2][2];
4830 for (int i = 0; i < 3; i++)
4831 {
4832 for (int j = 0; j < 2; j++)
4833 {
4834 for (int k = 0; k < 2; k++)
4835 {
4836 for (int l = 0; l < 2; l++)
4837 {
4838 // First generate the texture
4839 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
4840 glActiveTexture(GL_TEXTURE0 + textureUnit);
4841 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
4842 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
4843 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
4844 &texData[0]);
4845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4847 // Then send it as a uniform
4848 std::stringstream uniformName;
4849 uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
4850 GLint uniformLocation =
4851 glGetUniformLocation(program.get(), uniformName.str().c_str());
4852 // All array indices should be used.
4853 EXPECT_NE(uniformLocation, -1);
4854 glUniform1i(uniformLocation, textureUnit);
4855 }
4856 }
4857 }
4858 }
4859 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4860 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4861 }
4862
4863 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)4864 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
4865 {
4866 GLint numTextures;
4867 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4868 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
4869
4870 // anglebug.com/3832 - no sampler array params on Android
4871 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4872
4873 // http://anglebug.com/5546
4874 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
4875
4876 constexpr char kFS[] =
4877 "#version 310 es\n"
4878 "precision mediump float;\n"
4879 "out vec4 my_FragColor;\n"
4880 "uniform mediump isampler2D test[2][3][4];\n"
4881 "uniform mediump isampler2D test2[4];\n"
4882 "const vec2 ZERO = vec2(0.0, 0.0);\n"
4883 "\n"
4884 "bool check1D(isampler2D arr[4], int x, int y) {\n"
4885 " if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
4886 " if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
4887 " if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
4888 " if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
4889 " return true;\n"
4890 "}\n"
4891 "bool check2D(isampler2D arr[3][4], int x) {\n"
4892 " if (!check1D(arr[0], x, 0)) return false;\n"
4893 " if (!check1D(arr[1], x, 1)) return false;\n"
4894 " if (!check1D(arr[2], x, 2)) return false;\n"
4895 " return true;\n"
4896 "}\n"
4897 "bool check3D(isampler2D arr[2][3][4]) {\n"
4898 " if (!check2D(arr[0], 0)) return false;\n"
4899 " if (!check2D(arr[1], 1)) return false;\n"
4900 " return true;\n"
4901 "}\n"
4902 "void main() {\n"
4903 " bool passed = check3D(test) && check1D(test2, 7, 8);\n"
4904 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4905 "}\n";
4906
4907 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4908 glUseProgram(program.get());
4909 GLTexture textures1[2][3][4];
4910 GLTexture textures2[4];
4911 for (int i = 0; i < 2; i++)
4912 {
4913 for (int j = 0; j < 3; j++)
4914 {
4915 for (int k = 0; k < 4; k++)
4916 {
4917 // First generate the texture
4918 int textureUnit = k + 4 * (j + 3 * i);
4919 glActiveTexture(GL_TEXTURE0 + textureUnit);
4920 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
4921 GLint texData[3] = {i + 1, j + 1, k + 1};
4922 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
4923 &texData[0]);
4924 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4925 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4926 // Then send it as a uniform
4927 std::stringstream uniformName;
4928 uniformName << "test[" << i << "][" << j << "][" << k << "]";
4929 GLint uniformLocation =
4930 glGetUniformLocation(program.get(), uniformName.str().c_str());
4931 // All array indices should be used.
4932 EXPECT_NE(uniformLocation, -1);
4933 glUniform1i(uniformLocation, textureUnit);
4934 }
4935 }
4936 }
4937 for (int k = 0; k < 4; k++)
4938 {
4939 // First generate the texture
4940 int textureUnit = 2 * 3 * 4 + k;
4941 glActiveTexture(GL_TEXTURE0 + textureUnit);
4942 glBindTexture(GL_TEXTURE_2D, textures2[k]);
4943 GLint texData[3] = {7 + 1, 8 + 1, k + 1};
4944 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
4945 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4946 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4947 // Then send it as a uniform
4948 std::stringstream uniformName;
4949 uniformName << "test2[" << k << "]";
4950 GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4951 // All array indices should be used.
4952 EXPECT_NE(uniformLocation, -1);
4953 glUniform1i(uniformLocation, textureUnit);
4954 }
4955 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4956 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4957 }
4958
4959 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)4960 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
4961 {
4962 ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/3604 - rewriter can create name collisions
4963 GLint numTextures;
4964 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
4965 ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
4966 // anglebug.com/3832 - no sampler array params on Android
4967 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4968 constexpr char kFS[] =
4969 "#version 310 es\n"
4970 "precision mediump sampler2D;\n"
4971 "precision mediump float;\n"
4972 "uniform sampler2D test_field1_field2[2][2];\n"
4973 "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
4974 "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
4975 "vec4 func1(sampler2D param_field1_field2[2][2],\n"
4976 " int param_field1_field2_offset,\n"
4977 " S1 param_field1,\n"
4978 " S2 param) {\n"
4979 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
4980 "}\n"
4981 "out vec4 my_FragColor;\n"
4982 "void main() {\n"
4983 " my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
4984 " my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
4985 " vec2 uv = vec2(0.0);\n"
4986 " my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
4987 " texture(test_field1.field2[0][0], uv) +\n"
4988 " texture(test.field1_field2[0][0], uv);\n"
4989 "}\n";
4990 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4991 glActiveTexture(GL_TEXTURE0);
4992 GLTexture tex;
4993 glBindTexture(GL_TEXTURE_2D, tex);
4994 GLint zero = 0;
4995 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
4996 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4997 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4998 }
4999
5000 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)5001 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
5002 {
5003 constexpr char kFS[] =
5004 "#version 310 es\n"
5005 "precision mediump sampler2D;\n"
5006 "precision mediump float;\n"
5007 "uniform sampler2D sampler_array[2][2];\n"
5008 "uniform int array[3][2];\n"
5009 "vec4 func1(int param[2],\n"
5010 " int param2[3]) {\n"
5011 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
5012 "}\n"
5013 "out vec4 my_FragColor;\n"
5014 "void main() {\n"
5015 " my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
5016 " my_FragColor += func1(array[1], int[](1, 2, 3));\n"
5017 "}\n";
5018 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5019 glActiveTexture(GL_TEXTURE0);
5020 GLTexture tex;
5021 glBindTexture(GL_TEXTURE_2D, tex);
5022 GLint zero = 0;
5023 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
5024 drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5025 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5026 }
5027
5028 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
5029 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)5030 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
5031 {
5032 // This seems to be bugged on some version of Android. Might not affect the newest versions.
5033 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
5034 // Test skipped on Android because of bug with Nexus 5X.
5035 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5036
5037 constexpr char kVS[] =
5038 "#version 300 es\n"
5039 "out vec2 texCoord;\n"
5040 "in vec2 position;\n"
5041 "void main()\n"
5042 "{\n"
5043 " gl_Position = vec4(position, 0, 1);\n"
5044 " texCoord = position * 0.5 + vec2(0.5);\n"
5045 "}\n";
5046
5047 constexpr char kSimpleFS[] =
5048 "#version 300 es\n"
5049 "in mediump vec2 texCoord;\n"
5050 "out mediump vec4 fragColor;\n"
5051 "void main()\n"
5052 "{\n"
5053 " fragColor = vec4(texCoord, 0, 1);\n"
5054 "}\n";
5055
5056 constexpr char kNestedFS[] =
5057 "#version 300 es\n"
5058 "uniform mediump sampler2D samplerA;\n"
5059 "uniform mediump sampler2D samplerB;\n"
5060 "in mediump vec2 texCoord;\n"
5061 "out mediump vec4 fragColor;\n"
5062 "void main ()\n"
5063 "{\n"
5064 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
5065 "}\n";
5066
5067 ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
5068 ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
5069
5070 // Initialize a first texture with default texCoord data.
5071 GLTexture texA;
5072 glActiveTexture(GL_TEXTURE0);
5073 glBindTexture(GL_TEXTURE_2D, texA);
5074 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
5075 GL_UNSIGNED_BYTE, nullptr);
5076 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5077 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5078
5079 GLFramebuffer fbo;
5080 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5081 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
5082
5083 drawQuad(initProg, "position", 0.5f);
5084 ASSERT_GL_NO_ERROR();
5085
5086 // Initialize a second texture with a simple color pattern.
5087 GLTexture texB;
5088 glActiveTexture(GL_TEXTURE1);
5089 glBindTexture(GL_TEXTURE_2D, texB);
5090
5091 std::array<GLColor, 4> simpleColors = {
5092 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5093 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5094 simpleColors.data());
5095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5096 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5097
5098 // Draw with the nested program, using the first texture to index the second.
5099 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5100 glUseProgram(nestedProg);
5101 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
5102 ASSERT_NE(-1, samplerALoc);
5103 glUniform1i(samplerALoc, 0);
5104 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
5105 ASSERT_NE(-1, samplerBLoc);
5106 glUniform1i(samplerBLoc, 1);
5107
5108 drawQuad(nestedProg, "position", 0.5f);
5109 ASSERT_GL_NO_ERROR();
5110
5111 // Compute four texel centers.
5112 Vector2 windowSize(getWindowWidth(), getWindowHeight());
5113 Vector2 quarterWindowSize = windowSize / 4;
5114 Vector2 ul = quarterWindowSize;
5115 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
5116 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
5117 Vector2 lr = windowSize - quarterWindowSize;
5118
5119 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
5120 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
5121 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
5122 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
5123 }
5124
5125 // Tests that using a constant declaration as the only statement in a for loop without curly braces
5126 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)5127 TEST_P(GLSLTest, ConstantStatementInForLoop)
5128 {
5129 constexpr char kVS[] =
5130 "void main()\n"
5131 "{\n"
5132 " for (int i = 0; i < 10; ++i)\n"
5133 " const int b = 0;\n"
5134 "}\n";
5135
5136 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5137 EXPECT_NE(0u, shader);
5138 glDeleteShader(shader);
5139 }
5140
5141 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
5142 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)5143 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
5144 {
5145 constexpr char kVS[] =
5146 "void main()\n"
5147 "{\n"
5148 " for (const int i = 0; i < 0;) {}\n"
5149 "}\n";
5150
5151 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5152 EXPECT_NE(0u, shader);
5153 glDeleteShader(shader);
5154 }
5155
5156 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)5157 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
5158 {
5159 // Test skipped on Android GLES because local variable initialization is disabled.
5160 // http://anglebug.com/2046
5161 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5162
5163 constexpr char kFS[] =
5164 "#version 300 es\n"
5165 "precision mediump float;\n"
5166 "out vec4 my_FragColor;\n"
5167 "int result = 0;\n"
5168 "void main()\n"
5169 "{\n"
5170 " int u;\n"
5171 " result += u;\n"
5172 " int k = 0;\n"
5173 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
5174 " {\n"
5175 " result += j;\n"
5176 " }\n"
5177 " if (result == 2)\n"
5178 " {\n"
5179 " my_FragColor = vec4(0, 1, 0, 1);\n"
5180 " }\n"
5181 " else\n"
5182 " {\n"
5183 " my_FragColor = vec4(1, 0, 0, 1);\n"
5184 " }\n"
5185 "}\n";
5186
5187 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5188
5189 // [WebGL 1.0]
5190 // DrawArrays or drawElements will generate an INVALID_OPERATION error
5191 // if a vertex attribute is enabled as an array via enableVertexAttribArray
5192 // but no buffer is bound to that attribute.
5193 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5194 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5195 }
5196
5197 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
5198 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)5199 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
5200 {
5201 // Test skipped on Android GLES because local variable initialization is disabled.
5202 // http://anglebug.com/2046
5203 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5204
5205 constexpr char kFS[] =
5206 "precision mediump float;\n"
5207 "struct T\n"
5208 "{\n"
5209 " int a[2];\n"
5210 "};\n"
5211 "struct S\n"
5212 "{\n"
5213 " T t[2];\n"
5214 "};\n"
5215 "void main()\n"
5216 "{\n"
5217 " S s;\n"
5218 " S s2;\n"
5219 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
5220 " {\n"
5221 " gl_FragColor = vec4(0, 1, 0, 1);\n"
5222 " }\n"
5223 " else\n"
5224 " {\n"
5225 " gl_FragColor = vec4(1, 0, 0, 1);\n"
5226 " }\n"
5227 "}\n";
5228
5229 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5230 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5231 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5232 }
5233
5234 // Verify that two shaders with the same uniform name and members but different structure names will
5235 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)5236 TEST_P(GLSLTest, StructureNameMatchingTest)
5237 {
5238 const char *vsSource =
5239 "// Structures must have the same name, sequence of type names, and\n"
5240 "// type definitions, and field names to be considered the same type.\n"
5241 "// GLSL 1.017 4.2.4\n"
5242 "precision mediump float;\n"
5243 "struct info {\n"
5244 " vec4 pos;\n"
5245 " vec4 color;\n"
5246 "};\n"
5247 "\n"
5248 "uniform info uni;\n"
5249 "void main()\n"
5250 "{\n"
5251 " gl_Position = uni.pos;\n"
5252 "}\n";
5253
5254 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
5255 ASSERT_NE(0u, vs);
5256 glDeleteShader(vs);
5257
5258 const char *fsSource =
5259 "// Structures must have the same name, sequence of type names, and\n"
5260 "// type definitions, and field names to be considered the same type.\n"
5261 "// GLSL 1.017 4.2.4\n"
5262 "precision mediump float;\n"
5263 "struct info1 {\n"
5264 " vec4 pos;\n"
5265 " vec4 color;\n"
5266 "};\n"
5267 "\n"
5268 "uniform info1 uni;\n"
5269 "void main()\n"
5270 "{\n"
5271 " gl_FragColor = uni.color;\n"
5272 "}\n";
5273
5274 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
5275 ASSERT_NE(0u, fs);
5276 glDeleteShader(fs);
5277
5278 GLuint program = CompileProgram(vsSource, fsSource);
5279 EXPECT_EQ(0u, program);
5280 }
5281
5282 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)5283 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
5284 {
5285 // Test skipped on Android GLES because local variable initialization is disabled.
5286 // http://anglebug.com/2046
5287 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5288
5289 constexpr char kFS[] =
5290 "#version 300 es\n"
5291 "precision highp float;\n"
5292 "out vec4 my_FragColor;\n"
5293 "void main()\n"
5294 "{\n"
5295 " my_FragColor = vec4(1, 0, 0, 1);\n"
5296 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
5297 " my_FragColor = vec4(0, 1, 0, 1);\n"
5298 " }\n"
5299 "}\n";
5300
5301 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5302 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5303 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5304 }
5305
5306 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)5307 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
5308 {
5309 // http://anglebug.com/2862
5310 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
5311
5312 constexpr char kFS[] =
5313 "precision mediump float;\n"
5314 "int result;\n"
5315 "int i[2], j = i[0] + 1;\n"
5316 "void main()\n"
5317 "{\n"
5318 " result += j;\n"
5319 " if (result == 1)\n"
5320 " {\n"
5321 " gl_FragColor = vec4(0, 1, 0, 1);\n"
5322 " }\n"
5323 " else\n"
5324 " {\n"
5325 " gl_FragColor = vec4(1, 0, 0, 1);\n"
5326 " }\n"
5327 "}\n";
5328
5329 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5330 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5331 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5332 }
5333
5334 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)5335 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
5336 {
5337 constexpr char kFS[] =
5338 "precision mediump float;\n"
5339 "struct { float q; } b;\n"
5340 "void main()\n"
5341 "{\n"
5342 " gl_FragColor = vec4(1, 0, 0, 1);\n"
5343 " if (b.q == 0.0)\n"
5344 " {\n"
5345 " gl_FragColor = vec4(0, 1, 0, 1);\n"
5346 " }\n"
5347 "}\n";
5348
5349 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5350 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5351 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5352 }
5353
5354 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)5355 TEST_P(GLSLTest, EmbeddedStructUniform)
5356 {
5357 const char kFragmentShader[] = R"(precision mediump float;
5358 uniform struct { float q; } b;
5359 void main()
5360 {
5361 gl_FragColor = vec4(1, 0, 0, 1);
5362 if (b.q == 0.5)
5363 {
5364 gl_FragColor = vec4(0, 1, 0, 1);
5365 }
5366 })";
5367
5368 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5369 glUseProgram(program);
5370 GLint uniLoc = glGetUniformLocation(program, "b.q");
5371 ASSERT_NE(-1, uniLoc);
5372 glUniform1f(uniLoc, 0.5f);
5373
5374 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5375 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5376 }
5377
5378 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)5379 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
5380 {
5381 const char kVertexShader[] = R"(attribute vec2 position;
5382 varying vec2 texCoord;
5383 void main()
5384 {
5385 gl_Position = vec4(position, 0, 1);
5386 texCoord = position * 0.5 + vec2(0.5);
5387 })";
5388
5389 const char kFragmentShader[] = R"(precision mediump float;
5390 struct S { sampler2D samp; bool b; };
5391 uniform S uni;
5392 varying vec2 texCoord;
5393 void main()
5394 {
5395 if (uni.b)
5396 {
5397 gl_FragColor = texture2D(uni.samp, texCoord);
5398 }
5399 else
5400 {
5401 gl_FragColor = vec4(1, 0, 0, 1);
5402 }
5403 })";
5404
5405 ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
5406 glUseProgram(program);
5407
5408 GLint bLoc = glGetUniformLocation(program, "uni.b");
5409 ASSERT_NE(-1, bLoc);
5410 GLint sampLoc = glGetUniformLocation(program, "uni.samp");
5411 ASSERT_NE(-1, sampLoc);
5412
5413 glUniform1i(bLoc, 1);
5414
5415 std::array<GLColor, 4> kGreenPixels = {
5416 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
5417
5418 GLTexture tex;
5419 glBindTexture(GL_TEXTURE_2D, tex);
5420 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5421 kGreenPixels.data());
5422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5424 ASSERT_GL_NO_ERROR();
5425
5426 drawQuad(program, "position", 0.5f);
5427 ASSERT_GL_NO_ERROR();
5428
5429 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5430 }
5431
5432 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)5433 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
5434 {
5435 const char kFragmentShader[] = R"(precision mediump float;
5436 uniform struct { float q; } b, c;
5437 void main()
5438 {
5439 gl_FragColor = vec4(1, 0, 0, 1);
5440 if (b.q == 0.5 && c.q == 1.0)
5441 {
5442 gl_FragColor = vec4(0, 1, 0, 1);
5443 }
5444 })";
5445
5446 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
5447 glUseProgram(program);
5448
5449 GLint uniLocB = glGetUniformLocation(program, "b.q");
5450 ASSERT_NE(-1, uniLocB);
5451 glUniform1f(uniLocB, 0.5f);
5452
5453 GLint uniLocC = glGetUniformLocation(program, "c.q");
5454 ASSERT_NE(-1, uniLocC);
5455 glUniform1f(uniLocC, 1.0f);
5456
5457 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5458 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5459 }
5460
5461 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)5462 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
5463 {
5464 constexpr char kFS[] =
5465 "#version 300 es\n"
5466 "precision highp float;\n"
5467 "out vec4 my_FragColor;\n"
5468 "void main()\n"
5469 "{\n"
5470 " float i = 0.0;\n"
5471 " while (bool foo = (i < 1.5))\n"
5472 " {\n"
5473 " if (!foo)\n"
5474 " {\n"
5475 " ++i;\n"
5476 " }\n"
5477 " if (i > 3.5)\n"
5478 " {\n"
5479 " break;\n"
5480 " }\n"
5481 " ++i;\n"
5482 " }\n"
5483 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
5484 "}\n";
5485
5486 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5487 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
5488 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5489 }
5490
5491 // Test that a variable hides a user-defined function with the same name after its initializer.
5492 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
5493 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)5494 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
5495 {
5496 constexpr char kFS[] =
5497 "precision mediump float;\n"
5498 "uniform vec4 u;\n"
5499 "vec4 foo()\n"
5500 "{\n"
5501 " return u;\n"
5502 "}\n"
5503 "void main()\n"
5504 "{\n"
5505 " vec4 foo = foo();\n"
5506 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
5507 "}\n";
5508
5509 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5510 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
5511 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5512 }
5513
5514 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)5515 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
5516 {
5517 constexpr char kFS[] =
5518 "precision mediump float;\n"
5519 "uniform float u_zero;\n"
5520 "struct S { float foo; };\n"
5521 "struct S2 { float foo; };\n"
5522 "float get(S s) { return s.foo + u_zero; }\n"
5523 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
5524 "void main()\n"
5525 "{\n"
5526 " S s;\n"
5527 " s.foo = 0.5;\n"
5528 " S2 s2;\n"
5529 " s2.foo = 0.25;\n"
5530 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
5531 "}\n";
5532
5533 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5534 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
5535 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5536 }
5537
5538 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
5539 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)5540 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
5541 {
5542 // http://anglebug.com/4820
5543 ANGLE_SKIP_TEST_IF((IsOSX() && IsOpenGL()) || (IsIOS() && IsOpenGLES()));
5544
5545 constexpr char kVS[] =
5546 "attribute vec4 inputAttribute;\n"
5547 "varying vec4 varColor;\n"
5548 "void main()\n"
5549 "{\n"
5550 " gl_Position = inputAttribute;\n"
5551 "}\n";
5552
5553 constexpr char kFS[] =
5554 "precision mediump float;\n"
5555 "varying vec4 varColor;\n"
5556 "void main()\n"
5557 "{\n"
5558 " gl_FragColor = varColor;\n"
5559 "}\n";
5560
5561 ANGLE_GL_PROGRAM(program, kVS, kFS);
5562 drawQuad(program.get(), "inputAttribute", 0.5f);
5563 ASSERT_GL_NO_ERROR();
5564 }
5565
5566 // Test that a varying struct that's not statically used in the fragment shader works.
5567 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)5568 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
5569 {
5570 constexpr char kVS[] =
5571 "#version 300 es\n"
5572 "struct S {\n"
5573 " vec4 field;\n"
5574 "};\n"
5575 "out S varStruct;\n"
5576 "void main()\n"
5577 "{\n"
5578 " gl_Position = vec4(1.0);\n"
5579 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
5580 "}\n";
5581
5582 constexpr char kFS[] =
5583 "#version 300 es\n"
5584 "precision mediump float;\n"
5585 "struct S {\n"
5586 " vec4 field;\n"
5587 "};\n"
5588 "in S varStruct;\n"
5589 "out vec4 col;\n"
5590 "void main()\n"
5591 "{\n"
5592 " col = vec4(1.0);\n"
5593 "}\n";
5594
5595 ANGLE_GL_PROGRAM(program, kVS, kFS);
5596 }
5597
5598 // Test that a shader IO block varying that's not declared in the fragment shader links
5599 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)5600 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
5601 {
5602 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
5603
5604 constexpr char kVS[] =
5605 R"(#version 310 es
5606 #extension GL_EXT_shader_io_blocks : require
5607
5608 precision highp float;
5609 in vec4 inputAttribute;
5610 out Block_inout { vec4 value; } user_out;
5611
5612 void main()
5613 {
5614 gl_Position = inputAttribute;
5615 user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
5616 })";
5617
5618 constexpr char kFS[] =
5619 R"(#version 310 es
5620 #extension GL_EXT_shader_io_blocks : require
5621
5622 precision highp float;
5623 layout(location = 0) out mediump vec4 color;
5624 void main()
5625 {
5626 color = vec4(1, 0, 0, 1);
5627 })";
5628
5629 ANGLE_GL_PROGRAM(program, kVS, kFS);
5630 drawQuad(program.get(), "inputAttribute", 0.5f);
5631 ASSERT_GL_NO_ERROR();
5632
5633 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5634 }
5635
5636 // Test that a shader IO block varying that's not declared in the vertex shader links
5637 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)5638 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
5639 {
5640 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
5641
5642 constexpr char kVS[] =
5643 R"(#version 310 es
5644 #extension GL_EXT_shader_io_blocks : require
5645
5646 precision highp float;
5647 in vec4 inputAttribute;
5648
5649 void main()
5650 {
5651 gl_Position = inputAttribute;
5652 })";
5653
5654 constexpr char kFS[] =
5655 R"(#version 310 es
5656 #extension GL_EXT_shader_io_blocks : require
5657
5658 precision highp float;
5659 in Block_inout { vec4 value; } user_in;
5660 layout(location = 0) out mediump vec4 color;
5661
5662 void main()
5663 {
5664 color = vec4(1, 0, 0, 1);
5665 })";
5666
5667 ANGLE_GL_PROGRAM(program, kVS, kFS);
5668 drawQuad(program.get(), "inputAttribute", 0.5f);
5669 ASSERT_GL_NO_ERROR();
5670
5671 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5672 }
5673
5674 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)5675 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
5676 {
5677 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
5678 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
5679
5680 constexpr char kVS[] =
5681 R"(#version 310 es
5682 #extension GL_OES_shader_multisample_interpolation : require
5683
5684 precision highp float;
5685 in vec4 inputAttribute;
5686
5687 sample out mediump float tc_in;
5688 void main()
5689 {
5690 tc_in = inputAttribute[0];
5691 gl_Position = inputAttribute;
5692 })";
5693
5694 constexpr char kTCS[] =
5695 R"(#version 310 es
5696 #extension GL_EXT_tessellation_shader : require
5697 #extension GL_OES_shader_multisample_interpolation : require
5698 layout (vertices=3) out;
5699
5700 sample in mediump float tc_in[];
5701 sample out mediump float tc_out[];
5702 void main()
5703 {
5704 tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
5705 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
5706 gl_TessLevelInner[0] = 2.0;
5707 gl_TessLevelInner[1] = 2.0;
5708 gl_TessLevelOuter[0] = 2.0;
5709 gl_TessLevelOuter[1] = 2.0;
5710 gl_TessLevelOuter[2] = 2.0;
5711 gl_TessLevelOuter[3] = 2.0;
5712 })";
5713
5714 constexpr char kTES[] =
5715 R"(#version 310 es
5716 #extension GL_EXT_tessellation_shader : require
5717 #extension GL_OES_shader_multisample_interpolation : require
5718 layout (triangles) in;
5719
5720 sample in mediump float tc_out[];
5721 sample out mediump float te_out;
5722 void main()
5723 {
5724 te_out = tc_out[2];
5725 gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
5726 })";
5727
5728 constexpr char kFS[] =
5729 R"(#version 310 es
5730 #extension GL_OES_shader_multisample_interpolation : require
5731
5732 precision highp float;
5733 sample in mediump float te_out;
5734 layout(location = 0) out mediump vec4 color;
5735
5736 void main()
5737 {
5738 float out0 = te_out;
5739 color = vec4(1, 0, 0, 1);
5740 })";
5741
5742 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
5743 drawPatches(program.get(), "inputAttribute", 0.5f, 1.0f, GL_FALSE);
5744 ASSERT_GL_NO_ERROR();
5745 }
5746
5747 // Test that a varying struct that's not declared in the fragment shader links successfully.
5748 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)5749 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
5750 {
5751 constexpr char kVS[] =
5752 "#version 300 es\n"
5753 "struct S {\n"
5754 " vec4 field;\n"
5755 "};\n"
5756 "out S varStruct;\n"
5757 "void main()\n"
5758 "{\n"
5759 " gl_Position = vec4(1.0);\n"
5760 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
5761 "}\n";
5762
5763 constexpr char kFS[] =
5764 "#version 300 es\n"
5765 "precision mediump float;\n"
5766 "out vec4 col;\n"
5767 "void main()\n"
5768 "{\n"
5769 " col = vec4(1.0);\n"
5770 "}\n";
5771
5772 ANGLE_GL_PROGRAM(program, kVS, kFS);
5773 }
5774
5775 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
5776 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)5777 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
5778 {
5779 // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
5780 // going to use it. See section 9.1 in
5781 // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
5782 // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
5783 //
5784 // However, nvidia OpenGL ES drivers fail to link this program.
5785 //
5786 // http://anglebug.com/3413
5787 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
5788
5789 constexpr char kVS[] =
5790 "#version 300 es\n"
5791 "void main()\n"
5792 "{\n"
5793 " gl_Position = vec4(1.0);\n"
5794 "}\n";
5795
5796 constexpr char kFS[] =
5797 "#version 300 es\n"
5798 "precision mediump float;\n"
5799 "out vec4 col;\n"
5800 "struct S {\n"
5801 " vec4 field;\n"
5802 "};\n"
5803 "in S varStruct;\n"
5804 "void main()\n"
5805 "{\n"
5806 " col = vec4(1.0);\n"
5807 "}\n";
5808
5809 ANGLE_GL_PROGRAM(program, kVS, kFS);
5810 }
5811
5812 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)5813 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
5814 {
5815 // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
5816 // specification that the varying values are undefined in the fragment stage). See section 9.1
5817 // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
5818 // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
5819 //
5820 // However, windows and mac OpenGL drivers fail to link this program. With a message like:
5821 //
5822 // > Input of fragment shader 'varStruct' not written by vertex shader
5823 //
5824 // http://anglebug.com/3413
5825 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || (IsWindows() && !IsNVIDIA())));
5826 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
5827 // struct member. Not sure if it's being overly strict.
5828 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5829
5830 constexpr char kVS[] =
5831 "#version 300 es\n"
5832 "struct S {\n"
5833 " vec4 field;\n"
5834 "};\n"
5835 "out S varStruct;\n"
5836 "void main()\n"
5837 "{\n"
5838 " gl_Position = vec4(1.0);\n"
5839 "}\n";
5840
5841 constexpr char kFS[] =
5842 "#version 300 es\n"
5843 "precision mediump float;\n"
5844 "out vec4 col;\n"
5845 "struct S {\n"
5846 " vec4 field;\n"
5847 "};\n"
5848 "in S varStruct;\n"
5849 "void main()\n"
5850 "{\n"
5851 " col = varStruct.field;\n"
5852 "}\n";
5853
5854 ANGLE_GL_PROGRAM(program, kVS, kFS);
5855 }
5856
5857 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)5858 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
5859 {
5860 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
5861 // struct member. Not sure if it's being overly strict.
5862 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5863 constexpr char kVS[] =
5864 "#version 300 es\n"
5865 "in vec4 inputAttribute;\n"
5866 "struct S {\n"
5867 " vec4 field;\n"
5868 "};\n"
5869 "out S varStruct;\n"
5870 "out S varStruct2;\n"
5871 "void main()\n"
5872 "{\n"
5873 " gl_Position = inputAttribute;\n"
5874 " varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
5875 " varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
5876 "}\n";
5877
5878 constexpr char kFS[] =
5879 "#version 300 es\n"
5880 "precision mediump float;\n"
5881 "out vec4 col;\n"
5882 "struct S {\n"
5883 " vec4 field;\n"
5884 "};\n"
5885 "in S varStruct;\n"
5886 "in S varStruct2;\n"
5887 "void main()\n"
5888 "{\n"
5889 " col = varStruct.field + varStruct2.field;\n"
5890 "}\n";
5891
5892 ANGLE_GL_PROGRAM(program, kVS, kFS);
5893 drawQuad(program.get(), "inputAttribute", 0.5f);
5894 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5895 }
5896
5897 // This is a regression test to make sure a red quad is rendered without issues
5898 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)5899 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
5900 {
5901 constexpr char kVS[] =
5902 "precision mediump float;\n"
5903 "attribute vec4 inputAttribute;\n"
5904 "varying mediump vec2 texCoord;\n"
5905 "void main() {\n"
5906 " texCoord = inputAttribute.xy;\n"
5907 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
5908 "}\n";
5909
5910 constexpr char kFS[] =
5911 "precision mediump float;\n"
5912 "varying mediump vec2 texCoord;\n"
5913 "uniform sampler2D testSampler;\n"
5914 "vec3 passthrough(vec3 c) {\n"
5915 " return c;\n"
5916 "}\n"
5917 "void main() {\n"
5918 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
5919 "}\n";
5920 ANGLE_GL_PROGRAM(program, kVS, kFS);
5921
5922 // Initialize basic red texture.
5923 GLTexture texture;
5924 glBindTexture(GL_TEXTURE_2D, texture);
5925 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5926 GLColor::red.data());
5927 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5928 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5929 ASSERT_GL_NO_ERROR();
5930
5931 drawQuad(program.get(), "inputAttribute", 0.5f);
5932 ASSERT_GL_NO_ERROR();
5933 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5934 }
5935
5936 // This is a regression test to make sure a red quad is rendered without issues
5937 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)5938 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
5939 {
5940 constexpr char kVS[] =
5941 "precision mediump float;\n"
5942 "attribute vec4 inputAttribute;\n"
5943 "varying mediump vec2 texCoord;\n"
5944 "void main() {\n"
5945 " texCoord = inputAttribute.xy;\n"
5946 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
5947 "}\n";
5948
5949 constexpr char kFS[] =
5950 "precision mediump float;\n"
5951 "varying mediump vec2 texCoord;\n"
5952 "uniform sampler2D testSampler;\n"
5953 "vec4 passthrough(vec4 c) {\n"
5954 " return c;\n"
5955 "}\n"
5956 "void main() {\n"
5957 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
5958 "}\n";
5959 ANGLE_GL_PROGRAM(program, kVS, kFS);
5960
5961 // Initialize basic red texture.
5962 GLTexture texture;
5963 glBindTexture(GL_TEXTURE_2D, texture);
5964 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5965 GLColor::red.data());
5966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5967 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5968 ASSERT_GL_NO_ERROR();
5969
5970 drawQuad(program.get(), "inputAttribute", 0.5f);
5971 ASSERT_GL_NO_ERROR();
5972 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5973 }
5974
5975 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)5976 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
5977 {
5978 // TODO(syoussefi): fails on android with:
5979 //
5980 // > Internal Vulkan error: A return array was too small for the result
5981 //
5982 // http://anglebug.com/3220
5983 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
5984 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
5985 // struct members. Not sure if it's being overly strict.
5986 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5987
5988 constexpr char kVS[] =
5989 "#version 300 es\n"
5990 "in vec4 inputAttribute;\n"
5991 "struct S {\n"
5992 " vec4 field1;\n"
5993 " vec4 field2;\n"
5994 "};\n"
5995 "out S varStruct;\n"
5996 "out S varStruct2;\n"
5997 "void main()\n"
5998 "{\n"
5999 " gl_Position = inputAttribute;\n"
6000 " varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6001 " varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6002 " varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6003 " varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6004 "}\n";
6005
6006 constexpr char kFS[] =
6007 "#version 300 es\n"
6008 "precision mediump float;\n"
6009 "out vec4 col;\n"
6010 "struct S {\n"
6011 " vec4 field1;\n"
6012 " vec4 field2;\n"
6013 "};\n"
6014 "in S varStruct;\n"
6015 "in S varStruct2;\n"
6016 "void main()\n"
6017 "{\n"
6018 " col = varStruct.field1 + varStruct2.field2;\n"
6019 "}\n";
6020
6021 ANGLE_GL_PROGRAM(program, kVS, kFS);
6022 drawQuad(program.get(), "inputAttribute", 0.5f);
6023 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6024 }
6025
6026 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)6027 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
6028 {
6029 constexpr char kVS[] =
6030 "#version 300 es\n"
6031 "in vec4 inputAttribute;\n"
6032 "out vec4 varArray[4];\n"
6033 "void main()\n"
6034 "{\n"
6035 " gl_Position = inputAttribute;\n"
6036 " varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
6037 " varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
6038 " varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
6039 " varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
6040 "}\n";
6041
6042 constexpr char kFS[] =
6043 "#version 300 es\n"
6044 "precision mediump float;\n"
6045 "out vec4 col;\n"
6046 "void main()\n"
6047 "{\n"
6048 " col = vec4(0.0, 0.0, 0.0, 1.0);\n"
6049 "}\n";
6050
6051 ANGLE_GL_PROGRAM(program, kVS, kFS);
6052 drawQuad(program.get(), "inputAttribute", 0.5f);
6053 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6054 }
6055
6056 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)6057 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
6058 {
6059 constexpr char kVS[] =
6060 "#version 300 es\n"
6061 "in vec4 inputAttribute;\n"
6062 "struct S {\n"
6063 " vec4 field;\n"
6064 "};\n"
6065 "out S varStruct;\n"
6066 "out S varStruct2;\n"
6067 "void main()\n"
6068 "{\n"
6069 " gl_Position = inputAttribute;\n"
6070 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6071 " varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6072 "}\n";
6073
6074 constexpr char kFS[] =
6075 "#version 300 es\n"
6076 "precision mediump float;\n"
6077 "out vec4 col;\n"
6078 "struct S {\n"
6079 " vec4 field;\n"
6080 "};\n"
6081 "in S varStruct;\n"
6082 "in S varStruct2;\n"
6083 "void main()\n"
6084 "{\n"
6085 " col = varStruct.field;\n"
6086 "}\n";
6087
6088 ANGLE_GL_PROGRAM(program, kVS, kFS);
6089 drawQuad(program.get(), "inputAttribute", 0.5f);
6090 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6091 }
6092
6093 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)6094 TEST_P(GLSLTest_ES3, VaryingMatrices)
6095 {
6096 constexpr char kVS[] =
6097 "#version 300 es\n"
6098 "in vec4 inputAttribute;\n"
6099 "out mat2x2 varMat;\n"
6100 "out mat2x2 varMat2;\n"
6101 "out mat4x3 varMat3;\n"
6102 "void main()\n"
6103 "{\n"
6104 " gl_Position = inputAttribute;\n"
6105 " varMat[0] = vec2(1, 1);\n"
6106 " varMat[1] = vec2(1, 1);\n"
6107 " varMat2[0] = vec2(0.5, 0.5);\n"
6108 " varMat2[1] = vec2(0.5, 0.5);\n"
6109 " varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
6110 " varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
6111 " varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
6112 " varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
6113 "}\n";
6114
6115 constexpr char kFS[] =
6116 "#version 300 es\n"
6117 "precision mediump float;\n"
6118 "out vec4 col;\n"
6119 "in mat2x2 varMat;\n"
6120 "in mat2x2 varMat2;\n"
6121 "in mat4x3 varMat3;\n"
6122 "void main()\n"
6123 "{\n"
6124 " col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
6125 "}\n";
6126
6127 ANGLE_GL_PROGRAM(program, kVS, kFS);
6128 drawQuad(program.get(), "inputAttribute", 0.5f);
6129 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
6130 }
6131
6132 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)6133 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
6134 {
6135 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6136 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6137
6138 const char kFragmentShader[] = R"(precision mediump float;
6139 struct S { sampler2D samplerMember; };
6140 uniform S uStruct;
6141 uniform vec2 uTexCoord;
6142 vec4 foo(S structVar)
6143 {
6144 return texture2D(structVar.samplerMember, uTexCoord);
6145 }
6146 void main()
6147 {
6148 gl_FragColor = foo(uStruct);
6149 })";
6150
6151 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6152
6153 // Initialize the texture with green.
6154 GLTexture tex;
6155 glActiveTexture(GL_TEXTURE0);
6156 glBindTexture(GL_TEXTURE_2D, tex);
6157 GLubyte texData[] = {0u, 255u, 0u, 255u};
6158 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6161 ASSERT_GL_NO_ERROR();
6162
6163 // Draw
6164 glUseProgram(program);
6165 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6166 ASSERT_NE(-1, samplerMemberLoc);
6167 glUniform1i(samplerMemberLoc, 0);
6168 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6169 ASSERT_NE(-1, texCoordLoc);
6170 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6171
6172 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6173 ASSERT_GL_NO_ERROR();
6174
6175 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6176 }
6177
6178 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)6179 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
6180 {
6181 // Shader failed to compile on Android. http://anglebug.com/2114
6182 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6183
6184 const char kFragmentShader[] = R"(precision mediump float;
6185 struct S { sampler2D samplerMember; };
6186 uniform S uStruct;
6187 uniform vec2 uTexCoord;
6188 vec4 foo(S structVar);
6189 vec4 foo(S structVar)
6190 {
6191 return texture2D(structVar.samplerMember, uTexCoord);
6192 }
6193 void main()
6194 {
6195 gl_FragColor = foo(uStruct);
6196 })";
6197
6198 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6199
6200 // Initialize the texture with green.
6201 GLTexture tex;
6202 glActiveTexture(GL_TEXTURE0);
6203 glBindTexture(GL_TEXTURE_2D, tex);
6204 GLubyte texData[] = {0u, 255u, 0u, 255u};
6205 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6208 ASSERT_GL_NO_ERROR();
6209
6210 // Draw
6211 glUseProgram(program);
6212 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6213 ASSERT_NE(-1, samplerMemberLoc);
6214 glUniform1i(samplerMemberLoc, 0);
6215 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6216 ASSERT_NE(-1, texCoordLoc);
6217 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6218
6219 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6220 ASSERT_GL_NO_ERROR();
6221
6222 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6223 }
6224 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)6225 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
6226 {
6227 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6228 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6229
6230 constexpr char kFS[] =
6231 "precision mediump float;\n"
6232 "struct S\n"
6233 "{\n"
6234 " sampler2D samplerMember; \n"
6235 "};\n"
6236 "uniform S uStructs[2];\n"
6237 "uniform vec2 uTexCoord;\n"
6238 "\n"
6239 "vec4 foo(S[2] structs)\n"
6240 "{\n"
6241 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
6242 "}\n"
6243 "void main()\n"
6244 "{\n"
6245 " gl_FragColor = foo(uStructs);\n"
6246 "}\n";
6247
6248 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6249
6250 // Initialize the texture with green.
6251 GLTexture tex;
6252 glActiveTexture(GL_TEXTURE0);
6253 glBindTexture(GL_TEXTURE_2D, tex);
6254 GLubyte texData[] = {0u, 255u, 0u, 255u};
6255 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6258 ASSERT_GL_NO_ERROR();
6259
6260 // Draw
6261 glUseProgram(program);
6262 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
6263 ASSERT_NE(-1, samplerMemberLoc);
6264 glUniform1i(samplerMemberLoc, 0);
6265 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6266 ASSERT_NE(-1, texCoordLoc);
6267 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6268
6269 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6270 ASSERT_GL_NO_ERROR();
6271
6272 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6273 }
6274
6275 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)6276 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
6277 {
6278 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6279 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6280
6281 constexpr char kFS[] =
6282 "precision mediump float;\n"
6283 "struct S\n"
6284 "{\n"
6285 " sampler2D samplerMembers[2];\n"
6286 "};\n"
6287 "uniform S uStruct;\n"
6288 "uniform vec2 uTexCoord;\n"
6289 "\n"
6290 "vec4 foo(S str)\n"
6291 "{\n"
6292 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
6293 "}\n"
6294 "void main()\n"
6295 "{\n"
6296 " gl_FragColor = foo(uStruct);\n"
6297 "}\n";
6298
6299 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6300
6301 // Initialize the texture with green.
6302 GLTexture tex;
6303 glActiveTexture(GL_TEXTURE0);
6304 glBindTexture(GL_TEXTURE_2D, tex);
6305 GLubyte texData[] = {0u, 255u, 0u, 255u};
6306 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6307 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6308 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6309 ASSERT_GL_NO_ERROR();
6310
6311 // Draw
6312 glUseProgram(program);
6313 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
6314 ASSERT_NE(-1, samplerMemberLoc);
6315 glUniform1i(samplerMemberLoc, 0);
6316 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6317 ASSERT_NE(-1, texCoordLoc);
6318 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6319
6320 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6321 ASSERT_GL_NO_ERROR();
6322
6323 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6324 }
6325
6326 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)6327 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
6328 {
6329 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6330 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6331
6332 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
6333 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
6334
6335 const char kFragmentShader[] = R"(precision mediump float;
6336 struct S { sampler2D samplerMember; };
6337 struct T { S nest; };
6338 uniform T uStruct;
6339 uniform vec2 uTexCoord;
6340 vec4 foo2(S structVar)
6341 {
6342 return texture2D(structVar.samplerMember, uTexCoord);
6343 }
6344 vec4 foo(T structVar)
6345 {
6346 return foo2(structVar.nest);
6347 }
6348 void main()
6349 {
6350 gl_FragColor = foo(uStruct);
6351 })";
6352
6353 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6354
6355 // Initialize the texture with green.
6356 GLTexture tex;
6357 glActiveTexture(GL_TEXTURE0);
6358 glBindTexture(GL_TEXTURE_2D, tex);
6359 GLubyte texData[] = {0u, 255u, 0u, 255u};
6360 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6363 ASSERT_GL_NO_ERROR();
6364
6365 // Draw
6366 glUseProgram(program);
6367 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
6368 ASSERT_NE(-1, samplerMemberLoc);
6369 glUniform1i(samplerMemberLoc, 0);
6370 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6371 ASSERT_NE(-1, texCoordLoc);
6372 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6373
6374 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6375 ASSERT_GL_NO_ERROR();
6376
6377 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6378 }
6379
6380 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)6381 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
6382 {
6383 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6384 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6385
6386 const char kFragmentShader[] = R"(precision mediump float;
6387 struct S { sampler2D samplerMember; bool b; };
6388 uniform S uStruct;
6389 uniform vec2 uTexCoord;
6390 vec4 foo(S structVar)
6391 {
6392 if (structVar.b)
6393 return texture2D(structVar.samplerMember, uTexCoord);
6394 else
6395 return vec4(1, 0, 0, 1);
6396 }
6397 void main()
6398 {
6399 gl_FragColor = foo(uStruct);
6400 })";
6401
6402 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6403
6404 // Initialize the texture with green.
6405 GLTexture tex;
6406 glActiveTexture(GL_TEXTURE0);
6407 glBindTexture(GL_TEXTURE_2D, tex);
6408 GLubyte texData[] = {0u, 255u, 0u, 255u};
6409 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6412 ASSERT_GL_NO_ERROR();
6413
6414 // Draw
6415 glUseProgram(program);
6416 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6417 ASSERT_NE(-1, samplerMemberLoc);
6418 glUniform1i(samplerMemberLoc, 0);
6419 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6420 ASSERT_NE(-1, texCoordLoc);
6421 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6422 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
6423 ASSERT_NE(-1, bLoc);
6424 glUniform1i(bLoc, 1);
6425
6426 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6427 ASSERT_GL_NO_ERROR();
6428
6429 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6430 }
6431
6432 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)6433 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
6434 {
6435 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6436 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6437
6438 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
6439 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
6440
6441 const char kFragmentShader[] = R"(precision mediump float;
6442 struct S { sampler2D samplerMember; bool b; };
6443 struct T { S nest; bool b; };
6444 uniform T uStruct;
6445 uniform vec2 uTexCoord;
6446 vec4 foo2(S structVar)
6447 {
6448 if (structVar.b)
6449 return texture2D(structVar.samplerMember, uTexCoord);
6450 else
6451 return vec4(1, 0, 0, 1);
6452 }
6453 vec4 foo(T structVar)
6454 {
6455 if (structVar.b)
6456 return foo2(structVar.nest);
6457 else
6458 return vec4(1, 0, 0, 1);
6459 }
6460 void main()
6461 {
6462 gl_FragColor = foo(uStruct);
6463 })";
6464
6465 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6466
6467 // Initialize the texture with green.
6468 GLTexture tex;
6469 glActiveTexture(GL_TEXTURE0);
6470 glBindTexture(GL_TEXTURE_2D, tex);
6471 GLubyte texData[] = {0u, 255u, 0u, 255u};
6472 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6475 ASSERT_GL_NO_ERROR();
6476
6477 // Draw
6478 glUseProgram(program);
6479 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
6480 ASSERT_NE(-1, samplerMemberLoc);
6481 glUniform1i(samplerMemberLoc, 0);
6482 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6483 ASSERT_NE(-1, texCoordLoc);
6484 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6485
6486 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
6487 ASSERT_NE(-1, bLoc);
6488 glUniform1i(bLoc, 1);
6489
6490 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
6491 ASSERT_NE(-1, nestbLoc);
6492 glUniform1i(nestbLoc, 1);
6493
6494 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6495 ASSERT_GL_NO_ERROR();
6496
6497 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6498 }
6499
6500 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)6501 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
6502 {
6503 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6504 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6505
6506 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
6507 ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
6508
6509 const char kFragmentShader[] = R"(precision mediump float;
6510 struct S { bool b; sampler2D samplerMember; };
6511 struct T { bool b; S nest; };
6512 uniform T uStruct;
6513 uniform vec2 uTexCoord;
6514 vec4 foo2(S structVar)
6515 {
6516 if (structVar.b)
6517 return texture2D(structVar.samplerMember, uTexCoord);
6518 else
6519 return vec4(1, 0, 0, 1);
6520 }
6521 vec4 foo(T structVar)
6522 {
6523 if (structVar.b)
6524 return foo2(structVar.nest);
6525 else
6526 return vec4(1, 0, 0, 1);
6527 }
6528 void main()
6529 {
6530 gl_FragColor = foo(uStruct);
6531 })";
6532
6533 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6534
6535 // Initialize the texture with green.
6536 GLTexture tex;
6537 glActiveTexture(GL_TEXTURE0);
6538 glBindTexture(GL_TEXTURE_2D, tex);
6539 GLubyte texData[] = {0u, 255u, 0u, 255u};
6540 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6541 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6542 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6543 ASSERT_GL_NO_ERROR();
6544
6545 // Draw
6546 glUseProgram(program);
6547 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
6548 ASSERT_NE(-1, samplerMemberLoc);
6549 glUniform1i(samplerMemberLoc, 0);
6550 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6551 ASSERT_NE(-1, texCoordLoc);
6552 glUniform2f(texCoordLoc, 0.5f, 0.5f);
6553
6554 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
6555 ASSERT_NE(-1, bLoc);
6556 glUniform1i(bLoc, 1);
6557
6558 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
6559 ASSERT_NE(-1, nestbLoc);
6560 glUniform1i(nestbLoc, 1);
6561
6562 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6563 ASSERT_GL_NO_ERROR();
6564
6565 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6566 }
6567 // Test that a global variable declared after main() works. This is a regression test for an issue
6568 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)6569 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
6570 {
6571 constexpr char kFS[] =
6572 "precision mediump float;\n"
6573 "int getFoo();\n"
6574 "uniform int u_zero;\n"
6575 "void main()\n"
6576 "{\n"
6577 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6578 " if (getFoo() == 0)\n"
6579 " {\n"
6580 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6581 " }\n"
6582 "}\n"
6583 "int foo;\n"
6584 "int getFoo()\n"
6585 "{\n"
6586 " foo = u_zero;\n"
6587 " return foo;\n"
6588 "}\n";
6589
6590 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6591 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6592 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6593 }
6594
6595 // Test calling array length() with a "this" expression having side effects inside a loop condition.
6596 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)6597 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
6598 {
6599 // "a" gets doubled three times in the below program.
6600 constexpr char kFS[] = R"(#version 300 es
6601 precision highp float;
6602 out vec4 my_FragColor;
6603 uniform int u_zero;
6604 int a;
6605 int[2] doubleA()
6606 {
6607 a *= 2;
6608 return int[2](a, a);
6609 }
6610 void main()
6611 {
6612 a = u_zero + 1;
6613 for (int i = 0; i < doubleA().length(); ++i)
6614 {}
6615 if (a == 8)
6616 {
6617 my_FragColor = vec4(0, 1, 0, 1);
6618 }
6619 else
6620 {
6621 my_FragColor = vec4(1, 0, 0, 1);
6622 }
6623 })";
6624
6625 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6626 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6627 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6628 }
6629
6630 // Test calling array length() with a "this" expression having side effects that interact with side
6631 // effects of another operand of the same sequence operator. The spec says that sequence operator
6632 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)6633 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
6634 {
6635 constexpr char kFS[] = R"(#version 300 es
6636 precision highp float;
6637 out vec4 my_FragColor;
6638 uniform int u_zero;
6639 int a;
6640 int[3] doubleA()
6641 {
6642 a *= 2;
6643 return int[3](a, a, a);
6644 }
6645 void main()
6646 {
6647 a = u_zero;
6648 int b = (a++, doubleA().length());
6649 if (b == 3 && a == 2)
6650 {
6651 my_FragColor = vec4(0, 1, 0, 1);
6652 }
6653 else
6654 {
6655 my_FragColor = vec4(1, 0, 0, 1);
6656 }
6657 })";
6658
6659 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6660 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6661 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6662 }
6663
6664 // Test calling array length() with a "this" expression that also contains a call of array length().
6665 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)6666 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
6667 {
6668 constexpr char kFS[] = R"(#version 300 es
6669 precision highp float;
6670 out vec4 my_FragColor;
6671 uniform int u_zero;
6672 int a;
6673 int[3] multiplyA(int multiplier)
6674 {
6675 a *= multiplier;
6676 return int[3](a, a, a);
6677 }
6678 void main()
6679 {
6680 a = u_zero + 1;
6681 int b = multiplyA(multiplyA(2).length()).length();
6682 if (b == 3 && a == 6)
6683 {
6684 my_FragColor = vec4(0, 1, 0, 1);
6685 }
6686 else
6687 {
6688 my_FragColor = vec4(1, 0, 0, 1);
6689 }
6690 })";
6691
6692 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6693 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6694 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6695 }
6696
6697 // Test calling array length() with a "this" expression having side effects inside an if condition.
6698 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)6699 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
6700 {
6701 // Bug in the shader translator. http://anglebug.com/3829
6702 ANGLE_SKIP_TEST_IF(true);
6703
6704 // "a" shouldn't get modified by this shader.
6705 constexpr char kFS[] = R"(#version 300 es
6706 precision highp float;
6707 out vec4 my_FragColor;
6708 uniform int u_zero;
6709 int a;
6710 int[2] doubleA()
6711 {
6712 a *= 2;
6713 return int[2](a, a);
6714 }
6715 void main()
6716 {
6717 a = u_zero + 1;
6718 if (u_zero != 0 && doubleA().length() == 2)
6719 {
6720 ++a;
6721 }
6722 if (a == 1)
6723 {
6724 my_FragColor = vec4(0, 1, 0, 1);
6725 }
6726 else
6727 {
6728 my_FragColor = vec4(1, 0, 0, 1);
6729 }
6730 })";
6731
6732 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6733 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6734 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6735 }
6736
6737 // Test calling array length() with a "this" expression having side effects in a statement where the
6738 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)6739 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
6740 {
6741 // Bug in the shader translator. http://anglebug.com/3829
6742 ANGLE_SKIP_TEST_IF(true);
6743
6744 // "a" shouldn't get modified by this shader.
6745 constexpr char kFS[] = R"(#version 300 es
6746 precision highp float;
6747 out vec4 my_FragColor;
6748 uniform int u_zero;
6749 int a;
6750 int[2] doubleA()
6751 {
6752 a *= 2;
6753 return int[2](a, a);
6754 }
6755 void main()
6756 {
6757 a = u_zero + 1;
6758 bool test = u_zero != 0 && doubleA().length() == 2;
6759 if (a == 1)
6760 {
6761 my_FragColor = vec4(0, 1, 0, 1);
6762 }
6763 else
6764 {
6765 my_FragColor = vec4(1, 0, 0, 1);
6766 }
6767 })";
6768
6769 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6770 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6772 }
6773
6774 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)6775 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
6776 {
6777 constexpr char kFS[] = R"(#version 300 es
6778 precision highp float;
6779 uniform int u;
6780 void main()
6781 {
6782 switch (u)
6783 {
6784 case 0:
6785 ivec2 i;
6786 i.yx;
6787 }
6788 })";
6789
6790 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6791 }
6792
6793 // Test that switch fall-through works correctly.
6794 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)6795 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
6796 {
6797 constexpr char kFS[] = R"(#version 300 es
6798 precision highp float;
6799 out vec4 my_FragColor;
6800 uniform int u_zero;
6801
6802 void main()
6803 {
6804 int i = 0;
6805 // switch should fall through both cases.
6806 switch(u_zero)
6807 {
6808 case 0:
6809 i += 1;
6810 case 1:
6811 i += 2;
6812 }
6813 if (i == 3)
6814 {
6815 my_FragColor = vec4(0, 1, 0, 1);
6816 }
6817 else
6818 {
6819 my_FragColor = vec4(1, 0, 0, 1);
6820 }
6821 })";
6822
6823 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6824 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6825 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6826 }
6827
6828 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)6829 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
6830 {
6831 constexpr char kFS[] = R"(#version 300 es
6832
6833 precision mediump float;
6834 uniform int i;
6835 void main()
6836 {
6837 switch (i)
6838 {
6839 case 0:
6840 break;
6841 default:
6842 {}
6843 }
6844 })";
6845 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6846 }
6847
6848 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)6849 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
6850 {
6851 constexpr char kFS[] = R"(#version 300 es
6852
6853 precision mediump float;
6854 uniform int i;
6855 void main()
6856 {
6857 switch (i)
6858 {
6859 case 0:
6860 break;
6861 default:
6862 float;
6863 }
6864 })";
6865 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6866 }
6867
6868 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)6869 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
6870 {
6871 constexpr char kFS[] = R"(#version 300 es
6872
6873 precision highp float;
6874
6875 uniform int u_zero;
6876 out vec4 my_FragColor;
6877
6878 bool test(int n)
6879 {
6880 switch(n) {
6881 case 0:
6882 {
6883 {
6884 break;
6885 }
6886 }
6887 case 1:
6888 {
6889 return true;
6890 }
6891 case 2:
6892 {
6893 n++;
6894 }
6895 }
6896 return false;
6897 }
6898
6899 void main()
6900 {
6901 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
6902 })";
6903
6904 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6905 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6906 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6907 }
6908
6909 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
6910 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)6911 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
6912 {
6913 constexpr char kFS[] = R"(#version 300 es
6914
6915 precision highp float;
6916 out vec4 my_FragColor;
6917
6918 uniform int u_zero;
6919
6920 void main()
6921 {
6922 my_FragColor = vec4(1, 0, 0, 1);
6923 switch (u_zero)
6924 {
6925 case 0:
6926 ivec2 i;
6927 i = ivec2(1, 0);
6928 default:
6929 my_FragColor = vec4(0, i[0], 0, 1);
6930 }
6931 })";
6932
6933 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6934 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6935 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6936 }
6937
6938 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
6939 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)6940 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
6941 {
6942 constexpr char kFS[] = R"(#version 300 es
6943
6944 precision highp float;
6945 out vec4 my_FragColor;
6946
6947 uniform int u_zero;
6948 uniform int u_zero2;
6949
6950 void main()
6951 {
6952 my_FragColor = vec4(1, 0, 0, 1);
6953 switch (u_zero)
6954 {
6955 case 0:
6956 ivec2 i;
6957 i = ivec2(1, 0);
6958 switch (u_zero2)
6959 {
6960 case 0:
6961 int j;
6962 default:
6963 j = 1;
6964 i *= j;
6965 }
6966 default:
6967 my_FragColor = vec4(0, i[0], 0, 1);
6968 }
6969 })";
6970
6971 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6972 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6973 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6974 }
6975
6976 // Test that an empty switch/case statement is translated in a way that compiles and executes the
6977 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)6978 TEST_P(GLSLTest_ES3, EmptySwitch)
6979 {
6980 constexpr char kFS[] = R"(#version 300 es
6981
6982 precision highp float;
6983
6984 uniform int u_zero;
6985 out vec4 my_FragColor;
6986
6987 void main()
6988 {
6989 int i = u_zero;
6990 switch(++i) {}
6991 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
6992 })";
6993
6994 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6995 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6996 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6997 }
6998
6999 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)7000 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
7001 {
7002 // Incorrect output color was seen on Android. http://anglebug.com/2226
7003 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
7004
7005 constexpr char kFS[] = R"(#version 300 es
7006
7007 precision highp float;
7008 out vec4 my_FragColor;
7009
7010 uniform float u_zero;
7011
7012 struct S
7013 {
7014 float field;
7015 };
7016
7017 void main()
7018 {
7019 const S constS = S(1.0);
7020 S nonConstS = constS;
7021 nonConstS.field = u_zero;
7022 bool fail = (constS == nonConstS);
7023 my_FragColor = vec4(0, 1, 0, 1);
7024 if (fail)
7025 {
7026 my_FragColor = vec4(1, 0, 0, 1);
7027 }
7028 })";
7029
7030 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7031 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7032 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7033 }
7034
7035 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)7036 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
7037 {
7038 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7039 // struct member. Not sure if it's being overly strict.
7040 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7041 constexpr char kVS[] = R"(#version 300 es
7042 in vec4 inputAttribute;
7043
7044 flat out struct S
7045 {
7046 int field;
7047 } v_s;
7048
7049 void main()
7050 {
7051 v_s.field = 1;
7052 gl_Position = inputAttribute;
7053 })";
7054
7055 constexpr char kFS[] = R"(#version 300 es
7056
7057 precision highp float;
7058 out vec4 my_FragColor;
7059
7060 flat in struct S
7061 {
7062 int field;
7063 } v_s;
7064
7065 void main()
7066 {
7067 bool success = (v_s.field == 1);
7068 my_FragColor = vec4(1, 0, 0, 1);
7069 if (success)
7070 {
7071 my_FragColor = vec4(0, 1, 0, 1);
7072 }
7073 })";
7074
7075 ANGLE_GL_PROGRAM(program, kVS, kFS);
7076 drawQuad(program.get(), "inputAttribute", 0.5f);
7077 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7078 }
7079
7080 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)7081 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
7082 {
7083 constexpr char kVS[] = R"(#version 300 es
7084 in vec4 position;
7085 uniform highp float inVal;
7086 out highp float myVarying;
7087
7088 void main()
7089 {
7090 myVarying = inVal;
7091 gl_Position = position;
7092 })";
7093
7094 constexpr char kFS[] = R"(#version 300 es
7095 precision highp float;
7096 out vec4 my_FragColor;
7097 in mediump float myVarying;
7098
7099 void main()
7100 {
7101 my_FragColor = vec4(1, 0, 0, 1);
7102 if (myVarying > 1.0)
7103 {
7104 my_FragColor = vec4(0, 1, 0, 1);
7105 }
7106 })";
7107
7108 ANGLE_GL_PROGRAM(program, kVS, kFS);
7109
7110 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7111 glClear(GL_COLOR_BUFFER_BIT);
7112 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7113
7114 glUseProgram(program.get());
7115 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7116 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7117 for (Vector3 &vertex : quadVertices)
7118 {
7119 vertex.z() = 0.5f;
7120 }
7121 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7122 glEnableVertexAttribArray(positionLocation);
7123
7124 GLint inValLoc = glGetUniformLocation(program, "inVal");
7125 ASSERT_NE(-1, inValLoc);
7126 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7127
7128 glDrawArrays(GL_TRIANGLES, 0, 6);
7129 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7130 }
7131
7132 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)7133 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
7134 {
7135 // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
7136 // precision", thus this is the same test as MismatchPrecisionFloat but including it for
7137 // completeness in case something changes.
7138 constexpr char kVS[] = R"(#version 300 es
7139 in vec4 position;
7140 uniform highp float inVal;
7141 out highp float myVarying;
7142
7143 void main()
7144 {
7145 myVarying = inVal;
7146 gl_Position = position;
7147 })";
7148
7149 constexpr char kFS[] = R"(#version 300 es
7150 precision highp float;
7151 out vec4 my_FragColor;
7152 in lowp float myVarying;
7153
7154 void main()
7155 {
7156 my_FragColor = vec4(1, 0, 0, 1);
7157 if (myVarying > 1.0)
7158 {
7159 my_FragColor = vec4(0, 1, 0, 1);
7160 }
7161 })";
7162
7163 ANGLE_GL_PROGRAM(program, kVS, kFS);
7164
7165 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7166 glClear(GL_COLOR_BUFFER_BIT);
7167 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7168
7169 glUseProgram(program.get());
7170 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7171 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7172 for (Vector3 &vertex : quadVertices)
7173 {
7174 vertex.z() = 0.5f;
7175 }
7176 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7177 glEnableVertexAttribArray(positionLocation);
7178
7179 GLint inValLoc = glGetUniformLocation(program, "inVal");
7180 ASSERT_NE(-1, inValLoc);
7181 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7182
7183 glDrawArrays(GL_TRIANGLES, 0, 6);
7184 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7185 }
7186
7187 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)7188 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
7189 {
7190 constexpr char kVS[] = R"(#version 300 es
7191 in vec2 position;
7192 uniform highp float inVal;
7193 out highp float myVarying;
7194 out highp vec2 texCoord;
7195
7196 void main()
7197 {
7198 myVarying = inVal;
7199 gl_Position = vec4(position, 0, 1);
7200 texCoord = position * 0.5 + vec2(0.5);
7201 })";
7202
7203 constexpr char kFS[] = R"(#version 300 es
7204 precision highp float;
7205 out vec4 my_FragColor;
7206 in mediump float myVarying;
7207 in mediump vec2 texCoord;
7208
7209 void main()
7210 {
7211 my_FragColor = vec4(1, 0, 0, 1);
7212 if (myVarying > 1.0)
7213 {
7214 my_FragColor = vec4(0, 1, 0, 1);
7215 }
7216 })";
7217
7218 ANGLE_GL_PROGRAM(program, kVS, kFS);
7219
7220 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7221 glClear(GL_COLOR_BUFFER_BIT);
7222 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7223
7224 glUseProgram(program.get());
7225 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7226 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7227 for (Vector3 &vertex : quadVertices)
7228 {
7229 vertex.z() = 0.5f;
7230 }
7231 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7232 glEnableVertexAttribArray(positionLocation);
7233
7234 GLint inValLoc = glGetUniformLocation(program, "inVal");
7235 ASSERT_NE(-1, inValLoc);
7236 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7237
7238 glDrawArrays(GL_TRIANGLES, 0, 6);
7239 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7240 }
7241
7242 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)7243 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
7244 {
7245 constexpr char kVS[] = R"(#version 300 es
7246 in vec2 position;
7247 uniform highp float inVal;
7248 out mediump float myVarying;
7249
7250 void main()
7251 {
7252 myVarying = inVal;
7253 gl_Position = vec4(position, 0, 1);
7254 })";
7255
7256 constexpr char kFS[] = R"(#version 300 es
7257 precision highp float;
7258 out vec4 my_FragColor;
7259 in highp float myVarying;
7260
7261 void main()
7262 {
7263 my_FragColor = vec4(1, 0, 0, 1);
7264 if (myVarying > 1.0)
7265 {
7266 my_FragColor = vec4(0, 1, 0, 1);
7267 }
7268 })";
7269
7270 ANGLE_GL_PROGRAM(program, kVS, kFS);
7271
7272 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7273 glClear(GL_COLOR_BUFFER_BIT);
7274 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7275
7276 glUseProgram(program.get());
7277 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7278 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7279 for (Vector3 &vertex : quadVertices)
7280 {
7281 vertex.z() = 0.5f;
7282 }
7283 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7284 glEnableVertexAttribArray(positionLocation);
7285
7286 GLint inValLoc = glGetUniformLocation(program, "inVal");
7287 ASSERT_NE(-1, inValLoc);
7288 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7289
7290 glDrawArrays(GL_TRIANGLES, 0, 6);
7291 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7292 }
7293
7294 // Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
7295 // bug that appeared in NVIDIA OpenGL drivers and that is worked around by
7296 // VectorizeVectorScalarArithmetic AST transform.
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)7297 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
7298 {
7299 constexpr char kFS[] = R"(precision mediump float;
7300
7301 void main() {
7302 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
7303 for (int i = 0; i < 2; i++)
7304 {
7305 gl_FragColor += (2.0 * gl_FragCoord.x);
7306 }
7307 if (gl_FragColor.g == gl_FragColor.r &&
7308 gl_FragColor.b == gl_FragColor.r &&
7309 gl_FragColor.a == gl_FragColor.r)
7310 {
7311 gl_FragColor = vec4(0, 1, 0, 1);
7312 }
7313 })";
7314
7315 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7316 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
7317 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7318 }
7319
7320 // Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
7321 // bug that appeared in NVIDIA OpenGL drivers and that is worked around by
7322 // VectorizeVectorScalarArithmetic AST transform.
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)7323 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
7324 {
7325 constexpr char kFS[] = R"(precision mediump float;
7326
7327 void main() {
7328 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
7329 for (int i = 0; i < 2; i++)
7330 {
7331 float x = gl_FragCoord.x;
7332 gl_FragColor = gl_FragColor + (x /= 2.0);
7333 }
7334 if (gl_FragColor.g == gl_FragColor.r &&
7335 gl_FragColor.b == gl_FragColor.r &&
7336 gl_FragColor.a == gl_FragColor.r)
7337 {
7338 gl_FragColor = vec4(0, 1, 0, 1);
7339 }
7340 })";
7341
7342 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7343 drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
7344 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7345 }
7346
7347 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
7348 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)7349 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
7350 {
7351 constexpr char kVS[] = R"(#version 300 es
7352
7353 in vec4 inputAttribute;
7354
7355 flat out int v;
7356
7357 void main()
7358 {
7359 v = 1;
7360 gl_Position = inputAttribute;
7361 })";
7362
7363 constexpr char kFS[] = R"(#version 300 es
7364
7365 precision highp float;
7366 out vec4 my_FragColor;
7367
7368 flat in int v;
7369
7370 void main()
7371 {
7372 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
7373 })";
7374
7375 ANGLE_GL_PROGRAM(program, kVS, kFS);
7376 drawQuad(program.get(), "inputAttribute", 0.5f);
7377 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7378 }
7379
7380 // Verify that the link error message from last link failure is cleared when the new link is
7381 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)7382 TEST_P(GLSLTest, ClearLinkErrorLog)
7383 {
7384 constexpr char kVS[] = R"(attribute vec4 vert_in;
7385 varying vec4 vert_out;
7386 void main()
7387 {
7388 gl_Position = vert_in;
7389 vert_out = vert_in;
7390 })";
7391
7392 constexpr char kFS[] = R"(precision mediump float;
7393 varying vec4 frag_in;
7394 void main()
7395 {
7396 gl_FragColor = frag_in;
7397 })";
7398
7399 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
7400 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
7401
7402 GLuint program = glCreateProgram();
7403
7404 // The first time the program link fails because of lack of fragment shader.
7405 glAttachShader(program, vs);
7406 glLinkProgram(program);
7407 GLint linkStatus = GL_TRUE;
7408 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
7409 ASSERT_FALSE(linkStatus);
7410
7411 const std::string &lackOfFragmentShader = QueryErrorMessage(program);
7412
7413 // The second time the program link fails because of the mismatch of the varying types.
7414 glAttachShader(program, fs);
7415 glLinkProgram(program);
7416 linkStatus = GL_TRUE;
7417 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
7418 ASSERT_FALSE(linkStatus);
7419
7420 const std::string &varyingTypeMismatch = QueryErrorMessage(program);
7421
7422 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
7423
7424 glDetachShader(program, vs);
7425 glDetachShader(program, fs);
7426 glDeleteShader(vs);
7427 glDeleteShader(fs);
7428 glDeleteProgram(program);
7429
7430 ASSERT_GL_NO_ERROR();
7431 }
7432
7433 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)7434 TEST_P(GLSLTest, DrawAfterShaderLinkError)
7435 {
7436 constexpr char kVS[] = R"(attribute vec4 position;
7437 varying vec4 vColor;
7438 void main()
7439 {
7440 vColor = vec4(0.0, 1.0, 0.0, 1.0);
7441 gl_Position = position;
7442 })";
7443 constexpr char kFS[] = R"(precision mediump float;
7444 varying vec4 vColor;
7445 void main()
7446 {
7447 gl_FragColor = vColor;
7448 })";
7449 constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
7450
7451 GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
7452
7453 // Create bad fragment shader
7454 {
7455 const char *sourceArray[1] = {kBadFS};
7456 glShaderSource(fsBad, 1, sourceArray, nullptr);
7457 glCompileShader(fsBad);
7458
7459 GLint compileResult;
7460 glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
7461 ASSERT_FALSE(compileResult);
7462 }
7463
7464 ANGLE_GL_PROGRAM(program, kVS, kFS);
7465 GLuint fs = GetProgramShader(program.get(), GL_FRAGMENT_SHADER);
7466
7467 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7468 glClear(GL_COLOR_BUFFER_BIT);
7469 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7470
7471 glUseProgram(program.get());
7472 GLint positionLocation = glGetAttribLocation(program.get(), "position");
7473 std::array<Vector3, 6> quadVertices = GetQuadVertices();
7474 for (Vector3 &vertex : quadVertices)
7475 {
7476 vertex.z() = 0.5f;
7477 }
7478 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7479 glEnableVertexAttribArray(positionLocation);
7480 glDrawArrays(GL_TRIANGLES, 0, 6);
7481 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7482
7483 glDetachShader(program.get(), fs);
7484 glAttachShader(program.get(), fsBad);
7485 glLinkProgram(program.get());
7486 GLint linkStatus = GL_TRUE;
7487 glGetProgramiv(program.get(), GL_LINK_STATUS, &linkStatus);
7488 ASSERT_FALSE(linkStatus);
7489
7490 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7491 glClear(GL_COLOR_BUFFER_BIT);
7492 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7493
7494 glDrawArrays(GL_TRIANGLES, 0, 6);
7495 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7496 }
7497
7498 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)7499 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
7500 {
7501 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
7502 varying vec4 vertex_out;
7503 void main()
7504 {
7505 vertex_out = inputAttribute;
7506 gl_Position = inputAttribute;
7507 })";
7508
7509 constexpr char kFS[] = R"(precision mediump float;
7510 varying float vertex_out;
7511 void main()
7512 {
7513 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
7514 })";
7515
7516 validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
7517 }
7518
7519 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)7520 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
7521 {
7522 constexpr char kVS[] = R"(#version 300 es
7523 in vec4 inputAttribute;
7524 struct S {
7525 float val1;
7526 vec4 val2;
7527 };
7528 out S vertex_out;
7529 void main()
7530 {
7531 vertex_out.val2 = inputAttribute;
7532 vertex_out.val1 = inputAttribute[0];
7533 gl_Position = inputAttribute;
7534 })";
7535
7536 constexpr char kFS[] = R"(#version 300 es
7537 precision mediump float;
7538 struct S {
7539 float val1;
7540 vec4 val3;
7541 };
7542 in S vertex_out;
7543 layout (location = 0) out vec4 frag_out;
7544 void main()
7545 {
7546 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
7547 })";
7548
7549 validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
7550 }
7551
7552 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)7553 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
7554 {
7555 constexpr char kVS[] = R"(#version 300 es
7556 in vec4 inputAttribute;
7557 struct S {
7558 float val1;
7559 vec4 val2;
7560 };
7561 out S vertex_out;
7562 void main()
7563 {
7564 vertex_out.val2 = inputAttribute;
7565 vertex_out.val1 = inputAttribute[0];
7566 gl_Position = inputAttribute;
7567 })";
7568
7569 constexpr char kFS[] = R"(#version 300 es
7570 precision mediump float;
7571 struct S {
7572 float val1;
7573 vec2 val2;
7574 };
7575 in S vertex_out;
7576 layout (location = 0) out vec4 frag_out;
7577 void main()
7578 {
7579 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
7580 })";
7581
7582 validateComponentsInErrorMessage(kVS, kFS, "Types",
7583 "varying 'vertex_out' member 'vertex_out.val2'");
7584 }
7585
7586 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
7587 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)7588 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
7589 {
7590 constexpr char kVS[] = R"(
7591 struct T
7592 {
7593 vec2 t1;
7594 vec3 t2;
7595 };
7596 struct S {
7597 T val1;
7598 vec4 val2;
7599 };
7600 uniform S uni;
7601
7602 attribute vec4 inputAttribute;
7603 varying vec4 vertex_out;
7604 void main()
7605 {
7606 vertex_out = uni.val2;
7607 gl_Position = inputAttribute;
7608 })";
7609
7610 constexpr char kFS[] = R"(precision highp float;
7611 struct T
7612 {
7613 vec2 t1;
7614 vec3 t3;
7615 };
7616 struct S {
7617 T val1;
7618 vec4 val2;
7619 };
7620 uniform S uni;
7621
7622 varying vec4 vertex_out;
7623 void main()
7624 {
7625 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
7626 })";
7627
7628 validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
7629 }
7630
7631 // Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
7632 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)7633 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
7634 {
7635 constexpr char kVS[] = R"(#version 300 es
7636 uniform S {
7637 vec2 val1;
7638 vec4 val2;
7639 } uni;
7640
7641 in vec4 inputAttribute;
7642 out vec4 vertex_out;
7643 void main()
7644 {
7645 vertex_out = uni.val2;
7646 gl_Position = inputAttribute;
7647 })";
7648
7649 constexpr char kFS[] = R"(#version 300 es
7650 precision highp float;
7651 uniform S {
7652 vec2 val1;
7653 vec3 val2;
7654 } uni;
7655
7656 in vec4 vertex_out;
7657 layout (location = 0) out vec4 frag_out;
7658 void main()
7659 {
7660 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
7661 })";
7662
7663 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
7664 }
7665
7666 // Validate error messages when the link mismatch occurs on the type of a member of a uniform block
7667 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)7668 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
7669 {
7670 constexpr char kVS[] = R"(#version 300 es
7671 struct T
7672 {
7673 vec2 t1;
7674 vec3 t2;
7675 };
7676 uniform S {
7677 T val1;
7678 vec4 val2;
7679 } uni;
7680
7681 in vec4 inputAttribute;
7682 out vec4 vertex_out;
7683 void main()
7684 {
7685 vertex_out = uni.val2;
7686 gl_Position = inputAttribute;
7687 })";
7688
7689 constexpr char kFS[] = R"(#version 300 es
7690 precision highp float;
7691 struct T
7692 {
7693 vec2 t1;
7694 vec4 t2;
7695 };
7696 uniform S {
7697 T val1;
7698 vec4 val2;
7699 } uni;
7700
7701 in vec4 vertex_out;
7702 layout (location = 0) out vec4 frag_out;
7703 void main()
7704 {
7705 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
7706 })";
7707
7708 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
7709 }
7710
7711 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
7712 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)7713 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
7714 {
7715 constexpr char kVS[] = R"(#version 300 es
7716 precision mediump float;
7717
7718 void main()
7719 {
7720 gl_Position = vec4(0, 1, 0, 1);
7721 })";
7722
7723 constexpr char kFS[] = R"(#version 300 es
7724 precision mediump float;
7725 in float foo;
7726 out vec4 my_FragColor;
7727
7728 void main()
7729 {
7730 if (false)
7731 {
7732 float unreferenced = foo;
7733 }
7734 my_FragColor = vec4(0, 1, 0, 1);
7735 })";
7736
7737 validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
7738 }
7739
7740 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)7741 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
7742 {
7743 constexpr char kVS[] = R"(#version 300 es
7744 precision mediump float;
7745 in vec4 iv;
7746 out vec4 v;
7747 void main()
7748 {
7749 gl_Position = iv;
7750 v = iv;
7751 })";
7752
7753 constexpr char kFS[] = R"(#version 300 es
7754 precision mediump float;
7755 in vec4 v;
7756 out vec4 color;
7757 void main()
7758 {
7759 color = true ? vec4(0.0) : v;
7760 })";
7761
7762 ANGLE_GL_PROGRAM(program, kVS, kFS);
7763 }
7764
7765 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)7766 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
7767 {
7768 constexpr char kVS[] = R"(#version 310 es
7769 precision highp float;
7770 in vec4 position;
7771 layout(location = 1) out vec4 shaderOutput;
7772 void main() {
7773 gl_Position = position;
7774 shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
7775 })";
7776
7777 constexpr char kFS[] = R"(#version 310 es
7778 precision highp float;
7779 layout(location = 1) in vec4 shaderInput;
7780 out vec4 outColor;
7781 void main() {
7782 outColor = shaderInput;
7783 })";
7784
7785 ANGLE_GL_PROGRAM(program, kVS, kFS);
7786 drawQuad(program, "position", 0.5f);
7787 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7788 }
7789
7790 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)7791 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
7792 {
7793 // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
7794 // up red. http://crbug.com/838885
7795 ANGLE_SKIP_TEST_IF(IsD3D11());
7796
7797 constexpr char kFS[] = R"(#version 300 es
7798 precision highp float;
7799 out vec4 my_FragColor;
7800 void main()
7801 {
7802 vec2 coord = gl_FragCoord.xy / 500.0;
7803 my_FragColor = vec4(1, 0, 0, 1);
7804 if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
7805 {
7806 my_FragColor = vec4(0, 1, 0, 1);
7807 }
7808 })";
7809
7810 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7811 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7812 // Verify that all the corners of the rendered result are green.
7813 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7814 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7815 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
7816 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
7817 }
7818
7819 // Verify that a link error is generated when the sum of the number of active image uniforms and
7820 // active shader storage blocks in a rendering pipeline exceeds
7821 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)7822 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
7823 {
7824 // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
7825 // D3D11 back-ends.
7826 ANGLE_SKIP_TEST_IF(IsD3D11());
7827
7828 GLint maxVertexShaderStorageBlocks;
7829 GLint maxVertexImageUniforms;
7830 GLint maxFragmentShaderStorageBlocks;
7831 GLint maxFragmentImageUniforms;
7832 GLint maxCombinedShaderStorageBlocks;
7833 GLint maxCombinedImageUniforms;
7834 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
7835 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
7836 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
7837 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
7838 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
7839 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
7840
7841 ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
7842 ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
7843 ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
7844 ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
7845
7846 GLint vertexSSBOs = maxVertexShaderStorageBlocks;
7847 GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
7848 // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
7849 if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
7850 {
7851 fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
7852 }
7853
7854 GLint vertexImages = maxVertexImageUniforms;
7855 GLint fragmentImages = maxFragmentImageUniforms;
7856 // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
7857 if (vertexImages + fragmentImages > maxCombinedImageUniforms)
7858 {
7859 vertexImages = maxCombinedImageUniforms - fragmentImages;
7860 }
7861
7862 GLint maxDrawBuffers;
7863 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
7864
7865 GLint maxCombinedShaderOutputResources;
7866 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
7867 ASSERT_GL_NO_ERROR();
7868
7869 ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
7870 maxDrawBuffers <=
7871 maxCombinedShaderOutputResources);
7872
7873 std::ostringstream vertexStream;
7874 vertexStream << "#version 310 es\n";
7875 for (int i = 0; i < vertexSSBOs; ++i)
7876 {
7877 vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
7878 << "{\n"
7879 " float data;\n"
7880 "} ssbo"
7881 << i << ";\n";
7882 }
7883 vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
7884 << "];\n";
7885 vertexStream << "void main()\n"
7886 "{\n"
7887 " float val = 0.1;\n"
7888 " vec4 val2 = vec4(0.0);\n";
7889 for (int i = 0; i < vertexSSBOs; ++i)
7890 {
7891 vertexStream << " val += ssbo" << i << ".data; \n";
7892 }
7893 for (int i = 0; i < vertexImages; ++i)
7894 {
7895 vertexStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
7896 }
7897 vertexStream << " gl_Position = vec4(val, val2);\n"
7898 "}\n";
7899
7900 std::ostringstream fragmentStream;
7901 fragmentStream << "#version 310 es\n"
7902 << "precision highp float;\n";
7903 for (int i = 0; i < fragmentSSBOs; ++i)
7904 {
7905 fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
7906 << "{\n"
7907 " float data;\n"
7908 "} ssbo"
7909 << i << ";\n";
7910 }
7911 fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
7912 << fragmentImages << "];\n";
7913 fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
7914
7915 fragmentStream << "void main()\n"
7916 "{\n"
7917 " float val = 0.1;\n"
7918 " vec4 val2 = vec4(0.0);\n";
7919 for (int i = 0; i < fragmentSSBOs; ++i)
7920 {
7921 fragmentStream << " val += ssbo" << i << ".data; \n";
7922 }
7923 for (int i = 0; i < fragmentImages; ++i)
7924 {
7925 fragmentStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
7926 }
7927 for (int i = 0; i < maxDrawBuffers; ++i)
7928 {
7929 fragmentStream << " foutput[" << i << "] = vec4(val, val2);\n";
7930 }
7931 fragmentStream << "}\n";
7932
7933 GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
7934 EXPECT_EQ(0u, program);
7935
7936 ASSERT_GL_NO_ERROR();
7937 }
7938
7939 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
7940 // function works correctly.
TEST_P(GLSLTest_ES3,AssignAssignmentToSwizzled)7941 TEST_P(GLSLTest_ES3, AssignAssignmentToSwizzled)
7942 {
7943 constexpr char kFS[] = R"(#version 300 es
7944 precision highp float;
7945 out vec4 my_FragColor;
7946
7947 uniform float uzero;
7948
7949 vec3 fun(float s, float v)
7950 {
7951 vec3 r = vec3(0);
7952 if (s < 1.0) {
7953 r.x = r.y = r.z = v;
7954 return r;
7955 }
7956 return r;
7957 }
7958
7959 void main()
7960 {
7961 my_FragColor.a = 1.0;
7962 my_FragColor.rgb = fun(uzero, 1.0);
7963 })";
7964
7965 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7966 drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7967 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
7968 }
7969
7970 // Test a fragment shader that returns inside if (that being the only branch that actually gets
7971 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)7972 TEST_P(GLSLTest, IfElseIfAndReturn)
7973 {
7974 constexpr char kVS[] = R"(attribute vec4 a_position;
7975 varying vec2 vPos;
7976 void main()
7977 {
7978 gl_Position = a_position;
7979 vPos = a_position.xy;
7980 })";
7981
7982 constexpr char kFS[] = R"(precision mediump float;
7983 varying vec2 vPos;
7984 void main()
7985 {
7986 if (vPos.x < 1.0) // This colors the whole canvas green
7987 {
7988 gl_FragColor = vec4(0, 1, 0, 1);
7989 return;
7990 }
7991 else if (vPos.x < 1.1) // This should have no effect
7992 {
7993 gl_FragColor = vec4(1, 0, 0, 1);
7994 }
7995 })";
7996
7997 ANGLE_GL_PROGRAM(program, kVS, kFS);
7998 drawQuad(program.get(), "a_position", 0.5f);
7999 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8000 }
8001
8002 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)8003 TEST_P(GLSLTest, PointCoordConsistency)
8004 {
8005 // AMD's OpenGL drivers may have the same issue. http://anglebug.com/1643
8006 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
8007 // http://anglebug.com/4092
8008 ANGLE_SKIP_TEST_IF(isSwiftshader());
8009
8010 constexpr char kPointCoordVS[] = R"(attribute vec2 position;
8011 uniform vec2 viewportSize;
8012 void main()
8013 {
8014 gl_Position = vec4(position, 0, 1);
8015 gl_PointSize = viewportSize.x;
8016 })";
8017
8018 constexpr char kPointCoordFS[] = R"(void main()
8019 {
8020 gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
8021 })";
8022
8023 ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
8024 glUseProgram(program);
8025
8026 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8027 ASSERT_NE(-1, uniLoc);
8028 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8029 static_cast<GLfloat>(getWindowHeight()));
8030
8031 // Draw to backbuffer.
8032 glClear(GL_COLOR_BUFFER_BIT);
8033 glDrawArrays(GL_POINTS, 0, 1);
8034 ASSERT_GL_NO_ERROR();
8035
8036 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8037 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8038 backbufferData.data());
8039
8040 GLTexture tex;
8041 glBindTexture(GL_TEXTURE_2D, tex);
8042 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8043 GL_UNSIGNED_BYTE, nullptr);
8044
8045 GLFramebuffer fbo;
8046 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8047 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8048 ASSERT_GL_NO_ERROR();
8049 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8050
8051 // Draw to user FBO.
8052 glClear(GL_COLOR_BUFFER_BIT);
8053 glDrawArrays(GL_POINTS, 0, 1);
8054 ASSERT_GL_NO_ERROR();
8055
8056 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8057 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8058 userFBOData.data());
8059
8060 ASSERT_GL_NO_ERROR();
8061 ASSERT_EQ(userFBOData.size(), backbufferData.size());
8062 EXPECT_EQ(userFBOData, backbufferData);
8063 }
8064
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)8065 bool SubrectEquals(const std::vector<GLColor> &bigArray,
8066 const std::vector<GLColor> &smallArray,
8067 int bigSize,
8068 int offset,
8069 int smallSize)
8070 {
8071 int badPixels = 0;
8072 for (int y = 0; y < smallSize; y++)
8073 {
8074 for (int x = 0; x < smallSize; x++)
8075 {
8076 int bigOffset = (y + offset) * bigSize + x + offset;
8077 int smallOffset = y * smallSize + x;
8078 if (bigArray[bigOffset] != smallArray[smallOffset])
8079 badPixels++;
8080 }
8081 }
8082 return badPixels == 0;
8083 }
8084
8085 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)8086 TEST_P(GLSLTest, FragCoordConsistency)
8087 {
8088 constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
8089 void main()
8090 {
8091 gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
8092 })";
8093
8094 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
8095 glUseProgram(program);
8096
8097 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8098 ASSERT_NE(-1, uniLoc);
8099 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8100 static_cast<GLfloat>(getWindowHeight()));
8101
8102 // Draw to backbuffer.
8103 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8104 ASSERT_GL_NO_ERROR();
8105
8106 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8107 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8108 backbufferData.data());
8109
8110 GLTexture tex;
8111 glBindTexture(GL_TEXTURE_2D, tex);
8112 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8113 GL_UNSIGNED_BYTE, nullptr);
8114
8115 GLFramebuffer fbo;
8116 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8117 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8118 ASSERT_GL_NO_ERROR();
8119 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8120
8121 // Draw to user FBO.
8122 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8123 ASSERT_GL_NO_ERROR();
8124
8125 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8126 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8127 userFBOData.data());
8128
8129 ASSERT_GL_NO_ERROR();
8130 ASSERT_EQ(userFBOData.size(), backbufferData.size());
8131 EXPECT_EQ(userFBOData, backbufferData)
8132 << "FragCoord should be the same to default and user FBO";
8133
8134 // Repeat the same test but with a smaller viewport.
8135 ASSERT_EQ(getWindowHeight(), getWindowWidth());
8136 const int kQuarterSize = getWindowWidth() >> 2;
8137 glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
8138
8139 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8140 glClear(GL_COLOR_BUFFER_BIT);
8141 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8142
8143 std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
8144 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8145 GL_UNSIGNED_BYTE, userFBOViewportData.data());
8146
8147 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8148 glClear(GL_COLOR_BUFFER_BIT);
8149 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8150
8151 std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
8152 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8153 GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
8154 ASSERT_GL_NO_ERROR();
8155 EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
8156 << "FragCoord should be the same to default and user FBO even with a custom viewport";
8157
8158 // Check that the subrectangles are the same between the viewport and non-viewport modes.
8159 EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
8160 kQuarterSize * 2));
8161 EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
8162 kQuarterSize, kQuarterSize * 2));
8163 }
8164
8165 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)8166 TEST_P(GLSLTest, DefinedInMacroSucceeds)
8167 {
8168 constexpr char kVS[] = R"(precision mediump float;
8169 attribute highp vec4 position;
8170 varying vec2 out0;
8171
8172 void main()
8173 {
8174 #define AAA defined(BBB)
8175
8176 #if !AAA
8177 out0 = vec2(0.0, 1.0);
8178 #else
8179 out0 = vec2(1.0, 0.0);
8180 #endif
8181 gl_Position = position;
8182 })";
8183
8184 constexpr char kFS[] = R"(precision mediump float;
8185 varying vec2 out0;
8186 void main()
8187 {
8188 gl_FragColor = vec4(out0, 0, 1);
8189 })";
8190
8191 ANGLE_GL_PROGRAM(program, kVS, kFS);
8192 drawQuad(program, "position", 0.5f);
8193 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8194 }
8195
8196 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)8197 TEST_P(GLSLTest, DefinedInMacroWithUndef)
8198 {
8199 constexpr char kVS[] = R"(precision mediump float;
8200 attribute highp vec4 position;
8201 varying vec2 out0;
8202
8203 void main()
8204 {
8205 #define BBB 1
8206 #define AAA defined(BBB)
8207 #undef BBB
8208
8209 #if AAA
8210 out0 = vec2(1.0, 0.0);
8211 #else
8212 out0 = vec2(0.0, 1.0);
8213 #endif
8214 gl_Position = position;
8215 })";
8216
8217 constexpr char kFS[] = R"(precision mediump float;
8218 varying vec2 out0;
8219 void main()
8220 {
8221 gl_FragColor = vec4(out0, 0, 1);
8222 })";
8223
8224 ANGLE_GL_PROGRAM(program, kVS, kFS);
8225 drawQuad(program, "position", 0.5f);
8226 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8227 }
8228
8229 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)8230 TEST_P(GLSLTest, DefinedAfterMacroUsage)
8231 {
8232 constexpr char kVS[] = R"(precision mediump float;
8233 attribute highp vec4 position;
8234 varying vec2 out0;
8235
8236 void main()
8237 {
8238 #define AAA defined(BBB)
8239 #define BBB 1
8240
8241 #if AAA
8242 out0 = vec2(0.0, 1.0);
8243 #else
8244 out0 = vec2(1.0, 0.0);
8245 #endif
8246 gl_Position = position;
8247 })";
8248
8249 constexpr char kFS[] = R"(precision mediump float;
8250 varying vec2 out0;
8251 void main()
8252 {
8253 gl_FragColor = vec4(out0, 0, 1);
8254 })";
8255
8256 ANGLE_GL_PROGRAM(program, kVS, kFS);
8257 drawQuad(program, "position", 0.5f);
8258 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8259 }
8260
8261 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)8262 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
8263 {
8264 constexpr char kVS[] = R"(precision mediump float;
8265 attribute highp vec4 position;
8266 varying vec2 out0;
8267
8268 void main()
8269 {
8270 #define BBB 1
8271 #define AAA(defi, ned) defi ## ned(BBB)
8272
8273 #if AAA(defi, ned)
8274 out0 = vec2(0.0, 1.0);
8275 #else
8276 out0 = vec2(1.0, 0.0);
8277 #endif
8278 gl_Position = position;
8279 })";
8280
8281 constexpr char kFS[] = R"(precision mediump float;
8282 varying vec2 out0;
8283 void main()
8284 {
8285 gl_FragColor = vec4(out0, 0, 1);
8286 })";
8287
8288 GLuint program = CompileProgram(kVS, kFS);
8289 EXPECT_EQ(0u, program);
8290 glDeleteProgram(program);
8291 }
8292
8293 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)8294 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
8295 {
8296 constexpr char kVS[] = R"(precision mediump float;
8297 attribute highp vec4 position;
8298 varying vec2 out0;
8299
8300 void main()
8301 {
8302 #define BBB 1
8303 #define AAA(defined) defined(BBB)
8304
8305 #if AAA(defined)
8306 out0 = vec2(0.0, 1.0);
8307 #else
8308 out0 = vec2(1.0, 0.0);
8309 #endif
8310 gl_Position = position;
8311 })";
8312
8313 constexpr char kFS[] = R"(precision mediump float;
8314 varying vec2 out0;
8315 void main()
8316 {
8317 gl_FragColor = vec4(out0, 0, 1);
8318 })";
8319
8320 GLuint program = CompileProgram(kVS, kFS);
8321 EXPECT_EQ(0u, program);
8322 glDeleteProgram(program);
8323 }
8324
8325 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)8326 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
8327 {
8328 constexpr char kVS[] = R"(precision mediump float;
8329 attribute highp vec4 position;
8330 varying float out0;
8331
8332 void main()
8333 {
8334 #define AAA defined(BBB)
8335
8336 #if !AAA
8337 out0 = 1.0;
8338 #else
8339 out0 = 0.0;
8340 #endif
8341 gl_Position = dEQP_Position;
8342 })";
8343
8344 constexpr char kFS[] = R"(precision mediump float;
8345 varying float out0;
8346 void main()
8347 {
8348 gl_FragColor = vec4(out0, 0, 0, 1);
8349 })";
8350
8351 GLuint program = CompileProgram(kVS, kFS);
8352 EXPECT_EQ(0u, program);
8353 glDeleteProgram(program);
8354 }
8355
8356 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)8357 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
8358 {
8359 constexpr char kVS[] = R"(void main()
8360 {
8361 gl_Position = vec4(1, 0, 0, 1);
8362 })";
8363
8364 constexpr char kFS[] = R"(#if defined(GL_ES)
8365 precision mediump float;
8366 void main()
8367 {
8368 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
8369 }
8370 #else
8371 foo
8372 #endif
8373 )";
8374
8375 ANGLE_GL_PROGRAM(program, kVS, kFS);
8376 }
8377
8378 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)8379 TEST_P(GLSLTest, ValidIndexClampES100)
8380 {
8381 // http://anglebug.com/6027
8382 ANGLE_SKIP_TEST_IF(IsD3D9());
8383
8384 constexpr char kFS[] = R"(
8385 precision mediump float;
8386 uniform int u;
8387 uniform mat4 m[2];
8388 void main()
8389 {
8390 gl_FragColor = vec4(m[u][1].xyz, 1);
8391 }
8392 )";
8393
8394 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8395 glUseProgram(program);
8396
8397 GLint uniformLocation = glGetUniformLocation(program, "u");
8398 ASSERT_NE(-1, uniformLocation);
8399
8400 GLint matrixLocation = glGetUniformLocation(program, "m");
8401 ASSERT_NE(matrixLocation, -1);
8402 const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
8403 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
8404 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
8405 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
8406 glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
8407
8408 glUniform1i(uniformLocation, 1);
8409 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8410 EXPECT_GL_NO_ERROR();
8411
8412 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8413 }
8414
8415 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)8416 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
8417 {
8418 constexpr char kFS[] = R"(#version 300 es
8419 precision mediump float;
8420 out vec4 color;
8421 uniform int u;
8422 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
8423 void main()
8424 {
8425 color = vec4(m[u][2].xyz, 1);
8426 }
8427 )";
8428
8429 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8430 glUseProgram(program);
8431
8432 GLint uniformLocation = glGetUniformLocation(program, "u");
8433 ASSERT_NE(-1, uniformLocation);
8434
8435 glUniform1i(uniformLocation, 2);
8436 EXPECT_GL_NO_ERROR();
8437 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8438 EXPECT_GL_NO_ERROR();
8439
8440 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
8441 }
8442
8443 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)8444 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
8445 {
8446 constexpr char kFS[] = R"(#version 300 es
8447 precision mediump float;
8448
8449 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
8450 const mat4x2 matB = mat4x2(1.0/2.0, 1.0/4.0, 1.0/8.0, 1.0/16.0, 1.0/32.0, 1.0/64.0, 1.0/128.0, 1.0/256.0);
8451
8452 out vec4 color;
8453
8454 void main()
8455 {
8456 mat4x2 result = matrixCompMult(matA, matB);
8457 vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
8458 if (vresult == vec2(4.0, 4.0))
8459 {
8460 color = vec4(0.0, 1.0, 0.0, 1.0);
8461 }
8462 else
8463 {
8464 color = vec4(1.0, 0.0, 0.0, 1.0);
8465 }
8466 })";
8467
8468 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8469 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8470 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8471 }
8472
8473 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)8474 TEST_P(GLSLTest_ES3, InitSameNameArray)
8475 {
8476 constexpr char kFS[] = R"(#version 300 es
8477 precision highp float;
8478 out vec4 my_FragColor;
8479
8480 void main()
8481 {
8482 float arr[2] = float[2](1.0, 1.0);
8483 {
8484 float arr[2] = arr;
8485 my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
8486 }
8487 })";
8488
8489 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8490 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8491 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8492 }
8493
8494 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)8495 TEST_P(GLSLTest, FragData)
8496 {
8497 // Ensures that we don't regress and emit Vulkan layer warnings.
8498 // TODO(jonahr): http://anglebug.com/3900 - Remove check once warnings are cleaned up
8499 if (IsVulkan())
8500 {
8501 treatPlatformWarningsAsErrors();
8502 }
8503
8504 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
8505 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8506 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8507 EXPECT_GL_NO_ERROR();
8508 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8509 }
8510
8511 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)8512 TEST_P(GLSLTest, MemoryExhaustedTest)
8513 {
8514 ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
8515 GLuint program =
8516 CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
8517 EXPECT_NE(0u, program);
8518 }
8519
8520 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)8521 TEST_P(GLSLTest, InactiveSamplersInStruct)
8522 {
8523 constexpr char kVS[] = R"(attribute vec4 a_position;
8524 void main() {
8525 gl_Position = a_position;
8526 })";
8527
8528 constexpr char kFS[] = R"(precision highp float;
8529 struct S
8530 {
8531 vec4 v;
8532 sampler2D t[10];
8533 };
8534 uniform S s;
8535 void main() {
8536 gl_FragColor = s.v;
8537 })";
8538
8539 ANGLE_GL_PROGRAM(program, kVS, kFS);
8540
8541 drawQuad(program, "a_position", 0.5f);
8542 }
8543
8544 // Helper functions for MixedRowAndColumnMajorMatrices* tests
8545
8546 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)8547 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
8548 {
8549 return (value + alignment - 1) & ~(alignment - 1);
8550 }
8551
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)8552 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
8553 {
8554 unsigned int outputInitData = 0;
8555 glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
8556 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
8557 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
8558 EXPECT_GL_NO_ERROR();
8559 }
8560
8561 // Fill provided buffer with matrices based on the given dimensions. The buffer should be large
8562 // enough to accomodate the data.
FillBuffer(const std::pair<uint32_t,uint32_t> matrixDims[],const bool matrixIsColMajor[],size_t matrixCount,float data[],bool isStd430,bool isTransposed)8563 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
8564 const bool matrixIsColMajor[],
8565 size_t matrixCount,
8566 float data[],
8567 bool isStd430,
8568 bool isTransposed)
8569 {
8570 size_t offset = 0;
8571 for (size_t m = 0; m < matrixCount; ++m)
8572 {
8573 uint32_t cols = matrixDims[m].first;
8574 uint32_t rows = matrixDims[m].second;
8575 bool isColMajor = matrixIsColMajor[m] != isTransposed;
8576
8577 uint32_t arraySize = isColMajor ? cols : rows;
8578 uint32_t arrayElementComponents = isColMajor ? rows : cols;
8579 // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
8580 // MixedRowAndColumnMajorMatrices* tests don't use). With std430, small matrices can have
8581 // a stride of 2 between rows/columns.
8582 uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
8583
8584 offset = RoundUpPow2(offset, stride);
8585
8586 for (uint32_t i = 0; i < arraySize; ++i)
8587 {
8588 for (uint32_t c = 0; c < arrayElementComponents; ++c)
8589 {
8590 uint32_t row = isColMajor ? c : i;
8591 uint32_t col = isColMajor ? i : c;
8592
8593 data[offset + i * stride + c] = col * 4 + row;
8594 }
8595 }
8596
8597 offset += arraySize * stride;
8598 }
8599 return offset;
8600 }
8601
8602 // Initialize and bind the buffer.
8603 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)8604 void InitBuffer(GLuint program,
8605 const char *name,
8606 GLuint buffer,
8607 uint32_t bindingIndex,
8608 const T data[],
8609 uint32_t dataSize,
8610 bool isUniform)
8611 {
8612 GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
8613
8614 glBindBufferBase(bindPoint, bindingIndex, buffer);
8615 glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
8616
8617 if (isUniform)
8618 {
8619 GLint blockIndex = glGetUniformBlockIndex(program, name);
8620 glUniformBlockBinding(program, blockIndex, bindingIndex);
8621 }
8622 }
8623
8624 // Verify that buffer data is written by the shader as expected.
8625 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)8626 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
8627 {
8628 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
8629
8630 const T *ptr = reinterpret_cast<const T *>(
8631 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize, GL_MAP_READ_BIT));
8632
8633 bool isCorrect = memcmp(ptr, data, dataSize * sizeof(*data)) == 0;
8634 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8635
8636 return isCorrect;
8637 }
8638
8639 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)8640 bool VerifySuccess(GLuint buffer)
8641 {
8642 uint32_t success = 1;
8643 return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
8644 }
8645
8646 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
8647 // both std140 and std430 layouts. Tests many combinations of std140 vs std430, struct being used
8648 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
8649 // nested structs, matrix arrays, inout parameters etc.
8650 //
8651 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)8652 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
8653 {
8654 GLint maxComputeShaderStorageBlocks;
8655 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
8656
8657 // The test uses 9 SSBOs. Skip if not that many are supported.
8658 ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
8659
8660 // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
8661 // UBO also see it as row-major despite explicit column-major qualifier.
8662 // http://anglebug.com/3830
8663 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
8664
8665 // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
8666 // read column-major despite explicit row-major qualifier. http://anglebug.com/3837
8667 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
8668
8669 // Fails on windows AMD on GL: http://anglebug.com/3838
8670 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
8671
8672 // Fails to compile the shader on Android. http://anglebug.com/3839
8673 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
8674
8675 // Fails on assertion in translation to D3D. http://anglebug.com/3841
8676 ANGLE_SKIP_TEST_IF(IsD3D11());
8677
8678 // Fails on SSBO validation on Android/Vulkan. http://anglebug.com/3840
8679 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
8680
8681 // Fails input verification as well as std140 SSBO validation. http://anglebug.com/3844
8682 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
8683
8684 // Fails on ARM on Vulkan. http://anglebug.com/4492
8685 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
8686
8687 constexpr char kCS[] = R"(#version 310 es
8688 precision highp float;
8689 layout(local_size_x=1) in;
8690
8691 struct Inner
8692 {
8693 mat3x4 m3c4r;
8694 mat4x3 m4c3r;
8695 };
8696
8697 struct Matrices
8698 {
8699 mat2 m2c2r;
8700 mat2x3 m2c3r[2];
8701 mat3x2 m3c2r;
8702 Inner inner;
8703 };
8704
8705 // For simplicity, the layouts are either of:
8706 // - col-major mat4, row-major rest
8707 // - row-major mat4, col-major rest
8708 //
8709 // The former is tagged with c, the latter with r.
8710 layout(std140, column_major) uniform Ubo140c
8711 {
8712 mat4 m4c4r;
8713 layout(row_major) Matrices m;
8714 } ubo140cIn;
8715
8716 layout(std140, row_major) uniform Ubo140r
8717 {
8718 mat4 m4c4r;
8719 layout(column_major) Matrices m;
8720 } ubo140rIn;
8721
8722 layout(std140, row_major, binding = 0) buffer Ssbo140c
8723 {
8724 layout(column_major) mat4 m4c4r;
8725 Matrices m;
8726 } ssbo140cIn;
8727
8728 layout(std140, column_major, binding = 1) buffer Ssbo140r
8729 {
8730 layout(row_major) mat4 m4c4r;
8731 Matrices m;
8732 } ssbo140rIn;
8733
8734 layout(std430, column_major, binding = 2) buffer Ssbo430c
8735 {
8736 mat4 m4c4r;
8737 layout(row_major) Matrices m;
8738 } ssbo430cIn;
8739
8740 layout(std430, row_major, binding = 3) buffer Ssbo430r
8741 {
8742 mat4 m4c4r;
8743 layout(column_major) Matrices m;
8744 } ssbo430rIn;
8745
8746 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
8747 {
8748 layout(column_major) mat4 m4c4r;
8749 Matrices m;
8750 } ssbo140cOut;
8751
8752 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
8753 {
8754 layout(row_major) mat4 m4c4r;
8755 Matrices m;
8756 } ssbo140rOut;
8757
8758 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
8759 {
8760 mat4 m4c4r;
8761 layout(row_major) Matrices m;
8762 } ssbo430cOut;
8763
8764 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
8765 {
8766 mat4 m4c4r;
8767 layout(column_major) Matrices m;
8768 } ssbo430rOut;
8769
8770 layout(std140, binding = 8) buffer Result
8771 {
8772 uint success;
8773 } resultOut;
8774
8775 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
8776 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
8777
8778 #define VERIFY_IN(result, mat, cols, rows) \
8779 EXPECT(result, mat[0].x, 0.0); \
8780 EXPECT(result, mat[0][1], 1.0); \
8781 EXPECTV(result, mat[0].xy, vec2(0, 1)); \
8782 EXPECTV(result, mat[1].xy, vec2(4, 5)); \
8783 for (int c = 0; c < cols; ++c) \
8784 { \
8785 for (int r = 0; r < rows; ++r) \
8786 { \
8787 EXPECT(result, mat[c][r], float(c * 4 + r)); \
8788 } \
8789 }
8790
8791 #define COPY(matIn, matOut, cols, rows) \
8792 matOut = matOut + matIn; \
8793 /* random operations for testing */ \
8794 matOut[0].x += matIn[0].x + matIn[1].x; \
8795 matOut[0].x -= matIn[1].x; \
8796 matOut[0][1] += matIn[0][1]; \
8797 matOut[1] += matIn[1]; \
8798 matOut[1].xy -= matIn[1].xy; \
8799 /* undo the above to get back matIn */ \
8800 matOut[0].x -= matIn[0].x; \
8801 matOut[0][1] -= matIn[0][1]; \
8802 matOut[1] -= matIn[1]; \
8803 matOut[1].xy += matIn[1].xy;
8804
8805 bool verifyMatrices(in Matrices m)
8806 {
8807 bool result = true;
8808 VERIFY_IN(result, m.m2c2r, 2, 2);
8809 VERIFY_IN(result, m.m2c3r[0], 2, 3);
8810 VERIFY_IN(result, m.m2c3r[1], 2, 3);
8811 VERIFY_IN(result, m.m3c2r, 3, 2);
8812 VERIFY_IN(result, m.inner.m3c4r, 3, 4);
8813 VERIFY_IN(result, m.inner.m4c3r, 4, 3);
8814 return result;
8815 }
8816
8817 mat4 copyMat4(in mat4 m)
8818 {
8819 return m;
8820 }
8821
8822 void copyMatrices(in Matrices mIn, inout Matrices mOut)
8823 {
8824 COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
8825 COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
8826 COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
8827 COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
8828 COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
8829 COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
8830 }
8831
8832 void main()
8833 {
8834 bool result = true;
8835
8836 VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
8837 VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
8838 EXPECT(result, verifyMatrices(ubo140cIn.m), true);
8839
8840 VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
8841 VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
8842 EXPECT(result, verifyMatrices(ubo140rIn.m), true);
8843
8844 VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
8845 VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
8846 EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
8847
8848 VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
8849 VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
8850 EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
8851
8852 VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
8853 VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
8854 EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
8855
8856 VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
8857 VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
8858 EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
8859
8860 // Only assign to SSBO from a single invocation.
8861 if (gl_GlobalInvocationID.x == 0u)
8862 {
8863 ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
8864 copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
8865 ssbo140cOut.m.m2c3r[1] = mat2x3(0);
8866 COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
8867
8868 ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
8869 copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
8870 ssbo140rOut.m.inner.m3c4r = mat3x4(0);
8871 COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
8872
8873 ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
8874 copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
8875 ssbo430cOut.m.m3c2r = mat3x2(0);
8876 COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
8877
8878 ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
8879 copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
8880 ssbo430rOut.m.inner.m4c3r = mat4x3(0);
8881 COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
8882
8883 resultOut.success = uint(result);
8884 }
8885 })";
8886
8887 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
8888 EXPECT_GL_NO_ERROR();
8889
8890 constexpr size_t kMatrixCount = 7;
8891 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
8892 {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
8893 };
8894 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
8895 true, false, false, false, false, false, false,
8896 };
8897
8898 float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
8899 float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
8900 float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
8901 float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
8902 float dataZeros[kMatrixCount * 4 * 4] = {};
8903
8904 const uint32_t sizeStd140ColMajor =
8905 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
8906 const uint32_t sizeStd140RowMajor =
8907 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
8908 const uint32_t sizeStd430ColMajor =
8909 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
8910 const uint32_t sizeStd430RowMajor =
8911 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
8912
8913 GLBuffer uboStd140ColMajor, uboStd140RowMajor;
8914 GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
8915 GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
8916 GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
8917 GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
8918
8919 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
8920 true);
8921 InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
8922 true);
8923 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
8924 false);
8925 InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
8926 false);
8927 InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
8928 false);
8929 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
8930 false);
8931 InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
8932 false);
8933 InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
8934 false);
8935 InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
8936 false);
8937 InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
8938 false);
8939 EXPECT_GL_NO_ERROR();
8940
8941 GLBuffer outputBuffer;
8942 CreateOutputBuffer(&outputBuffer, 8);
8943
8944 glUseProgram(program);
8945 glDispatchCompute(1, 1, 1);
8946 EXPECT_GL_NO_ERROR();
8947 EXPECT_TRUE(VerifySuccess(outputBuffer));
8948
8949 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
8950 EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
8951 EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
8952 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
8953 }
8954
8955 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)8956 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
8957 {
8958 // Fails to compile the shader on Android: http://anglebug.com/3839
8959 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
8960
8961 // http://anglebug.com/3837
8962 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
8963
8964 // Fails on Mac on Intel and AMD: http://anglebug.com/3842
8965 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
8966
8967 // Fails on windows AMD on GL: http://anglebug.com/3838
8968 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
8969
8970 // Fails on D3D due to mistranslation: http://anglebug.com/3841
8971 ANGLE_SKIP_TEST_IF(IsD3D11());
8972
8973 constexpr char kFS[] = R"(#version 300 es
8974 precision highp float;
8975 out vec4 outColor;
8976
8977 layout(std140, column_major) uniform Ubo
8978 {
8979 mat4 m1;
8980 layout(row_major) mat4 m2;
8981 } ubo[3];
8982
8983 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
8984
8985 #define VERIFY_IN(result, mat, cols, rows) \
8986 for (int c = 0; c < cols; ++c) \
8987 { \
8988 for (int r = 0; r < rows; ++r) \
8989 { \
8990 EXPECT(result, mat[c][r], float(c * 4 + r)); \
8991 } \
8992 }
8993
8994 void main()
8995 {
8996 bool result = true;
8997
8998 VERIFY_IN(result, ubo[0].m1, 4, 4);
8999 VERIFY_IN(result, ubo[0].m2, 4, 4);
9000
9001 VERIFY_IN(result, ubo[1].m1, 4, 4);
9002 VERIFY_IN(result, ubo[1].m2, 4, 4);
9003
9004 VERIFY_IN(result, ubo[2].m1, 4, 4);
9005 VERIFY_IN(result, ubo[2].m2, 4, 4);
9006
9007 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9008 })";
9009
9010 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9011 EXPECT_GL_NO_ERROR();
9012
9013 constexpr size_t kMatrixCount = 2;
9014 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9015 {4, 4},
9016 {4, 4},
9017 };
9018 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9019 true,
9020 false,
9021 };
9022
9023 float data[kMatrixCount * 4 * 4] = {};
9024
9025 const uint32_t size =
9026 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9027
9028 GLBuffer ubos[3];
9029
9030 InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
9031 InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
9032 InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
9033
9034 EXPECT_GL_NO_ERROR();
9035
9036 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9037 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9038 }
9039
9040 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)9041 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
9042 {
9043 // Fails on Mac on Intel and AMD: http://anglebug.com/3842
9044 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
9045
9046 // Fails on D3D due to mistranslation: http://anglebug.com/3841
9047 ANGLE_SKIP_TEST_IF(IsD3D11());
9048
9049 constexpr char kFS[] = R"(#version 300 es
9050 precision highp float;
9051 out vec4 outColor;
9052
9053 struct S
9054 {
9055 mat2x3 m2[3];
9056 };
9057
9058 layout(std140, column_major) uniform Ubo
9059 {
9060 mat4 m1;
9061 layout(row_major) S s[2];
9062 } ubo;
9063
9064 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
9065
9066 #define VERIFY_IN(result, mat, cols, rows) \
9067 for (int c = 0; c < cols; ++c) \
9068 { \
9069 for (int r = 0; r < rows; ++r) \
9070 { \
9071 EXPECT(result, mat[c][r], float(c * 4 + r)); \
9072 } \
9073 }
9074
9075 bool verify2x3(mat2x3 mat)
9076 {
9077 bool result = true;
9078
9079 for (int c = 0; c < 2; ++c)
9080 {
9081 for (int r = 0; r < 3; ++r)
9082 {
9083 EXPECT(result, mat[c][r], float(c * 4 + r));
9084 }
9085 }
9086
9087 return result;
9088 }
9089
9090 void main()
9091 {
9092 bool result = true;
9093
9094 int sideEffect = 0;
9095 VERIFY_IN(result, ubo.m1, 4, 4);
9096 EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
9097 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
9098 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
9099
9100 EXPECT(result, sideEffect, 2);
9101
9102 EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
9103 EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
9104 EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
9105
9106 EXPECT(result, sideEffect, 4);
9107
9108 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9109 })";
9110
9111 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9112 EXPECT_GL_NO_ERROR();
9113
9114 constexpr size_t kMatrixCount = 7;
9115 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9116 {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
9117 };
9118 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9119 true, false, false, false, false, false, false,
9120 };
9121
9122 float data[kMatrixCount * 4 * 4] = {};
9123
9124 const uint32_t size =
9125 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9126
9127 GLBuffer ubo;
9128 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
9129
9130 EXPECT_GL_NO_ERROR();
9131
9132 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9133 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9134 }
9135
9136 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)9137 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
9138 {
9139 // http://anglebug.com/3837
9140 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
9141
9142 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
9143 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
9144 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
9145
9146 constexpr char kFS[] = R"(#version 300 es
9147 precision highp float;
9148 out vec4 outColor;
9149
9150 layout(std140, column_major) uniform Ubo
9151 {
9152 mat4 m1;
9153 layout(row_major) mat4 m2[2];
9154 } ubo;
9155
9156 void main()
9157 {
9158 bool result = true;
9159
9160 int x = 0;
9161 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
9162 {
9163 result = true;
9164 }
9165 else
9166 {
9167 result = false;
9168 }
9169
9170 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9171 })";
9172
9173 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9174 EXPECT_GL_NO_ERROR();
9175
9176 constexpr size_t kMatrixCount = 3;
9177 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9178 {4, 4},
9179 {4, 4},
9180 {4, 4},
9181 };
9182 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
9183
9184 float data[kMatrixCount * 4 * 4] = {};
9185
9186 const uint32_t size =
9187 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9188
9189 GLBuffer ubo;
9190 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
9191
9192 EXPECT_GL_NO_ERROR();
9193
9194 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9195 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9196 }
9197
9198 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)9199 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
9200 {
9201 // Fails on Android: http://anglebug.com/3839
9202 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
9203
9204 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
9205 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
9206 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
9207
9208 constexpr char kFS[] = R"(#version 300 es
9209 precision highp float;
9210 out vec4 outColor;
9211
9212 layout(std140, column_major) uniform Ubo
9213 {
9214 mat4 m1;
9215 layout(row_major) mat4 m2[2];
9216 } ubo;
9217
9218 void main()
9219 {
9220 bool result = true;
9221
9222 int x = 0;
9223 if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
9224 {
9225 // First x == 1 should prevent the side effect of the second expression (x = 1) from
9226 // being executed. If x = 1 is run before the if, the condition of the if would be true,
9227 // which is a failure.
9228 result = false;
9229 }
9230 if (x == 1)
9231 {
9232 result = false;
9233 }
9234
9235 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9236 })";
9237
9238 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9239 EXPECT_GL_NO_ERROR();
9240
9241 constexpr size_t kMatrixCount = 3;
9242 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9243 {4, 4},
9244 {4, 4},
9245 {4, 4},
9246 };
9247 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
9248
9249 float data[kMatrixCount * 4 * 4] = {};
9250
9251 const uint32_t size =
9252 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9253
9254 GLBuffer ubo;
9255 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
9256
9257 EXPECT_GL_NO_ERROR();
9258
9259 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9260 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9261 }
9262
9263 // Test that dynamic indexing of swizzled l-values should work.
9264 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)9265 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
9266 {
9267 // The shader first assigns v.x to v.z (1.0)
9268 // Then v.y to v.y (2.0)
9269 // Then v.z to v.x (1.0)
9270 constexpr char kFS[] = R"(#version 300 es
9271 precision highp float;
9272 out vec4 my_FragColor;
9273 void main() {
9274 vec3 v = vec3(1.0, 2.0, 3.0);
9275 for (int i = 0; i < 3; i++) {
9276 v.zyx[i] = v[i];
9277 }
9278 my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9279 })";
9280
9281 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9282 EXPECT_GL_NO_ERROR();
9283 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9284 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9285 }
9286
9287 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)9288 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
9289 {
9290 constexpr char kFS[] = R"(#version 300 es
9291 precision mediump float;
9292 out vec4 color;
9293
9294 vec4 f(vec4 c)
9295 {
9296 return c;
9297 // dead code
9298 c = vec4(0, 0, 1, 1);
9299 return c;
9300 }
9301
9302 void main()
9303 {
9304 vec4 result = vec4(0, 0.5, 0, 1);
9305 int var = int(result.y * 2.2);
9306
9307 {
9308 if (result.x > 1.0)
9309 {
9310 discard;
9311 // dead code
9312 result = vec4(1, 0, 0, 1);
9313 }
9314 for (int i = 0; i < 3; ++i)
9315 {
9316 if (i < 2)
9317 {
9318 result = f(result);
9319 continue;
9320 // dead code
9321 result = vec4(1, 0, 1, 1);
9322 }
9323 result = f(result);
9324 break;
9325 // dead code
9326 result = vec4(1, 0, 1, 0);
9327 }
9328 while (true)
9329 {
9330 if (result.x > -1.0)
9331 {
9332 {
9333 result = f(result);
9334 {
9335 break;
9336 // dead code
9337 result = vec4(1, 0, 0, 0);
9338 }
9339 // dead code
9340 for (int j = 0; j < 3; ++j)
9341 {
9342 if (j > 1) continue;
9343 result = vec4(0, 0, 1, 0);
9344 color = vec4(0.5, 0, 0.5, 0.5);
9345 return;
9346 }
9347 }
9348 // dead code
9349 result = vec4(0.5, 0, 0, 0);
9350 }
9351 }
9352 switch (var)
9353 {
9354 case 2:
9355 return;
9356 // dead code
9357 color = vec4(0.25, 0, 0.25, 0.25);
9358 case 1:
9359 {
9360 // Make sure this path is not pruned due to the return in the previous case.
9361 result.y += 0.5;
9362 break;
9363 // dead code
9364 color = vec4(0.25, 0, 0, 0);
9365 }
9366 // dead code
9367 color = vec4(0, 0, 0.25, 0);
9368 break;
9369 default:
9370 break;
9371 }
9372
9373 color = result;
9374 return;
9375 // dead code
9376 color = vec4(0, 0, 0.5, 0);
9377 }
9378 // dead code
9379 color = vec4(0, 0, 0, 0.5);
9380 })";
9381
9382 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9383
9384 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9385 EXPECT_GL_NO_ERROR();
9386
9387 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9388 }
9389
9390 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
9391 // make sure they are all linked ok. The front-end sorts these resources and traverses the list of
9392 // "uniforms" to find the range for each resource. A bug there was causing some resource ranges to
9393 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)9394 TEST_P(GLSLTest_ES31, MixOfAllResources)
9395 {
9396 // http://anglebug.com/5072
9397 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
9398
9399 constexpr char kComputeShader[] = R"(#version 310 es
9400 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9401 layout(binding = 1, std430) buffer Output {
9402 uint ubo_value;
9403 uint default_value;
9404 uint sampler_value;
9405 uint ac_value;
9406 uint image_value;
9407 } outbuf;
9408 uniform Input {
9409 uint input_value;
9410 } inbuf;
9411 uniform uint default_uniform;
9412 uniform sampler2D smplr;
9413 layout(binding=0) uniform atomic_uint ac;
9414 layout(r32ui) uniform highp readonly uimage2D image;
9415
9416 void main(void)
9417 {
9418 outbuf.ubo_value = inbuf.input_value;
9419 outbuf.default_value = default_uniform;
9420 outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
9421 outbuf.ac_value = atomicCounterIncrement(ac);
9422 outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
9423 }
9424 )";
9425 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9426 EXPECT_GL_NO_ERROR();
9427
9428 glUseProgram(program);
9429
9430 unsigned int inputData = 89u;
9431 GLBuffer inputBuffer;
9432 glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
9433 glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
9434 GLuint inputBufferIndex = glGetUniformBlockIndex(program.get(), "Input");
9435 ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
9436 glUniformBlockBinding(program.get(), inputBufferIndex, 0);
9437 glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
9438
9439 unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
9440 0x13579BDFu};
9441 GLBuffer outputBuffer;
9442 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9443 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
9444 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9445 EXPECT_GL_NO_ERROR();
9446
9447 unsigned int uniformData = 456u;
9448 GLint uniformLocation = glGetUniformLocation(program, "default_uniform");
9449 ASSERT_NE(uniformLocation, -1);
9450 glUniform1ui(uniformLocation, uniformData);
9451
9452 unsigned int acData = 2u;
9453 GLBuffer atomicCounterBuffer;
9454 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9455 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9456 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9457 EXPECT_GL_NO_ERROR();
9458
9459 unsigned int imageData = 33u;
9460 GLTexture image;
9461 glBindTexture(GL_TEXTURE_2D, image);
9462 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
9463 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
9464 glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
9465 EXPECT_GL_NO_ERROR();
9466
9467 GLColor textureData(127, 18, 189, 211);
9468 GLTexture texture;
9469 glBindTexture(GL_TEXTURE_2D, texture);
9470 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
9471 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9473 ASSERT_GL_NO_ERROR();
9474
9475 glDispatchCompute(1, 1, 1);
9476 EXPECT_GL_NO_ERROR();
9477
9478 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9479
9480 // read back
9481 const GLuint *ptr = reinterpret_cast<const GLuint *>(
9482 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9483 EXPECT_EQ(ptr[0], inputData);
9484 EXPECT_EQ(ptr[1], uniformData);
9485 EXPECT_NEAR(ptr[2], textureData.R, 1.0);
9486 EXPECT_EQ(ptr[3], acData);
9487 EXPECT_EQ(ptr[4], imageData);
9488
9489 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9490 }
9491
9492 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)9493 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
9494 {
9495 // http://anglebug.com/5546
9496 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9497
9498 // anglebug.com/3832 - no sampler array params on Android
9499 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9500
9501 constexpr char kComputeShader[] = R"(#version 310 es
9502 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9503
9504 layout(binding = 1, std430) buffer Output {
9505 uint success;
9506 } outbuf;
9507
9508 uniform uint initialAcValue;
9509 uniform sampler2D smplr[2][3];
9510 layout(binding=0) uniform atomic_uint ac;
9511
9512 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
9513 {
9514 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
9515 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
9516 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
9517 uint aResult = atomicCounterIncrement(a);
9518
9519 return sExpect == sResult && aExpect == aResult;
9520 }
9521
9522 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
9523 {
9524 bool success = true;
9525 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
9526 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
9527 return success;
9528 }
9529
9530 void main(void)
9531 {
9532 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
9533 }
9534 )";
9535 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9536 EXPECT_GL_NO_ERROR();
9537
9538 glUseProgram(program);
9539
9540 unsigned int outputInitData = 0x12345678u;
9541 GLBuffer outputBuffer;
9542 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9543 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9544 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9545 EXPECT_GL_NO_ERROR();
9546
9547 unsigned int acData = 2u;
9548 GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
9549 ASSERT_NE(uniformLocation, -1);
9550 glUniform1ui(uniformLocation, acData);
9551
9552 GLBuffer atomicCounterBuffer;
9553 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9554 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9555 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9556 EXPECT_GL_NO_ERROR();
9557
9558 const std::array<GLColor, 6> kTextureData = {
9559 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
9560 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
9561 };
9562 GLTexture textures[2][3];
9563
9564 for (int dim1 = 0; dim1 < 2; ++dim1)
9565 {
9566 for (int dim2 = 0; dim2 < 3; ++dim2)
9567 {
9568 int textureUnit = dim1 * 3 + dim2;
9569 glActiveTexture(GL_TEXTURE0 + textureUnit);
9570 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
9571 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9572 &kTextureData[textureUnit]);
9573 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9575
9576 std::stringstream uniformName;
9577 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
9578 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
9579 EXPECT_NE(samplerLocation, -1);
9580 glUniform1i(samplerLocation, textureUnit);
9581 }
9582 }
9583 ASSERT_GL_NO_ERROR();
9584
9585 glDispatchCompute(1, 1, 1);
9586 EXPECT_GL_NO_ERROR();
9587
9588 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9589
9590 // read back
9591 const GLuint *ptr = reinterpret_cast<const GLuint *>(
9592 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9593 EXPECT_EQ(ptr[0], 1u);
9594
9595 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9596 }
9597
9598 // Test that array of array of samplers used as function parameter with an index that has a
9599 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)9600 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
9601 {
9602 // http://anglebug.com/5546
9603 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9604
9605 // anglebug.com/3832 - no sampler array params on Android
9606 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9607
9608 // Skip if EXT_gpu_shader5 is not enabled.
9609 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
9610
9611 constexpr char kComputeShader[] = R"(#version 310 es
9612 #extension GL_EXT_gpu_shader5 : require
9613
9614 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9615
9616 layout(binding = 1, std430) buffer Output {
9617 uint success;
9618 } outbuf;
9619
9620 uniform sampler2D smplr[2][3];
9621 layout(binding=0) uniform atomic_uint ac;
9622
9623 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
9624 {
9625 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
9626 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
9627 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
9628 uint aResult = atomicCounter(a);
9629
9630 return sExpect == sResult && aExpect == aResult;
9631 }
9632
9633 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
9634 {
9635 bool success = true;
9636 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
9637 s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
9638 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
9639 s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
9640 return success;
9641 }
9642
9643 void main(void)
9644 {
9645 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
9646 }
9647 )";
9648 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9649 EXPECT_GL_NO_ERROR();
9650
9651 glUseProgram(program);
9652
9653 unsigned int outputInitData = 0x12345678u;
9654 GLBuffer outputBuffer;
9655 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9656 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9657 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9658 EXPECT_GL_NO_ERROR();
9659
9660 unsigned int acData = 0u;
9661 GLBuffer atomicCounterBuffer;
9662 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9663 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9664 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9665 EXPECT_GL_NO_ERROR();
9666
9667 const std::array<GLColor, 6> kTextureData = {
9668 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
9669 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
9670 };
9671 GLTexture textures[2][3];
9672
9673 for (int dim1 = 0; dim1 < 2; ++dim1)
9674 {
9675 for (int dim2 = 0; dim2 < 3; ++dim2)
9676 {
9677 int textureUnit = dim1 * 3 + dim2;
9678 glActiveTexture(GL_TEXTURE0 + textureUnit);
9679 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
9680 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9681 &kTextureData[textureUnit]);
9682 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9683 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9684
9685 std::stringstream uniformName;
9686 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
9687 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
9688 EXPECT_NE(samplerLocation, -1);
9689 glUniform1i(samplerLocation, textureUnit);
9690 }
9691 }
9692 ASSERT_GL_NO_ERROR();
9693
9694 glDispatchCompute(1, 1, 1);
9695 EXPECT_GL_NO_ERROR();
9696
9697 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9698
9699 // read back
9700 const GLuint *ptr = reinterpret_cast<const GLuint *>(
9701 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9702 EXPECT_EQ(ptr[0], 1u);
9703
9704 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9705 }
9706
9707 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndex)9708 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndex)
9709 {
9710 // Skip if EXT_gpu_shader5 is not enabled.
9711 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
9712
9713 int maxTextureImageUnits = 0;
9714 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
9715 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
9716
9717 // anglebug.com/3832 - no sampler array params on Android
9718 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9719
9720 // http://anglebug.com/5546
9721 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9722
9723 constexpr char kComputeShader[] = R"(#version 310 es
9724 #extension GL_EXT_gpu_shader5 : require
9725
9726 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9727
9728 layout(binding = 1, std430) buffer Output {
9729 uint success;
9730 } outbuf;
9731
9732 uniform sampler2D smplr[2][3][4];
9733 layout(binding=0) uniform atomic_uint ac;
9734
9735 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
9736 {
9737 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
9738 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
9739 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
9740 uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
9741 uint aResult = atomicCounter(a);
9742
9743 return sExpect == sResult && aExpect == aResult;
9744 }
9745
9746 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
9747 {
9748 bool success = true;
9749 // [0][0]
9750 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
9751 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
9752 // [1][0]
9753 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
9754 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
9755 // [0][1]
9756 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
9757 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
9758 // [0][2]
9759 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
9760 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
9761 // [1][1]
9762 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
9763 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
9764 // [1][2]
9765 uint acValue = atomicCounterIncrement(ac); // Returns 5
9766 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
9767 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
9768
9769 return success;
9770 }
9771
9772 void main(void)
9773 {
9774 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
9775 }
9776 )";
9777 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9778 EXPECT_GL_NO_ERROR();
9779
9780 glUseProgram(program);
9781
9782 unsigned int outputInitData = 0x12345678u;
9783 GLBuffer outputBuffer;
9784 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9785 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9786 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9787 EXPECT_GL_NO_ERROR();
9788
9789 unsigned int acData = 0u;
9790 GLBuffer atomicCounterBuffer;
9791 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
9792 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
9793 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
9794 EXPECT_GL_NO_ERROR();
9795
9796 const std::array<GLColor, 24> kTextureData = {
9797 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
9798 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
9799 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
9800 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
9801 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
9802 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
9803 };
9804 GLTexture textures[2][3][4];
9805
9806 for (int dim1 = 0; dim1 < 2; ++dim1)
9807 {
9808 for (int dim2 = 0; dim2 < 3; ++dim2)
9809 {
9810 for (int dim3 = 0; dim3 < 4; ++dim3)
9811 {
9812 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
9813 glActiveTexture(GL_TEXTURE0 + textureUnit);
9814 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
9815 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9816 &kTextureData[textureUnit]);
9817 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9818 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9819
9820 std::stringstream uniformName;
9821 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
9822 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
9823 EXPECT_NE(samplerLocation, -1);
9824 glUniform1i(samplerLocation, textureUnit);
9825 }
9826 }
9827 }
9828 ASSERT_GL_NO_ERROR();
9829
9830 glDispatchCompute(1, 1, 1);
9831 EXPECT_GL_NO_ERROR();
9832
9833 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
9834
9835 // read back
9836 const GLuint *ptr = reinterpret_cast<const GLuint *>(
9837 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
9838 EXPECT_EQ(ptr[0], 1u);
9839
9840 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9841 }
9842
9843 // Test that array of array of samplers can be indexed correctly with dynamic indices. Uses
9844 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)9845 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
9846 {
9847 // Skip if EXT_gpu_shader5 is not enabled.
9848 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
9849
9850 int maxTextureImageUnits = 0;
9851 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
9852 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
9853
9854 // http://anglebug.com/5072
9855 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
9856
9857 // anglebug.com/3832 - no sampler array params on Android
9858 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
9859
9860 // http://anglebug.com/5546
9861 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
9862
9863 constexpr char kComputeShader[] = R"(#version 310 es
9864 #extension GL_EXT_gpu_shader5 : require
9865
9866 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
9867
9868 layout(binding = 1, std430) buffer Output {
9869 uint success;
9870 } outbuf;
9871
9872 struct I
9873 {
9874 uint index;
9875 };
9876
9877 struct S
9878 {
9879 sampler2D smplr[4];
9880 I nested;
9881 };
9882
9883 struct T
9884 {
9885 S nested[3];
9886 uint tIndex;
9887 };
9888
9889 uniform T u[2];
9890
9891 uint getValue(in sampler2D s)
9892 {
9893 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
9894 }
9895
9896 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
9897 {
9898 uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
9899 getValue(s[2]), getValue(s[3]));
9900
9901 return sExpect == sResult;
9902 }
9903
9904 bool samplerTest(T t, uint N)
9905 {
9906 // u[N].tIndex == 0 + N*4
9907 // u[N].nested[0].nested.index == 1 + N*4
9908 // u[N].nested[1].nested.index == 2 + N*4
9909 // u[N].nested[2].nested.index == 3 + N*4
9910
9911 uvec4 colorOffset = N * 3u * 4u * uvec4(8);
9912
9913 bool success = true;
9914 // [N][0]
9915 success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
9916 t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
9917 // [N][1]
9918 success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
9919 t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
9920 // [N][2]
9921 success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
9922 t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
9923
9924 return success;
9925 }
9926
9927 bool uniformTest(T t, uint N)
9928 {
9929 // Also verify that expressions that involve structs-with-samplers are correct when not
9930 // referecing the sampler.
9931
9932 bool success = true;
9933 success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
9934 success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
9935 success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
9936
9937 success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
9938 && success;
9939 success = (t.nested[t.nested[0].nested.index - t.tIndex ].nested.index - t.tIndex == 2u)
9940 && success;
9941 success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
9942 && success;
9943
9944 success = (t.nested[
9945 t.nested[
9946 t.nested[2].nested.index - t.tIndex - 1u // 2
9947 ].nested.index - t.tIndex - 2u // 1
9948 ].nested.index - t.tIndex // 2
9949 == 2u) && success;
9950
9951 return success;
9952 }
9953
9954 void main(void)
9955 {
9956 bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
9957 && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
9958 outbuf.success = uint(success);
9959 }
9960 )";
9961 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
9962 EXPECT_GL_NO_ERROR();
9963
9964 glUseProgram(program);
9965
9966 unsigned int outputInitData = 0x12345678u;
9967 GLBuffer outputBuffer;
9968 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
9969 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9970 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
9971 EXPECT_GL_NO_ERROR();
9972
9973 const std::array<GLColor, 24> kTextureData = {
9974 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
9975 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
9976 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
9977 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
9978 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
9979 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
9980 };
9981 GLTexture textures[2][3][4];
9982
9983 for (int dim1 = 0; dim1 < 2; ++dim1)
9984 {
9985 for (int dim2 = 0; dim2 < 3; ++dim2)
9986 {
9987 for (int dim3 = 0; dim3 < 4; ++dim3)
9988 {
9989 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
9990 glActiveTexture(GL_TEXTURE0 + textureUnit);
9991 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
9992 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9993 &kTextureData[textureUnit]);
9994 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9996
9997 std::stringstream uniformName;
9998 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
9999 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10000 EXPECT_NE(samplerLocation, -1);
10001 glUniform1i(samplerLocation, textureUnit);
10002 }
10003
10004 std::stringstream uniformName;
10005 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
10006 GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
10007 EXPECT_NE(nestedIndexLocation, -1);
10008 glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
10009 }
10010
10011 std::stringstream uniformName;
10012 uniformName << "u[" << dim1 << "].tIndex";
10013 GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
10014 EXPECT_NE(indexLocation, -1);
10015 glUniform1ui(indexLocation, dim1 * 4);
10016 }
10017 ASSERT_GL_NO_ERROR();
10018
10019 glDispatchCompute(1, 1, 1);
10020 EXPECT_GL_NO_ERROR();
10021
10022 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10023
10024 // read back
10025 const GLuint *ptr = reinterpret_cast<const GLuint *>(
10026 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10027 EXPECT_EQ(ptr[0], 1u);
10028
10029 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10030 }
10031
10032 // Test that array of array of samplers work when indexed with an expression that's derived from an
10033 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)10034 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
10035 {
10036 // Skip if EXT_gpu_shader5 is not enabled.
10037 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10038
10039 // anglebug.com/3832 - no sampler array params on Android
10040 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10041
10042 constexpr char kComputeShader[] = R"(#version 310 es
10043 #extension GL_EXT_gpu_shader5 : require
10044
10045 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10046
10047 layout(binding = 1, std430) buffer Output {
10048 uint success;
10049 } outbuf;
10050
10051 uniform sampler2D smplr[2][3];
10052
10053 uint getValue(in sampler2D s)
10054 {
10055 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
10056 }
10057
10058 bool runTest(in sampler2D s[2][3])
10059 {
10060 // s[0][0] should contain 2
10061 // s[0][1] should contain 0
10062 // s[0][2] should contain 1
10063 // s[1][0] should contain 1
10064 // s[1][1] should contain 2
10065 // s[1][2] should contain 0
10066
10067 uint result = getValue(
10068 s[
10069 getValue(
10070 s[
10071 getValue(s[0][1]) // 0
10072 ][
10073 getValue(s[0][0]) // 2
10074 ]
10075 ) // s[0][2] -> 1
10076 ][
10077 getValue(
10078 s[
10079 getValue(s[1][0]) // 1
10080 ][
10081 getValue(s[1][1]) // 2
10082 ]
10083 ) // s[1][2] -> 0
10084 ]
10085 ); // s[1][0] -> 1
10086
10087 return result == 1u;
10088 }
10089
10090 void main(void)
10091 {
10092 outbuf.success = uint(runTest(smplr));
10093 }
10094 )";
10095 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10096 EXPECT_GL_NO_ERROR();
10097
10098 glUseProgram(program);
10099
10100 unsigned int outputInitData = 0x12345678u;
10101 GLBuffer outputBuffer;
10102 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10103 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10104 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10105 EXPECT_GL_NO_ERROR();
10106
10107 const std::array<GLColor, 6> kTextureData = {
10108 GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
10109 GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
10110 };
10111 GLTexture textures[2][3];
10112
10113 for (int dim1 = 0; dim1 < 2; ++dim1)
10114 {
10115 for (int dim2 = 0; dim2 < 3; ++dim2)
10116 {
10117 int textureUnit = dim1 * 3 + dim2;
10118 glActiveTexture(GL_TEXTURE0 + textureUnit);
10119 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
10120 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10121 &kTextureData[textureUnit]);
10122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10124
10125 std::stringstream uniformName;
10126 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
10127 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10128 EXPECT_NE(samplerLocation, -1);
10129 glUniform1i(samplerLocation, textureUnit);
10130 }
10131 }
10132 ASSERT_GL_NO_ERROR();
10133
10134 glDispatchCompute(1, 1, 1);
10135 EXPECT_GL_NO_ERROR();
10136
10137 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10138
10139 // read back
10140 const GLuint *ptr = reinterpret_cast<const GLuint *>(
10141 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10142 EXPECT_EQ(ptr[0], 1u);
10143
10144 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10145 }
10146
10147 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)10148 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
10149 {
10150 // http://anglebug.com/3831
10151 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
10152
10153 // Fails on windows AMD on GL: http://anglebug.com/3838
10154 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
10155 // http://anglebug.com/5384
10156 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
10157
10158 // Fails on D3D due to mistranslation: http://anglebug.com/3841
10159 ANGLE_SKIP_TEST_IF(IsD3D11());
10160
10161 constexpr char kCS[] = R"(#version 310 es
10162 precision highp float;
10163 layout(local_size_x=1) in;
10164
10165 layout(std140, column_major) uniform Ubo
10166 {
10167 mat4 m1;
10168 layout(row_major) mat4 m2;
10169 } ubo;
10170
10171 layout(std140, row_major, binding = 0) buffer Ssbo
10172 {
10173 layout(column_major) mat4 m1;
10174 mat4 m2;
10175 } ssbo;
10176
10177 layout(std140, binding = 1) buffer Result
10178 {
10179 uint success;
10180 } resultOut;
10181
10182 void main()
10183 {
10184 bool result = true;
10185
10186 // Only assign to SSBO from a single invocation.
10187 if (gl_GlobalInvocationID.x == 0u)
10188 {
10189 if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
10190 {
10191 result = false;
10192 }
10193
10194 resultOut.success = uint(result);
10195 }
10196 })";
10197
10198 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10199 EXPECT_GL_NO_ERROR();
10200
10201 constexpr size_t kMatrixCount = 2;
10202 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10203 {4, 4},
10204 {4, 4},
10205 };
10206 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10207 true,
10208 false,
10209 };
10210
10211 float data[kMatrixCount * 4 * 4] = {};
10212 float zeros[kMatrixCount * 4 * 4] = {};
10213
10214 const uint32_t size =
10215 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10216
10217 GLBuffer ubo, ssbo;
10218
10219 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10220 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
10221 EXPECT_GL_NO_ERROR();
10222
10223 GLBuffer outputBuffer;
10224 CreateOutputBuffer(&outputBuffer, 1);
10225
10226 glUseProgram(program);
10227 glDispatchCompute(1, 1, 1);
10228 EXPECT_GL_NO_ERROR();
10229 EXPECT_TRUE(VerifySuccess(outputBuffer));
10230
10231 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
10232 }
10233
10234 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)10235 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
10236 {
10237 // Fails on windows AMD on GL: http://anglebug.com/3838
10238 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
10239 // http://anglebug.com/5384
10240 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
10241
10242 // Fails on D3D due to mistranslation: http://anglebug.com/3841
10243 ANGLE_SKIP_TEST_IF(IsD3D11());
10244
10245 // Fails compiling shader on Android/Vulkan. http://anglebug.com/4290
10246 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
10247
10248 // Fails on ARM on Vulkan. http://anglebug.com/4492
10249 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
10250
10251 constexpr char kCS[] = R"(#version 310 es
10252 precision highp float;
10253 layout(local_size_x=1) in;
10254
10255 layout(std140, column_major) uniform Ubo
10256 {
10257 mat4 m1;
10258 layout(row_major) mat4 m2[2][3];
10259 } ubo;
10260
10261 layout(std140, row_major, binding = 0) buffer Ssbo
10262 {
10263 layout(column_major) mat4 m1;
10264 mat4 m2[2][3];
10265 } ssbo;
10266
10267 layout(std140, binding = 1) buffer Result
10268 {
10269 uint success;
10270 } resultOut;
10271
10272 void main()
10273 {
10274 bool result = true;
10275
10276 // Only assign to SSBO from a single invocation.
10277 if (gl_GlobalInvocationID.x == 0u)
10278 {
10279 ssbo.m1 = ubo.m1;
10280 ssbo.m2 = ubo.m2;
10281
10282 resultOut.success = uint(result);
10283 }
10284 })";
10285
10286 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10287 EXPECT_GL_NO_ERROR();
10288
10289 constexpr size_t kMatrixCount = 7;
10290 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10291 {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
10292 };
10293 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10294 true, false, false, false, false, false, false,
10295 };
10296
10297 float data[kMatrixCount * 4 * 4] = {};
10298 float zeros[kMatrixCount * 4 * 4] = {};
10299
10300 const uint32_t size =
10301 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10302
10303 GLBuffer ubo, ssbo;
10304
10305 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10306 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
10307 EXPECT_GL_NO_ERROR();
10308
10309 GLBuffer outputBuffer;
10310 CreateOutputBuffer(&outputBuffer, 1);
10311
10312 glUseProgram(program);
10313 glDispatchCompute(1, 1, 1);
10314 EXPECT_GL_NO_ERROR();
10315 EXPECT_TRUE(VerifySuccess(outputBuffer));
10316
10317 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
10318 }
10319
10320 // Verify that types used differently (in different block storages, differently qualified etc) work
10321 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)10322 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
10323 {
10324 constexpr char kCS[] = R"(#version 310 es
10325 precision highp float;
10326 layout(local_size_x=1) in;
10327
10328 struct Inner
10329 {
10330 mat3x2 m;
10331 float f[3];
10332 uvec2 u[2][4];
10333 ivec3 i;
10334 mat2x3 m2[3][2];
10335 };
10336
10337 struct Outer
10338 {
10339 Inner i[2];
10340 };
10341
10342 layout(std140, column_major) uniform Ubo140c
10343 {
10344 mat2 m;
10345 layout(row_major) Outer o;
10346 } ubo140cIn;
10347
10348 layout(std430, row_major, binding = 0) buffer Ubo430r
10349 {
10350 mat2 m;
10351 layout(column_major) Outer o;
10352 } ubo430rIn;
10353
10354 layout(std140, column_major, binding = 1) buffer Ssbo140c
10355 {
10356 layout(row_major) mat2 m[2];
10357 Outer o;
10358 layout(row_major) Inner i;
10359 } ssbo140cOut;
10360
10361 layout(std430, row_major, binding = 2) buffer Ssbo430r
10362 {
10363 layout(column_major) mat2 m[2];
10364 Outer o;
10365 layout(column_major) Inner i;
10366 } ssbo430rOut;
10367
10368 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
10369 {
10370 ssbo140cOut.o.i[innerIndex].u = u;
10371 }
10372
10373 void writeBlockArgToStd140(Inner i, int innerIndex)
10374 {
10375 ssbo140cOut.o.i[innerIndex] = i;
10376 }
10377
10378 mat2x3[3][2] readFromStd140(int innerIndex)
10379 {
10380 return ubo140cIn.o.i[0].m2;
10381 }
10382
10383 Inner readBlockFromStd430(int innerIndex)
10384 {
10385 return ubo430rIn.o.i[innerIndex];
10386 }
10387
10388 void copyFromStd140(out Inner i)
10389 {
10390 i = ubo140cIn.o.i[1];
10391 }
10392
10393 void main(){
10394 // Directly copy from one layout to another.
10395 ssbo140cOut.m[0] = ubo140cIn.m;
10396 ssbo140cOut.m[1] = ubo430rIn.m;
10397 ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
10398 ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
10399 ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
10400
10401 // Read from block and pass to function.
10402 writeArgToStd140(ubo140cIn.o.i[0].u, 0);
10403 writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
10404
10405 // Have function return value read from block.
10406 ssbo140cOut.o.i[0].m2 = readFromStd140(0);
10407
10408 // Have function fill in value as out parameter.
10409 copyFromStd140(ssbo140cOut.i);
10410
10411 // Initialize local variable.
10412 mat2 mStd140 = ubo140cIn.m;
10413
10414 // Copy to variable, through multiple assignments.
10415 mat2 mStd430, temp;
10416 mStd430 = temp = ubo430rIn.m;
10417
10418 // Copy from local variable
10419 ssbo430rOut.m[0] = mStd140;
10420 ssbo430rOut.m[1] = mStd430;
10421
10422 // Construct from struct.
10423 Inner iStd140 = ubo140cIn.o.i[1];
10424 Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
10425
10426 // Copy struct from local variable.
10427 ssbo430rOut.o = oStd140;
10428
10429 // Construct from arrays
10430 Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
10431 ubo430rIn.o.i[1].f,
10432 ubo430rIn.o.i[1].u,
10433 ubo430rIn.o.i[1].i,
10434 ubo430rIn.o.i[1].m2);
10435 ssbo430rOut.i = iStd430;
10436 })";
10437
10438 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10439 EXPECT_GL_NO_ERROR();
10440
10441 // Test data, laid out with padding (0) based on std140/std430 rules.
10442 // clang-format off
10443 const std::vector<float> ubo140cData = {
10444 // m (mat2, column-major)
10445 1, 2, 0, 0, 3, 4, 0, 0,
10446
10447 // o.i[0].m (mat3x2, row-major)
10448 5, 7, 9, 0, 6, 8, 10, 0,
10449 // o.i[0].f (float[3])
10450 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
10451 // o.i[0].u (uvec2[2][4])
10452 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
10453 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
10454 // o.i[0].i (ivec3)
10455 31, 32, 33, 0,
10456 // o.i[0].m2 (mat2x3[3][2], row-major)
10457 34, 37, 0, 0, 35, 38, 0, 0, 36, 39, 0, 0,
10458 40, 43, 0, 0, 41, 44, 0, 0, 42, 45, 0, 0,
10459 46, 49, 0, 0, 47, 50, 0, 0, 48, 51, 0, 0,
10460 52, 55, 0, 0, 53, 56, 0, 0, 54, 57, 0, 0,
10461 58, 61, 0, 0, 59, 62, 0, 0, 60, 63, 0, 0,
10462 64, 67, 0, 0, 65, 68, 0, 0, 66, 69, 0, 0,
10463
10464 // o.i[1].m (mat3x2, row-major)
10465 70, 72, 74, 0, 71, 73, 75, 0,
10466 // o.i[1].f (float[3])
10467 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
10468 // o.i[1].u (uvec2[2][4])
10469 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
10470 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
10471 // o.i[1].i (ivec3)
10472 96, 97, 98, 0,
10473 // o.i[1].m2 (mat2x3[3][2], row-major)
10474 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
10475 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
10476 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
10477 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
10478 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
10479 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
10480 };
10481 const std::vector<float> ubo430rData = {
10482 // m (mat2, row-major)
10483 135, 137, 136, 138,
10484
10485 // o.i[0].m (mat3x2, column-major)
10486 139, 140, 141, 142, 143, 144,
10487 // o.i[0].f (float[3])
10488 146, 147, 148, 0,
10489 // o.i[0].u (uvec2[2][4])
10490 149, 150, 151, 152, 153, 154, 155, 156,
10491 157, 158, 159, 160, 161, 162, 163, 164, 0, 0,
10492 // o.i[0].i (ivec3)
10493 165, 166, 167, 0,
10494 // o.i[0].m2 (mat2x3[3][2], column-major)
10495 168, 169, 170, 0, 171, 172, 173, 0,
10496 174, 175, 176, 0, 177, 178, 179, 0,
10497 180, 181, 182, 0, 183, 184, 185, 0,
10498 186, 187, 188, 0, 189, 190, 191, 0,
10499 192, 193, 194, 0, 195, 196, 197, 0,
10500 198, 199, 200, 0, 201, 202, 203, 0,
10501
10502 // o.i[1].m (mat3x2, column-major)
10503 204, 205, 206, 207, 208, 209,
10504 // o.i[1].f (float[3])
10505 211, 212, 213, 0,
10506 // o.i[1].u (uvec2[2][4])
10507 214, 215, 216, 217, 218, 219, 220, 221,
10508 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
10509 // o.i[1].i (ivec3)
10510 230, 231, 232, 0,
10511 // o.i[1].m2 (mat2x3[3][2], column-major)
10512 233, 234, 235, 0, 236, 237, 238, 0,
10513 239, 240, 241, 0, 242, 243, 244, 0,
10514 245, 246, 247, 0, 248, 249, 250, 0,
10515 251, 252, 253, 0, 254, 255, 256, 0,
10516 257, 258, 259, 0, 260, 261, 262, 0,
10517 263, 264, 265, 0, 266, 267, 268, 0,
10518 };
10519 const std::vector<float> ssbo140cExpect = {
10520 // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
10521 1, 3, 0, 0, 2, 4, 0, 0,
10522 135, 137, 0, 0, 136, 138, 0, 0,
10523
10524 // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
10525 5, 6, 0, 0, 7, 8, 0, 0, 9, 10, 0, 0,
10526 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
10527 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
10528 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
10529 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
10530 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
10531 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
10532 31, 32, 33, 0,
10533 // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
10534 34, 35, 36, 0, 37, 38, 39, 0,
10535 40, 41, 42, 0, 43, 44, 45, 0,
10536 46, 47, 48, 0, 49, 50, 51, 0,
10537 52, 53, 54, 0, 55, 56, 57, 0,
10538 58, 59, 60, 0, 61, 62, 63, 0,
10539 64, 65, 66, 0, 67, 68, 69, 0,
10540
10541 // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
10542 139, 140, 0, 0, 141, 142, 0, 0, 143, 144, 0, 0,
10543 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
10544 146, 0, 0, 0, 147, 0, 0, 0, 148, 0, 0, 0,
10545 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
10546 149, 150, 0, 0, 151, 152, 0, 0, 153, 154, 0, 0, 155, 156, 0, 0,
10547 157, 158, 0, 0, 159, 160, 0, 0, 161, 162, 0, 0, 163, 164, 0, 0,
10548 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
10549 165, 166, 167, 0,
10550 // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
10551 168, 169, 170, 0, 171, 172, 173, 0,
10552 174, 175, 176, 0, 177, 178, 179, 0,
10553 180, 181, 182, 0, 183, 184, 185, 0,
10554 186, 187, 188, 0, 189, 190, 191, 0,
10555 192, 193, 194, 0, 195, 196, 197, 0,
10556 198, 199, 200, 0, 201, 202, 203, 0,
10557
10558 // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
10559 70, 72, 74, 0, 71, 73, 75, 0,
10560 // i.f (float[3]), copied from ubo140cIn.o.i[1].f
10561 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
10562 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
10563 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
10564 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
10565 // i.i (ivec3), copied from ubo140cIn.o.i[1].i
10566 96, 97, 98, 0,
10567 // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
10568 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
10569 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
10570 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
10571 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
10572 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
10573 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
10574 };
10575 const std::vector<float> ssbo430rExpect = {
10576 // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
10577 1, 2, 3, 4,
10578 135, 136, 137, 138,
10579
10580 // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
10581 70, 72, 74, 0, 71, 73, 75, 0,
10582 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
10583 77, 78, 79, 0,
10584 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
10585 80, 81, 82, 83, 84, 85, 86, 87,
10586 88, 89, 90, 91, 92, 93, 94, 95,
10587 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
10588 96, 97, 98, 0,
10589 // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
10590 99, 102, 100, 103, 101, 104,
10591 105, 108, 106, 109, 107, 110,
10592 111, 114, 112, 115, 113, 116,
10593 117, 120, 118, 121, 119, 122,
10594 123, 126, 124, 127, 125, 128,
10595 129, 132, 130, 133, 131, 134,
10596
10597 // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
10598 204, 206, 208, 0, 205, 207, 209, 0,
10599 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
10600 211, 212, 213, 0,
10601 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
10602 214, 215, 216, 217, 218, 219, 220, 221,
10603 222, 223, 224, 225, 226, 227, 228, 229,
10604 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
10605 230, 231, 232, 0,
10606 // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
10607 233, 236, 234, 237, 235, 238,
10608 239, 242, 240, 243, 241, 244,
10609 245, 248, 246, 249, 247, 250,
10610 251, 254, 252, 255, 253, 256,
10611 257, 260, 258, 261, 259, 262,
10612 263, 266, 264, 267, 265, 268,
10613
10614 // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
10615 204, 205, 206, 207, 208, 209,
10616 // i.f (float[3]), copied from ubo430rIn.o.i[1].f
10617 211, 212, 213, 0,
10618 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
10619 214, 215, 216, 217, 218, 219, 220, 221,
10620 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
10621 // i.i (ivec3), copied from ubo430rIn.o.i[1].i
10622 230, 231, 232, 0,
10623 // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
10624 233, 234, 235, 0, 236, 237, 238, 0,
10625 239, 240, 241, 0, 242, 243, 244, 0,
10626 245, 246, 247, 0, 248, 249, 250, 0,
10627 251, 252, 253, 0, 254, 255, 256, 0,
10628 257, 258, 259, 0, 260, 261, 262, 0,
10629 263, 264, 265, 0, 266, 267, 268, 0,
10630 };
10631 const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
10632 // clang-format on
10633
10634 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
10635 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
10636
10637 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
10638 static_cast<uint32_t>(ubo140cData.size()), true);
10639 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
10640 static_cast<uint32_t>(ubo430rData.size()), false);
10641 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
10642 static_cast<uint32_t>(ssbo140cExpect.size()), false);
10643 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
10644 static_cast<uint32_t>(ssbo430rExpect.size()), false);
10645 EXPECT_GL_NO_ERROR();
10646
10647 glUseProgram(program);
10648 glDispatchCompute(1, 1, 1);
10649 EXPECT_GL_NO_ERROR();
10650
10651 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
10652 static_cast<uint32_t>(ssbo140cExpect.size())));
10653 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
10654 static_cast<uint32_t>(ssbo430rExpect.size())));
10655 }
10656
10657 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)10658 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
10659 {
10660 constexpr char kCS[] = R"(#version 310 es
10661 precision highp float;
10662 layout(local_size_x=1) in;
10663
10664 struct Inner
10665 {
10666 bool b;
10667 bvec2 b2;
10668 bvec3 b3;
10669 bvec4 b4;
10670 bool ba[5];
10671 bvec2 b2a[2][3];
10672 };
10673
10674 struct Outer
10675 {
10676 Inner i[2];
10677 };
10678
10679 layout(std140) uniform Ubo140
10680 {
10681 Outer o;
10682 };
10683
10684 layout(std430, binding = 0) buffer Ubo430
10685 {
10686 Outer o;
10687 } ubo430In;
10688
10689 layout(std140, binding = 1) buffer Ssbo140
10690 {
10691 bool valid;
10692 Inner i;
10693 } ssbo140Out;
10694
10695 layout(std430, binding = 2) buffer Ssbo430
10696 {
10697 bool valid;
10698 Inner i;
10699 };
10700
10701 void writeArgToStd430(bool ba[5])
10702 {
10703 i.ba = ba;
10704 }
10705
10706 bool[5] readFromStd430(uint innerIndex)
10707 {
10708 return ubo430In.o.i[innerIndex].ba;
10709 }
10710
10711 void copyFromStd430(out bvec2 b2a[2][3])
10712 {
10713 b2a = ubo430In.o.i[0].b2a;
10714 }
10715
10716 bool destroyContent(inout Inner iOut)
10717 {
10718 iOut.b = true;
10719 iOut.b2 = bvec2(true);
10720 iOut.b3 = bvec3(true);
10721 iOut.b4 = bvec4(true);
10722 iOut.ba = bool[5](true, true, true, true, true);
10723 bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
10724 iOut.b2a = bvec2[2][3](true3, true3);
10725 return true;
10726 }
10727
10728 void main(){
10729 // Directly copy from one layout to another.
10730 i.b = o.i[0].b;
10731 i.b2 = o.i[0].b2;
10732 i.b2a = o.i[0].b2a;
10733
10734 // Copy to temp with swizzle.
10735 bvec4 t1 = o.i[0].b3.yxzy;
10736 bvec4 t2 = o.i[0].b4.xxyy;
10737 bvec4 t3 = o.i[0].b4.zzww;
10738
10739 // Copy from temp with swizzle.
10740 i.b3 = t1.ywz;
10741 i.b4.yz = bvec2(t2.z, t3.y);
10742 i.b4.wx = bvec2(t3.w, t2.x);
10743
10744 // Copy by passing argument to function.
10745 writeArgToStd430(o.i[0].ba);
10746
10747 // Copy by return value.
10748 ssbo140Out.i.ba = readFromStd430(0u);
10749
10750 // Copy by out parameter.
10751 copyFromStd430(ssbo140Out.i.b2a);
10752
10753 // Logical operations
10754 uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
10755 ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
10756 ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
10757 ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
10758 ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
10759
10760 ssbo140Out.valid = true;
10761 ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
10762 ssbo140Out.valid = ssbo140Out.valid &&
10763 all(notEqual(o.i[1].b4, bvec4(o.i[1].ba[0], o.i[1].ba[1], o.i[1].ba[2], o.i[1].ba[3])));
10764 ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
10765 for (int x = 0; x < o.i[1].b2a.length(); ++x)
10766 {
10767 for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
10768 {
10769 ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
10770 }
10771 }
10772
10773 valid = o.i[1] == ubo430In.o.i[1];
10774
10775 // Make sure short-circuiting behavior is correct.
10776 bool falseVar = !valid && destroyContent(i);
10777 if (falseVar && destroyContent(ssbo140Out.i))
10778 {
10779 valid = false;
10780 }
10781
10782 if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
10783 {
10784 }
10785 else
10786 {
10787 ssbo140Out.valid = false;
10788 }
10789 })";
10790
10791 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
10792 EXPECT_GL_NO_ERROR();
10793
10794 // Test data, laid out with padding (0) based on std140/std430 rules.
10795 // clang-format off
10796 const std::vector<uint32_t> ubo140Data = {
10797 // o.i[0].b (bool)
10798 true, 0,
10799 // o.i[0].b2 (bvec2)
10800 true, false,
10801 // o.i[0].b3 (bvec3)
10802 true, true, false, 0,
10803 // o.i[0].b4 (bvec4)
10804 false, true, false, true,
10805 // o.i[0].ba (bool[5])
10806 true, 0, 0, 0,
10807 false, 0, 0, 0,
10808 false, 0, 0, 0,
10809 true, 0, 0, 0,
10810 true, 0, 0, 0,
10811 // o.i[0].b2a (bool[2][3])
10812 false, true, 0, 0, true, true, 0, 0, true, false, 0, 0,
10813 true, false, 0, 0, false, false, 0, 0, true, true, 0, 0,
10814
10815 // o.i[1].b (bool)
10816 false, 0,
10817 // o.i[1].b2 (bvec2)
10818 true, true,
10819 // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
10820 false, true, true, 0,
10821 // o.i[1].b4 (bvec4)
10822 true, false, true, true,
10823 // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
10824 false, 0, 0, 0,
10825 true, 0, 0, 0,
10826 false, 0, 0, 0,
10827 false, 0, 0, 0,
10828 true, 0, 0, 0,
10829 // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
10830 false, false, 0, 0, false, true, 0, 0, false, false, 0, 0,
10831 true, false, 0, 0, true, true, 0, 0, true, false, 0, 0,
10832 };
10833 const std::vector<uint32_t> ubo430Data = {
10834 // o.i[0].b (bool)
10835 false, 0,
10836 // o.i[0].b2 (bvec2)
10837 true, true,
10838 // o.i[0].b3 (bvec3)
10839 false, false, true, 0,
10840 // o.i[0].b4 (bvec4)
10841 true, false, true, true,
10842 // o.i[0].ba (bool[5])
10843 false, false, false, true, false, 0,
10844 // o.i[0].b2a (bool[2][3])
10845 true, false, true, false, true, true,
10846 false, true, true, true, false, false, 0, 0,
10847
10848 // o.i[1] expected to be equal to ubo140In.o.i[1]
10849 // o.i[1].b (bool)
10850 false, 0,
10851 // o.i[1].b2 (bvec2)
10852 true, true,
10853 // o.i[1].b3 (bvec3)
10854 false, true, true, 0,
10855 // o.i[1].b4 (bvec4)
10856 true, false, true, true,
10857 // o.i[1].ba (bool[5])
10858 false, true, false, false, true, 0,
10859 // o.i[1].b2a (bvec2[2][3])
10860 false, false, false, true, false, false,
10861 true, false, true, true, true, false,
10862 };
10863 const std::vector<uint32_t> ssbo140Expect = {
10864 // valid, expected to be true
10865 true, 0, 0, 0,
10866
10867 // i.b (bool), ubo430In.o.i[0].b ? false : true
10868 true, 0,
10869 // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
10870 false, false,
10871 // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
10872 false, true, false, 0,
10873 // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
10874 true, true, true, false,
10875 // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
10876 false, 0, 0, 0,
10877 false, 0, 0, 0,
10878 false, 0, 0, 0,
10879 true, 0, 0, 0,
10880 false, 0, 0, 0,
10881 // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
10882 true, false, 0, 0, true, false, 0, 0, true, true, 0, 0,
10883 false, true, 0, 0, true, true, 0, 0, false, false, 0, 0,
10884 };
10885 const std::vector<uint32_t> ssbo430Expect = {
10886 // valid, expected to be true
10887 true, 0, 0, 0,
10888
10889 // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
10890 true, 0,
10891 // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
10892 true, false,
10893 // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
10894 true, true, false, 0,
10895 // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
10896 false, true, false, true,
10897 // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
10898 true, false, false, true, true, 0,
10899 // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
10900 false, true, true, true, true, false,
10901 true, false, false, false, true, true, 0, 0,
10902 };
10903 const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
10904 // clang-format on
10905
10906 GLBuffer uboStd140, uboStd430;
10907 GLBuffer ssboStd140, ssboStd430;
10908
10909 InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
10910 static_cast<uint32_t>(ubo140Data.size()), true);
10911 InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
10912 static_cast<uint32_t>(ubo430Data.size()), false);
10913 InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
10914 static_cast<uint32_t>(ssbo140Expect.size()), false);
10915 InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
10916 static_cast<uint32_t>(ssbo430Expect.size()), false);
10917 EXPECT_GL_NO_ERROR();
10918
10919 glUseProgram(program);
10920 glDispatchCompute(1, 1, 1);
10921 EXPECT_GL_NO_ERROR();
10922
10923 EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
10924 static_cast<uint32_t>(ssbo140Expect.size())));
10925 EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
10926 static_cast<uint32_t>(ssbo430Expect.size())));
10927 }
10928
10929 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)10930 TEST_P(GLSLTest_ES3, PreciseNotReserved)
10931 {
10932 // Skip in ES3.1+ as the precise keyword is reserved/core.
10933 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
10934 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
10935
10936 constexpr char kFS[] = R"(#version 300 es
10937 precision mediump float;
10938 in float precise;
10939 out vec4 my_FragColor;
10940 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
10941
10942 constexpr char kVS[] = R"(#version 300 es
10943 in vec4 a_position;
10944 out float precise;
10945 void main() { precise = a_position.x; gl_Position = a_position; })";
10946
10947 GLuint program = CompileProgram(kVS, kFS);
10948 EXPECT_NE(0u, program);
10949 }
10950
10951 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)10952 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
10953 {
10954 // Skip if EXT_gpu_shader5 is enabled.
10955 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10956 // Skip in ES3.2+ as the precise keyword is core.
10957 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
10958 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
10959
10960 constexpr char kFS[] = R"(#version 310 es
10961 precision mediump float;
10962 in float v_varying;
10963 out vec4 my_FragColor;
10964 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
10965
10966 constexpr char kVS[] = R"(#version 310 es
10967 in vec4 a_position;
10968 precise out float v_varying;
10969 void main() { v_varying = a_position.x; gl_Position = a_position; })";
10970
10971 // Should fail, as precise is a reserved keyword when the extension is not enabled.
10972 GLuint program = CompileProgram(kVS, kFS);
10973 EXPECT_EQ(0u, program);
10974 }
10975
10976 // Test that reusing the same variable name for different uses across stages links fine. Glslang
10977 // wrapper's SPIR-V transformation should ignore all names for non-shader-interface variables and
10978 // not get confused by them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)10979 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
10980 {
10981 // Fails to compile the fragment shader with error "undeclared identifier '_g'"
10982 // http://anglebug.com/4404
10983 ANGLE_SKIP_TEST_IF(IsD3D11());
10984
10985 constexpr char kVS[] = R"(#version 310 es
10986 precision mediump float;
10987 uniform highp vec4 a;
10988 in highp vec4 b;
10989 in highp vec4 c;
10990 in highp vec4 d;
10991 out highp vec4 e;
10992
10993 vec4 f(vec4 a)
10994 {
10995 return a;
10996 }
10997
10998 vec4 g(vec4 f)
10999 {
11000 return f + f;
11001 }
11002
11003 void main() {
11004 e = f(b) + a;
11005 gl_Position = g(c) + f(d);
11006 }
11007 )";
11008
11009 constexpr char kFS[] = R"(#version 310 es
11010 precision mediump float;
11011 in highp vec4 e;
11012 uniform sampler2D f;
11013 layout(rgba8) uniform highp readonly image2D g;
11014 uniform A
11015 {
11016 vec4 x;
11017 } c;
11018 layout(std140, binding=0) buffer B
11019 {
11020 vec4 x;
11021 } d[2];
11022 out vec4 col;
11023
11024 vec4 h(vec4 c)
11025 {
11026 return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
11027 }
11028
11029 vec4 i(vec4 x, vec4 y)
11030 {
11031 return vec4(x.xy, y.zw);
11032 }
11033
11034 void main() {
11035 col = h(e) + i(c.x, d[0].x) + d[1].x;
11036 }
11037 )";
11038
11039 GLuint program = CompileProgram(kVS, kFS);
11040 EXPECT_NE(0u, program);
11041 }
11042
11043 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)11044 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
11045 {
11046 constexpr char kVS[] = R"(#version 310 es
11047 precision mediump float;
11048 in highp vec4 variableWithSameName;
11049
11050 void main() {
11051 gl_Position = variableWithSameName;
11052 }
11053 )";
11054
11055 constexpr char kFS[] = R"(#version 310 es
11056 precision mediump float;
11057 uniform vec4 variableWithSameName;
11058 out vec4 col;
11059
11060 void main() {
11061 col = vec4(variableWithSameName);
11062 }
11063 )";
11064
11065 GLuint program = CompileProgram(kVS, kFS);
11066 EXPECT_NE(0u, program);
11067 }
11068
11069 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)11070 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
11071 {
11072 // Nvidia driver bug: http://anglebug.com/5240
11073 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
11074
11075 constexpr char kVSUnused[] = R"(#version 300 es
11076 precision highp float;
11077 uniform highp vec4 positionIn;
11078
11079 void main()
11080 {
11081 gl_Position = vec4(1, 0, 0, 1);
11082 })";
11083
11084 constexpr char kVSStaticUse[] = R"(#version 300 es
11085 precision highp float;
11086 uniform highp vec4 positionIn;
11087
11088 void main()
11089 {
11090 gl_Position = positionIn;
11091 })";
11092
11093 constexpr char kFSUnused[] = R"(#version 300 es
11094 precision highp float;
11095 uniform highp vec4 positionIn;
11096 out vec4 my_FragColor;
11097
11098 void main()
11099 {
11100 my_FragColor = vec4(1, 0, 0, 1);
11101 })";
11102
11103 constexpr char kFSStaticUse[] = R"(#version 300 es
11104 precision highp float;
11105 uniform mediump vec4 positionIn;
11106 out vec4 my_FragColor;
11107
11108 void main()
11109 {
11110 my_FragColor = vec4(1, 0, 0, positionIn.z);
11111 })";
11112
11113 GLuint program = 0;
11114
11115 program = CompileProgram(kVSUnused, kFSUnused);
11116 EXPECT_NE(0u, program);
11117
11118 program = CompileProgram(kVSUnused, kFSStaticUse);
11119 EXPECT_NE(0u, program);
11120
11121 program = CompileProgram(kVSStaticUse, kFSUnused);
11122 EXPECT_NE(0u, program);
11123
11124 program = CompileProgram(kVSStaticUse, kFSStaticUse);
11125 EXPECT_EQ(0u, program);
11126 }
11127
11128 // Validate that link fails when two instanceless interface blocks with different block names but
11129 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)11130 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
11131 {
11132 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11133
11134 constexpr char kVS[] = R"(#version 310 es
11135 in highp vec4 position;
11136 layout(binding = 0) buffer BlockA { mediump float a; };
11137 void main()
11138 {
11139 a = 0.0;
11140 gl_Position = position;
11141 })";
11142
11143 constexpr char kFS[] = R"(#version 310 es
11144 precision mediump float;
11145 layout(location = 0) out mediump vec4 color;
11146 uniform BlockB { float a; };
11147 void main()
11148 {
11149 color = vec4(a, a, a, 1.0);
11150 })";
11151
11152 GLuint program = CompileProgram(kVS, kFS);
11153 EXPECT_EQ(0u, program);
11154 }
11155
11156 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)11157 TEST_P(GLSLTest_ES31, IOBlockLocations)
11158 {
11159 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11160 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
11161
11162 constexpr char kVS[] = R"(#version 310 es
11163 #extension GL_EXT_shader_io_blocks : require
11164
11165 in highp vec4 position;
11166
11167 layout(location = 0) out vec4 aOut;
11168
11169 layout(location = 6) out VSBlock
11170 {
11171 vec4 b; // location 6
11172 vec4 c; // location 7
11173 layout(location = 1) vec4 d;
11174 vec4 e; // location 2
11175 vec4 f[2]; // locations 3 and 4
11176 } blockOut;
11177
11178 layout(location = 5) out vec4 gOut;
11179
11180 void main()
11181 {
11182 aOut = vec4(0.03, 0.06, 0.09, 0.12);
11183 blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
11184 blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
11185 blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
11186 blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
11187 blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
11188 blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
11189 gOut = vec4(0.84, 0.87, 0.9, 0.93);
11190 gl_Position = position;
11191 })";
11192
11193 constexpr char kGS[] = R"(#version 310 es
11194 #extension GL_EXT_geometry_shader : require
11195 layout (triangles) in;
11196 layout (triangle_strip, max_vertices = 3) out;
11197
11198 // Input varyings
11199 layout(location = 0) in vec4 aIn[];
11200
11201 layout(location = 6) in VSBlock
11202 {
11203 vec4 b;
11204 vec4 c;
11205 layout(location = 1) vec4 d;
11206 vec4 e;
11207 vec4 f[2];
11208 } blockIn[];
11209
11210 layout(location = 5) in vec4 gIn[];
11211
11212 // Output varyings
11213 layout(location = 1) out vec4 aOut;
11214
11215 layout(location = 0) out GSBlock
11216 {
11217 vec4 b; // location 0
11218 layout(location = 3) vec4 c;
11219 layout(location = 7) vec4 d;
11220 layout(location = 5) vec4 e[2];
11221 layout(location = 4) vec4 f;
11222 } blockOut;
11223
11224 layout(location = 2) out vec4 gOut;
11225
11226 void main()
11227 {
11228 int n;
11229 for (n = 0; n < gl_in.length(); n++)
11230 {
11231 gl_Position = gl_in[n].gl_Position;
11232
11233 aOut = aIn[n];
11234 blockOut.b = blockIn[n].b;
11235 blockOut.c = blockIn[n].c;
11236 blockOut.d = blockIn[n].d;
11237 blockOut.e[0] = blockIn[n].e;
11238 blockOut.e[1] = blockIn[n].f[0];
11239 blockOut.f = blockIn[n].f[1];
11240 gOut = gIn[n];
11241
11242 EmitVertex();
11243 }
11244 EndPrimitive();
11245 })";
11246
11247 constexpr char kFS[] = R"(#version 310 es
11248 #extension GL_EXT_shader_io_blocks : require
11249 precision mediump float;
11250
11251 layout(location = 0) out mediump vec4 color;
11252
11253 layout(location = 1) in vec4 aIn;
11254
11255 layout(location = 0) in GSBlock
11256 {
11257 vec4 b;
11258 layout(location = 3) vec4 c;
11259 layout(location = 7) vec4 d;
11260 layout(location = 5) vec4 e[2];
11261 layout(location = 4) vec4 f;
11262 } blockIn;
11263
11264 layout(location = 2) in vec4 gIn;
11265
11266 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
11267
11268 void main()
11269 {
11270 bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
11271 bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
11272 isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
11273 isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
11274 isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
11275 isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
11276 isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
11277 bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
11278
11279 color = vec4(passR, passG, passB, 1.0);
11280 })";
11281
11282 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
11283 EXPECT_GL_NO_ERROR();
11284
11285 GLTexture color;
11286 glBindTexture(GL_TEXTURE_2D, color);
11287 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
11288
11289 GLFramebuffer fbo;
11290 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
11291 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
11292
11293 drawQuad(program, "position", 0);
11294
11295 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
11296 }
11297
11298 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)11299 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
11300 {
11301 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11302
11303 constexpr char kVS[] = R"(#version 310 es
11304 #extension GL_EXT_shader_io_blocks : require
11305
11306 in highp vec4 position;
11307
11308 out VSBlock1
11309 {
11310 vec4 a;
11311 vec4 b[2];
11312 } blockOut1;
11313
11314 out VSBlock2
11315 {
11316 vec4 c[2];
11317 vec4 d;
11318 } blockOut2;
11319
11320 void main()
11321 {
11322 blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
11323 blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
11324 blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
11325 blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
11326 blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
11327 blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
11328 gl_Position = position;
11329 })";
11330
11331 constexpr char kFS[] = R"(#version 310 es
11332 #extension GL_EXT_shader_io_blocks : require
11333 precision mediump float;
11334
11335 layout(location = 0) out mediump vec4 color;
11336
11337 in VSBlock1
11338 {
11339 vec4 a;
11340 vec4 b[2];
11341 } blockIn1;
11342
11343 in VSBlock2
11344 {
11345 vec4 c[2];
11346 vec4 d;
11347 } blockIn2;
11348
11349 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
11350
11351 void main()
11352 {
11353 bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
11354 bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
11355 isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
11356 bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
11357 isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
11358 bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
11359
11360 color = vec4(passR, passG, passB, passA);
11361 })";
11362
11363 ANGLE_GL_PROGRAM(program, kVS, kFS);
11364 EXPECT_GL_NO_ERROR();
11365
11366 GLTexture color;
11367 glBindTexture(GL_TEXTURE_2D, color);
11368 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
11369
11370 GLFramebuffer fbo;
11371 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
11372 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
11373
11374 drawQuad(program, "position", 0);
11375
11376 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
11377 }
11378
11379 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)11380 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
11381 {
11382 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11383
11384 constexpr char kVS[] = R"(#version 310 es
11385 #extension GL_EXT_shader_io_blocks : require
11386 in highp vec4 position;
11387 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11388 void main()
11389 {
11390 blockOut1.a = vec4(0);
11391 blockOut1.b[0] = vec4(0);
11392 blockOut1.b[1] = vec4(0);
11393 gl_Position = position;
11394 })";
11395
11396 constexpr char kFS[] = R"(#version 310 es
11397 #extension GL_EXT_shader_io_blocks : require
11398 precision mediump float;
11399 layout(location = 0) out mediump vec4 color;
11400 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
11401 void main()
11402 {
11403 color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11404 })";
11405
11406 GLuint program = CompileProgram(kVS, kFS);
11407 EXPECT_EQ(0u, program);
11408 }
11409
11410 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)11411 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
11412 {
11413 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11414
11415 constexpr char kVS[] = R"(#version 310 es
11416 #extension GL_EXT_shader_io_blocks : require
11417 in highp vec4 position;
11418 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11419 void main()
11420 {
11421 blockOut1.a = vec4(0);
11422 blockOut1.b[0] = vec4(0);
11423 blockOut1.b[1] = vec4(0);
11424 gl_Position = position;
11425 })";
11426
11427 constexpr char kFS[] = R"(#version 310 es
11428 #extension GL_EXT_shader_io_blocks : require
11429 precision mediump float;
11430 layout(location = 0) out mediump vec4 color;
11431 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
11432 void main()
11433 {
11434 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11435 })";
11436
11437 GLuint program = CompileProgram(kVS, kFS);
11438 EXPECT_EQ(0u, program);
11439 }
11440
11441 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)11442 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
11443 {
11444 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11445
11446 constexpr char kVS[] = R"(#version 310 es
11447 #extension GL_EXT_shader_io_blocks : require
11448 in highp vec4 position;
11449 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11450 void main()
11451 {
11452 blockOut1.a = vec4(0);
11453 blockOut1.b[0] = vec4(0);
11454 blockOut1.b[1] = vec4(0);
11455 gl_Position = position;
11456 })";
11457
11458 constexpr char kFS[] = R"(#version 310 es
11459 #extension GL_EXT_shader_io_blocks : require
11460 precision mediump float;
11461 layout(location = 0) out mediump vec4 color;
11462 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
11463 void main()
11464 {
11465 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11466 })";
11467
11468 GLuint program = CompileProgram(kVS, kFS);
11469 EXPECT_EQ(0u, program);
11470 }
11471
11472 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)11473 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
11474 {
11475 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11476
11477 constexpr char kVS[] = R"(#version 310 es
11478 #extension GL_EXT_shader_io_blocks : require
11479 in highp vec4 position;
11480 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
11481 void main()
11482 {
11483 blockOut1.a = vec4(0);
11484 blockOut1.b[0] = vec4(0);
11485 blockOut1.b[1] = vec4(0);
11486 gl_Position = position;
11487 })";
11488
11489 constexpr char kFS[] = R"(#version 310 es
11490 #extension GL_EXT_shader_io_blocks : require
11491 precision mediump float;
11492 layout(location = 0) out mediump vec4 color;
11493 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
11494 void main()
11495 {
11496 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11497 })";
11498
11499 GLuint program = CompileProgram(kVS, kFS);
11500 EXPECT_EQ(0u, program);
11501 }
11502
11503 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)11504 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
11505 {
11506 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11507
11508 constexpr char kVS[] = R"(#version 310 es
11509 #extension GL_EXT_shader_io_blocks : require
11510 in highp vec4 position;
11511 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
11512 void main()
11513 {
11514 blockOut1.a = vec4(0);
11515 blockOut1.b[0] = vec4(0);
11516 blockOut1.b[1] = vec4(0);
11517 gl_Position = position;
11518 })";
11519
11520 constexpr char kFS[] = R"(#version 310 es
11521 #extension GL_EXT_shader_io_blocks : require
11522 precision mediump float;
11523 layout(location = 0) out mediump vec4 color;
11524 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
11525 void main()
11526 {
11527 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
11528 })";
11529
11530 GLuint program = CompileProgram(kVS, kFS);
11531 EXPECT_EQ(0u, program);
11532 }
11533
11534 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)11535 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
11536 {
11537 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11538
11539 constexpr char kVS[] = R"(#version 310 es
11540 #extension GL_EXT_shader_io_blocks : require
11541 in highp vec4 position;
11542 struct S1 { vec4 a; vec4 b[2]; };
11543 out VSBlock { S1 s; } blockOut1;
11544 void main()
11545 {
11546 blockOut1.s.a = vec4(0);
11547 blockOut1.s.b[0] = vec4(0);
11548 blockOut1.s.b[1] = vec4(0);
11549 gl_Position = position;
11550 })";
11551
11552 constexpr char kFS[] = R"(#version 310 es
11553 #extension GL_EXT_shader_io_blocks : require
11554 precision mediump float;
11555 layout(location = 0) out mediump vec4 color;
11556 struct S2 { vec4 a; vec4 b[2]; };
11557 in VSBlock { S2 s; } blockIn1;
11558 void main()
11559 {
11560 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11561 })";
11562
11563 GLuint program = CompileProgram(kVS, kFS);
11564 EXPECT_EQ(0u, program);
11565 }
11566
11567 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)11568 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
11569 {
11570 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11571
11572 constexpr char kVS[] = R"(#version 310 es
11573 #extension GL_EXT_shader_io_blocks : require
11574 in highp vec4 position;
11575 struct S { vec4 c; vec4 b[2]; };
11576 out VSBlock { S s; } blockOut1;
11577 void main()
11578 {
11579 blockOut1.s.c = vec4(0);
11580 blockOut1.s.b[0] = vec4(0);
11581 blockOut1.s.b[1] = vec4(0);
11582 gl_Position = position;
11583 })";
11584
11585 constexpr char kFS[] = R"(#version 310 es
11586 #extension GL_EXT_shader_io_blocks : require
11587 precision mediump float;
11588 layout(location = 0) out mediump vec4 color;
11589 struct S { vec4 a; vec4 b[2]; };
11590 in VSBlock { S s; } blockIn1;
11591 void main()
11592 {
11593 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11594 })";
11595
11596 GLuint program = CompileProgram(kVS, kFS);
11597 EXPECT_EQ(0u, program);
11598 }
11599
11600 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)11601 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
11602 {
11603 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11604
11605 constexpr char kVS[] = R"(#version 310 es
11606 #extension GL_EXT_shader_io_blocks : require
11607 in highp vec4 position;
11608 struct S { vec4 a; vec4 b[2]; };
11609 out VSBlock { S s; } blockOut1;
11610 void main()
11611 {
11612 blockOut1.s.a = vec4(0);
11613 blockOut1.s.b[0] = vec4(0);
11614 blockOut1.s.b[1] = vec4(0);
11615 gl_Position = position;
11616 })";
11617
11618 constexpr char kFS[] = R"(#version 310 es
11619 #extension GL_EXT_shader_io_blocks : require
11620 precision mediump float;
11621 layout(location = 0) out mediump vec4 color;
11622 struct S { vec3 a; vec4 b[2]; };
11623 in VSBlock { S s; } blockIn1;
11624 void main()
11625 {
11626 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11627 })";
11628
11629 GLuint program = CompileProgram(kVS, kFS);
11630 EXPECT_EQ(0u, program);
11631 }
11632
11633 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)11634 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
11635 {
11636 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11637
11638 constexpr char kVS[] = R"(#version 310 es
11639 #extension GL_EXT_shader_io_blocks : require
11640 in highp vec4 position;
11641 struct S { vec4 a; vec4 b[3]; };
11642 out VSBlock { S s; } blockOut1;
11643 void main()
11644 {
11645 blockOut1.s.a = vec4(0);
11646 blockOut1.s.b[0] = vec4(0);
11647 blockOut1.s.b[1] = vec4(0);
11648 gl_Position = position;
11649 })";
11650
11651 constexpr char kFS[] = R"(#version 310 es
11652 #extension GL_EXT_shader_io_blocks : require
11653 precision mediump float;
11654 layout(location = 0) out mediump vec4 color;
11655 struct S { vec4 a; vec4 b[2]; };
11656 in VSBlock { S s; } blockIn1;
11657 void main()
11658 {
11659 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11660 })";
11661
11662 GLuint program = CompileProgram(kVS, kFS);
11663 EXPECT_EQ(0u, program);
11664 }
11665
11666 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)11667 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
11668 {
11669 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11670
11671 constexpr char kVS[] = R"(#version 310 es
11672 #extension GL_EXT_shader_io_blocks : require
11673 in highp vec4 position;
11674 struct S { vec4 a; vec4 b[2]; vec4 c; };
11675 out VSBlock { S s; } blockOut1;
11676 void main()
11677 {
11678 blockOut1.s.c = vec4(0);
11679 blockOut1.s.b[0] = vec4(0);
11680 blockOut1.s.b[1] = vec4(0);
11681 gl_Position = position;
11682 })";
11683
11684 constexpr char kFS[] = R"(#version 310 es
11685 #extension GL_EXT_shader_io_blocks : require
11686 precision mediump float;
11687 layout(location = 0) out mediump vec4 color;
11688 struct S { vec4 a; vec4 b[2]; };
11689 in VSBlock { S s; } blockIn1;
11690 void main()
11691 {
11692 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
11693 })";
11694
11695 GLuint program = CompileProgram(kVS, kFS);
11696 EXPECT_EQ(0u, program);
11697 }
11698
11699 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)11700 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
11701 {
11702 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
11703
11704 constexpr char kVS[] = R"(#version 310 es
11705 #extension GL_EXT_shader_io_blocks : require
11706 in highp vec4 position;
11707 struct S1 { vec4 c; vec4 b[2]; };
11708 struct S2 { S1 s; };
11709 struct S3 { S2 s; };
11710 out VSBlock { S3 s; } blockOut1;
11711 void main()
11712 {
11713 blockOut1.s.s.s.c = vec4(0);
11714 blockOut1.s.s.s.b[0] = vec4(0);
11715 blockOut1.s.s.s.b[1] = vec4(0);
11716 gl_Position = position;
11717 })";
11718
11719 constexpr char kFS[] = R"(#version 310 es
11720 #extension GL_EXT_shader_io_blocks : require
11721 precision mediump float;
11722 layout(location = 0) out mediump vec4 color;
11723 struct S1 { vec4 a; vec4 b[2]; };
11724 struct S2 { S1 s; };
11725 struct S3 { S2 s; };
11726 in VSBlock { S3 s; } blockIn1;
11727 void main()
11728 {
11729 color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
11730 })";
11731
11732 GLuint program = CompileProgram(kVS, kFS);
11733 EXPECT_EQ(0u, program);
11734 }
11735
11736 // Regression test for transformation bug which separates struct declarations from uniform
11737 // declarations. The bug was that the uniform variable usage in the initializer of a new
11738 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)11739 TEST_P(GLSLTest, UniformStructBug)
11740 {
11741 constexpr char kVS[] = R"(precision highp float;
11742
11743 uniform struct Global
11744 {
11745 float x;
11746 } u_global;
11747
11748 void main() {
11749 float y = u_global.x;
11750
11751 gl_Position = vec4(y);
11752 })";
11753
11754 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
11755
11756 const char *sourceArray[1] = {kVS};
11757 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
11758 glShaderSource(shader, 1, sourceArray, lengths);
11759 glCompileShader(shader);
11760
11761 GLint compileResult;
11762 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
11763 EXPECT_NE(compileResult, 0);
11764 }
11765
11766 // Regression test for transformation bug which separates struct declarations from uniform
11767 // declarations. The bug was that the arrayness of the declaration was not being applied to the
11768 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)11769 TEST_P(GLSLTest_ES31, UniformStructBug2)
11770 {
11771 constexpr char kVS[] = R"(#version 310 es
11772 precision highp float;
11773
11774 uniform struct Global
11775 {
11776 float x;
11777 } u_global[2][3];
11778
11779 void main() {
11780 float y = u_global[0][0].x;
11781
11782 gl_Position = vec4(y);
11783 })";
11784
11785 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
11786
11787 const char *sourceArray[1] = {kVS};
11788 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
11789 glShaderSource(shader, 1, sourceArray, lengths);
11790 glCompileShader(shader);
11791
11792 GLint compileResult;
11793 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
11794 EXPECT_NE(compileResult, 0);
11795 }
11796
11797 // Test that providing more components to a matrix constructor than necessary works. Based on a
11798 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)11799 TEST_P(GLSLTest, MatrixConstructor)
11800 {
11801 constexpr char kVS[] = R"(attribute vec4 aPosition;
11802 varying vec4 vColor;
11803 void main()
11804 {
11805 gl_Position = aPosition;
11806 vec4 color = vec4(aPosition.xy, 0, 1);
11807 mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
11808 vColor = m4[0];
11809 })";
11810
11811 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
11812 EXPECT_NE(0u, shader);
11813 glDeleteShader(shader);
11814 }
11815
11816 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)11817 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
11818 {
11819 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
11820
11821 constexpr char kVS[] = R"(#version 300 es
11822 #extension GL_EXT_shader_non_constant_global_initializers : require
11823 uniform vec4 u;
11824 out vec4 color;
11825
11826 vec4 global1 = u;
11827 vec4 global2 = u + vec4(1);
11828 vec4 global3 = global1 * global2;
11829 void main()
11830 {
11831 color = global3;
11832 })";
11833
11834 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
11835 EXPECT_NE(0u, shader);
11836 glDeleteShader(shader);
11837 }
11838
11839 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)11840 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
11841 {
11842 constexpr char kFS[] = R"(#version 300 es
11843 precision highp float;
11844 out vec4 color;
11845
11846 struct T
11847 {
11848 float f;
11849 };
11850
11851 struct S
11852 {
11853 vec4 v;
11854 mat3x4 m[2];
11855 T t;
11856 };
11857
11858 S s = S(
11859 vec4(0, 1, 2, 3),
11860 mat3x4[2](
11861 mat3x4(
11862 vec4(4, 5, 6, 7),
11863 vec4(8, 9, 10, 11),
11864 vec4(12, 13, 14, 15)
11865 ),
11866 mat3x4(
11867 vec4(16, 17, 18, 19),
11868 vec4(20, 21, 22, 23),
11869 vec4(24, 25, 26, 27)
11870 )
11871 ),
11872 T(28.0)
11873 );
11874
11875 void main()
11876 {
11877 vec4 result = vec4(0, 1, 0, 1);
11878
11879 if (s.v != vec4(0, 1, 2, 3))
11880 result = vec4(1, 0, 0, 0);
11881
11882 for (int index = 0; index < 2; ++index)
11883 {
11884 for (int column = 0; column < 3; ++column)
11885 {
11886 int expect = index * 12 + column * 4 + 4;
11887 if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
11888 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
11889 }
11890 }
11891
11892 if (s.t.f != 28.0)
11893 result = vec4(0, 0, 1, 0);
11894
11895 color = result;
11896 })";
11897
11898 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11899
11900 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11901 EXPECT_GL_NO_ERROR();
11902
11903 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11904 }
11905
11906 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)11907 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
11908 {
11909 constexpr char kFS[] = R"(#version 310 es
11910 precision highp float;
11911 precision highp int;
11912
11913 out vec4 color;
11914
11915 uniform float f; // = 3.41
11916 uniform uvec4 u1; // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
11917 uniform uvec4 u2; // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
11918
11919 struct S
11920 {
11921 float fvalue;
11922 int ivalues[2];
11923 uvec4 uvalues[3];
11924 };
11925
11926 struct T
11927 {
11928 S s[2];
11929 };
11930
11931 void main()
11932 {
11933 float integer;
11934 float fraction = modf(f, integer);
11935
11936 T t;
11937
11938 t.s[0].fvalue = frexp(f, t.s[0].ivalues[0]);
11939 float significand = t.s[0].fvalue;
11940 int exponent = t.s[0].ivalues[0];
11941
11942 t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
11943 uvec4 addResult = t.s[0].uvalues[0];
11944 uvec4 addCarry = t.s[0].uvalues[1].yxwz;
11945
11946 t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
11947 uvec2 subResult = t.s[0].uvalues[2].wx;
11948 uvec2 subBorrow = t.s[1].uvalues[0].wx;
11949
11950 umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
11951 uvec4 mulMsb = t.s[1].uvalues[1];
11952 uvec4 mulLsb = t.s[1].uvalues[2];
11953
11954 ivec2 imulMsb, imulLsb;
11955 imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
11956
11957 bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
11958 bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
11959 bool addPassed =
11960 addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
11961 addCarry == uvec4(1, 0, 1, 0);
11962 bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
11963 bool mulPassed =
11964 mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
11965 mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
11966 bool imulPassed =
11967 imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
11968 imulLsb == ivec2(0x35068740, 0x822E97E0);
11969
11970 color = vec4(modfPassed ? 1 : 0,
11971 frexpPassed ? 1 : 0,
11972 (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
11973 (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
11974 })";
11975
11976 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
11977 glUseProgram(program);
11978
11979 GLint floc = glGetUniformLocation(program, "f");
11980 GLint u1loc = glGetUniformLocation(program, "u1");
11981 GLint u2loc = glGetUniformLocation(program, "u2");
11982 ASSERT_NE(floc, -1);
11983 ASSERT_NE(u1loc, -1);
11984 ASSERT_NE(u2loc, -1);
11985 glUniform1f(floc, 3.41);
11986 glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
11987 glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
11988
11989 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
11990 EXPECT_GL_NO_ERROR();
11991
11992 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
11993 }
11994
11995 // Test that interpolateAt* work with swizzle. This test is disabled as swizzled interpolants are
11996 // only allowed in desktop GLSL.
TEST_P(GLSLTest_ES31,InterpolateAtWithSwizzle)11997 TEST_P(GLSLTest_ES31, InterpolateAtWithSwizzle)
11998 {
11999 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
12000
12001 constexpr char kVS[] = R"(#version 310 es
12002
12003 out vec4 interpolant;
12004
12005 void main()
12006 {
12007 // The following triangle is being drawn over the framebuffer.
12008 //
12009 // (-1,3) |\
12010 // | \
12011 // | \
12012 // | \
12013 // | \
12014 // +--------------+
12015 // | | \
12016 // | | \
12017 // | Framebuffer | \
12018 // | | \
12019 // | | \
12020 // (-1,-1) +--------------+--------------- (3,-1)
12021 //
12022 // Interpolant is set such that interpolateAtCentroid would produce the desired value for
12023 // position == (0, 0), and interpolateAtOffset(0.5, -0.5) for position == (1,-1)
12024 if (gl_VertexID == 0)
12025 {
12026 gl_Position = vec4(-1, -1, 0, 1);
12027 interpolant = vec4(1.5, 0.5, 0, 0);
12028 }
12029 else if (gl_VertexID == 1)
12030 {
12031 gl_Position = vec4(3, -1, 0, 1);
12032 interpolant = vec4(0, 0, 1, 2);
12033 }
12034 else
12035 {
12036 gl_Position = vec4(-1, 3, 0, 1);
12037 interpolant = vec4(0, 1, -1, 2);
12038 }
12039 })";
12040
12041 constexpr char kFS[] = R"(#version 310 es
12042 #extension GL_OES_shader_multisample_interpolation : require
12043 precision highp float;
12044
12045 in vec4 interpolant;
12046 out vec4 color;
12047
12048 void main()
12049 {
12050 // Should result in (0.75, 1.0)
12051 vec2 atCentroid = interpolateAtCentroid(interpolant.xw);
12052 // Selecting the bottom-right corner, this should result in (0.5, 0.25), but interpolateAtOffset
12053 // doesn't make guarantees regarding the range and granularity of the offset. The interpolant
12054 // is given values such that the bottom-left/top-right diagonal is interpolated to a constant
12055 // value of (0, 0.5). The top-left corner has the value (-0.5, 0.75). We therefore make a
12056 // coarse test to make sure that atOffset.x > 0 and atOffset.y < 0.5, thus ensuring at least
12057 // that the offset is in the correct half of the pixel.
12058 vec2 atOffset = interpolateAtOffset(interpolant.zy, vec2(0.5, -0.5));
12059
12060 color = vec4(atCentroid, atOffset.x > 0.0 ? 1 : 0, atOffset.y < 0.5 ? 1 : 0);
12061 })";
12062
12063 GLRenderbuffer rbo;
12064 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
12065 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
12066
12067 GLFramebuffer fbo;
12068 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12069 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
12070 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12071
12072 ANGLE_GL_PROGRAM(program, kVS, kFS);
12073 glUseProgram(program);
12074
12075 glViewport(0, 0, 1, 1);
12076 glDrawArrays(GL_TRIANGLES, 0, 3);
12077 EXPECT_GL_NO_ERROR();
12078
12079 EXPECT_PIXEL_NEAR(0, 0, 191, 255, 255, 255, 1);
12080 }
12081
12082 class GLSLTestLoops : public GLSLTest
12083 {
12084 protected:
runTest(const char * fs)12085 void runTest(const char *fs)
12086 {
12087 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
12088
12089 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12090 EXPECT_GL_NO_ERROR();
12091
12092 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12093 }
12094 };
12095
12096 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)12097 TEST_P(GLSLTestLoops, BasicFor)
12098 {
12099 constexpr char kFS[] = R"(#version 300 es
12100 precision mediump float;
12101 out vec4 color;
12102
12103 void main()
12104 {
12105 int result = 0;
12106 for (int i = 0; i < 10; ++i)
12107 for (int j = 0; j < 8; ++j)
12108 {
12109 for (int k = 0; k < 2; ++k, ++j) ++result;
12110 for (int k = 0; k < 3; ++k) ++result;
12111 for (int k = 0; k < 0; ++k) ++result;
12112 }
12113
12114 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12115 })";
12116
12117 runTest(kFS);
12118 }
12119
12120 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)12121 TEST_P(GLSLTestLoops, ForNoCondition)
12122 {
12123 constexpr char kFS[] = R"(#version 300 es
12124 precision mediump float;
12125 out vec4 color;
12126
12127 void main()
12128 {
12129 int result = 0;
12130 for (int i = 0; i < 10; ++i)
12131 for (int j = 0; ; ++j)
12132 {
12133 for (int k = 0; k < 2; ++k, ++j) ++result;
12134 for (int k = 0; k < 3; ++k) ++result;
12135 for (int k = 0; k < 0; ++k) ++result;
12136
12137 if (j >= 8)
12138 break;
12139 }
12140
12141 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12142 })";
12143
12144 runTest(kFS);
12145 }
12146
12147 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)12148 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
12149 {
12150 constexpr char kFS[] = R"(#version 300 es
12151 precision mediump float;
12152 out vec4 color;
12153
12154 void main()
12155 {
12156 int result = 0;
12157 for (int i = 0; i < 10; ++i)
12158 {
12159 int j = 0;
12160 for (;;)
12161 {
12162 for (int k = 0; k < 2; ++k, ++j) ++result;
12163 for (int k = 0; k < 3; ++k) ++result;
12164 for (int k = 0; k < 0; ++k) ++result;
12165
12166 if (j >= 8)
12167 break;
12168 ++j;
12169 }
12170 }
12171
12172 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12173 })";
12174
12175 runTest(kFS);
12176 }
12177
12178 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)12179 TEST_P(GLSLTestLoops, ForContinue)
12180 {
12181 constexpr char kFS[] = R"(#version 300 es
12182 precision mediump float;
12183 out vec4 color;
12184
12185 void main()
12186 {
12187 int result = 0;
12188 for (int i = 0; i < 10; ++i)
12189 for (int j = 0; j < 8; ++j)
12190 {
12191 for (int k = 0; k < 2; ++k, ++j) ++result;
12192 for (int k = 0; k < 3; ++k) ++result;
12193 if (i > 3)
12194 continue;
12195 for (int k = 0; k < 0; ++k) ++result;
12196 }
12197
12198 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12199 })";
12200
12201 runTest(kFS);
12202 }
12203
12204 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)12205 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
12206 {
12207 constexpr char kFS[] = R"(#version 300 es
12208 precision mediump float;
12209 out vec4 color;
12210
12211 void main()
12212 {
12213 int result = 0;
12214 for (int i = 0; i < 10; ++i)
12215 for (int j = 0; j < 8; ++j)
12216 {
12217 for (int k = 0; k < 2; ++k, ++j) ++result;
12218 for (int k = 0; k < 3; ++k) ++result;
12219 for (int k = 0; k < 0; ++k) ++result;
12220 continue;
12221 }
12222
12223 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12224 })";
12225
12226 runTest(kFS);
12227 }
12228
12229 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)12230 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
12231 {
12232 constexpr char kFS[] = R"(#version 300 es
12233 precision mediump float;
12234 out vec4 color;
12235
12236 void main()
12237 {
12238 int result = 0;
12239 for (int i = 0; i < 10; ++i)
12240 for (int j = 0; j < 8; ++j)
12241 {
12242 for (int k = 0; k < 2; ++k, ++j) ++result;
12243 for (int k = 0; k < 3; ++k) ++result;
12244 for (int k = 0; k < 0; ++k) ++result;
12245 break;
12246 }
12247
12248 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12249 })";
12250
12251 runTest(kFS);
12252 }
12253
12254 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)12255 TEST_P(GLSLTestLoops, ForBreakContinue)
12256 {
12257 constexpr char kFS[] = R"(#version 300 es
12258 precision mediump float;
12259 out vec4 color;
12260
12261 void main()
12262 {
12263 int result = 0;
12264 for (int i = 0; i < 10; ++i)
12265 for (int j = 0; j < 8; ++j)
12266 {
12267 if (j < 2) continue;
12268 if (j > 6) break;
12269 if (i < 3) continue;
12270 if (i > 8) break;
12271 ++result;
12272 }
12273
12274 color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12275 })";
12276
12277 runTest(kFS);
12278 }
12279
12280 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)12281 TEST_P(GLSLTestLoops, BasicWhile)
12282 {
12283 constexpr char kFS[] = R"(#version 300 es
12284 precision mediump float;
12285 out vec4 color;
12286
12287 void main()
12288 {
12289 int result = 0;
12290 int i = 0;
12291 while (i < 10)
12292 {
12293 int j = 0;
12294 while (j < 8)
12295 {
12296 int k = 0;
12297 while (k < 2) { ++result; ++k; ++j; }
12298 while (k < 5) { ++result; ++k; }
12299 while (k < 4) { ++result; }
12300 ++j;
12301 }
12302 ++i;
12303 }
12304
12305 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12306 })";
12307
12308 runTest(kFS);
12309 }
12310
12311 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)12312 TEST_P(GLSLTestLoops, WhileContinue)
12313 {
12314 constexpr char kFS[] = R"(#version 300 es
12315 precision mediump float;
12316 out vec4 color;
12317
12318 void main()
12319 {
12320 int result = 0;
12321 int i = 0;
12322 while (i < 10)
12323 {
12324 int j = 0;
12325 while (j < 8)
12326 {
12327 int k = 0;
12328 while (k < 2) { ++result; ++k; ++j; }
12329 while (k < 5) { ++result; ++k; }
12330 if (i > 3)
12331 {
12332 ++j;
12333 continue;
12334 }
12335 while (k < 4) { ++result; }
12336 ++j;
12337 }
12338 ++i;
12339 }
12340
12341 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12342 })";
12343
12344 runTest(kFS);
12345 }
12346
12347 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)12348 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
12349 {
12350 constexpr char kFS[] = R"(#version 300 es
12351 precision mediump float;
12352 out vec4 color;
12353
12354 void main()
12355 {
12356 int result = 0;
12357 int i = 0;
12358 while (i < 10)
12359 {
12360 int j = 0;
12361 while (j < 8)
12362 {
12363 int k = 0;
12364 while (k < 2) { ++result; ++k; ++j; }
12365 while (k < 5) { ++result; ++k; }
12366 while (k < 4) { ++result; }
12367 ++j;
12368 continue;
12369 }
12370 ++i;
12371 }
12372
12373 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12374 })";
12375
12376 runTest(kFS);
12377 }
12378
12379 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)12380 TEST_P(GLSLTestLoops, WhileBreak)
12381 {
12382 constexpr char kFS[] = R"(#version 300 es
12383 precision mediump float;
12384 out vec4 color;
12385
12386 void main()
12387 {
12388 int result = 0;
12389 int i = 0;
12390 while (i < 10)
12391 {
12392 int j = 0;
12393 while (true)
12394 {
12395 int k = 0;
12396 while (k < 2) { ++result; ++k; ++j; }
12397 while (k < 5) { ++result; ++k; }
12398 while (k < 4) { ++result; }
12399 ++j;
12400 if (j >= 8)
12401 break;
12402 }
12403 ++i;
12404 }
12405
12406 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12407 })";
12408
12409 runTest(kFS);
12410 }
12411
12412 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)12413 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
12414 {
12415 constexpr char kFS[] = R"(#version 300 es
12416 precision mediump float;
12417 out vec4 color;
12418
12419 void main()
12420 {
12421 int result = 0;
12422 int i = 0;
12423 while (i < 10)
12424 {
12425 int j = 0;
12426 while (j < 8)
12427 {
12428 int k = 0;
12429 while (k < 2) { ++result; ++k; ++j; }
12430 while (k < 5) { ++result; ++k; }
12431 while (k < 4) { ++result; }
12432 ++j;
12433 break;
12434 }
12435 ++i;
12436 }
12437
12438 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12439 })";
12440
12441 runTest(kFS);
12442 }
12443
12444 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)12445 TEST_P(GLSLTestLoops, BasicDoWhile)
12446 {
12447 constexpr char kFS[] = R"(#version 300 es
12448 precision mediump float;
12449 out vec4 color;
12450
12451 void main()
12452 {
12453 int result = 0;
12454 int i = 0;
12455 do
12456 {
12457 int j = 0;
12458 do
12459 {
12460 int k = 0;
12461 do { ++result; ++k; ++j; } while (k < 2);
12462 do { ++result; ++k; } while (k < 5);
12463 do { ++result; } while (k < 3);
12464 ++j;
12465 } while (j < 8);
12466 ++i;
12467 } while (i < 10);
12468
12469 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12470 })";
12471
12472 runTest(kFS);
12473 }
12474
12475 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)12476 TEST_P(GLSLTestLoops, DoWhileContinue)
12477 {
12478 constexpr char kFS[] = R"(#version 300 es
12479 precision mediump float;
12480 out vec4 color;
12481
12482 void main()
12483 {
12484 int result = 0;
12485 int i = 0;
12486 do
12487 {
12488 int j = 0;
12489 do
12490 {
12491 int k = 0;
12492 do { ++result; ++k; ++j; } while (k < 2);
12493 if (i > 3)
12494 {
12495 ++j;
12496 continue;
12497 }
12498 do { ++result; ++k; } while (k < 5);
12499 do { ++result; } while (k < 3);
12500 ++j;
12501 } while (j < 8);
12502 ++i;
12503 } while (i < 10);
12504
12505 color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12506 })";
12507
12508 runTest(kFS);
12509 }
12510
12511 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)12512 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
12513 {
12514 constexpr char kFS[] = R"(#version 300 es
12515 precision mediump float;
12516 out vec4 color;
12517
12518 void main()
12519 {
12520 int result = 0;
12521 int i = 0;
12522 do
12523 {
12524 int j = 0;
12525 do
12526 {
12527 int k = 0;
12528 do { ++result; ++k; ++j; continue; } while (k < 2);
12529 do { ++result; ++k; continue; } while (k < 5);
12530 do { ++result; continue; } while (k < 3);
12531 ++j;
12532 } while (j < 8);
12533 ++i;
12534 } while (i < 10);
12535
12536 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12537 })";
12538
12539 runTest(kFS);
12540 }
12541
12542 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)12543 TEST_P(GLSLTestLoops, DoWhileBreak)
12544 {
12545 constexpr char kFS[] = R"(#version 300 es
12546 precision mediump float;
12547 out vec4 color;
12548
12549 void main()
12550 {
12551 int result = 0;
12552 int i = 0;
12553 do
12554 {
12555 int j = 0;
12556 do
12557 {
12558 int k = 0;
12559 do { ++result; ++k; ++j; } while (k < 2);
12560 do { ++result; ++k; } while (k < 5);
12561 do { ++result; } while (k < 3);
12562 ++j;
12563 if (j >= 8)
12564 break;
12565 } while (true);
12566 ++i;
12567 } while (i < 10);
12568
12569 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12570 })";
12571
12572 runTest(kFS);
12573 }
12574
12575 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)12576 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
12577 {
12578 constexpr char kFS[] = R"(#version 300 es
12579 precision mediump float;
12580 out vec4 color;
12581
12582 void main()
12583 {
12584 int result = 0;
12585 int i = 0;
12586 do
12587 {
12588 int j = 0;
12589 do
12590 {
12591 int k = 0;
12592 do { ++result; ++k; ++j; break; } while (k < 2);
12593 do { ++result; ++k; break; } while (k < 5);
12594 do { ++result; break; } while (k < 3);
12595 ++j;
12596 } while (j < 8);
12597 ++i;
12598 } while (i < 10);
12599
12600 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12601 })";
12602
12603 runTest(kFS);
12604 }
12605
12606 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)12607 TEST_P(GLSLTestLoops, ForContinueInSwitch)
12608 {
12609 constexpr char kFS[] = R"(#version 300 es
12610 precision mediump float;
12611 out vec4 color;
12612
12613 void main()
12614 {
12615 int result = 0;
12616 for (int i = 0; i < 10; ++i)
12617 for (int j = 0; j < 8; ++j)
12618 {
12619 switch (j)
12620 {
12621 case 2:
12622 case 3:
12623 case 4:
12624 ++result;
12625 // fallthrough
12626 case 5:
12627 case 6:
12628 ++result;
12629 break;
12630 default:
12631 continue;
12632 }
12633 }
12634
12635 color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12636 })";
12637
12638 runTest(kFS);
12639 }
12640
12641 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)12642 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
12643 {
12644 constexpr char kFS[] = R"(#version 300 es
12645 precision mediump float;
12646 out vec4 color;
12647
12648 void main()
12649 {
12650 int result = 0;
12651 int i = 0;
12652 while (i < 10)
12653 {
12654 int j = 0;
12655 while (j < 8)
12656 {
12657 switch (j)
12658 {
12659 case 2:
12660 default:
12661 case 3:
12662 case 4:
12663 ++j;
12664 ++result;
12665 continue;
12666 case 0:
12667 case 1:
12668 case 7:
12669 break;
12670 }
12671 ++j;
12672 }
12673 ++i;
12674 }
12675
12676 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12677 })";
12678
12679 runTest(kFS);
12680 }
12681
12682 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)12683 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
12684 {
12685 constexpr char kFS[] = R"(#version 300 es
12686 precision mediump float;
12687 out vec4 color;
12688
12689 void main()
12690 {
12691 int result = 0;
12692 int i = 0;
12693 do
12694 {
12695 int j = 0;
12696 do
12697 {
12698 switch (j)
12699 {
12700 case 0:
12701 ++j;
12702 continue;
12703 default:
12704 case 2:
12705 case 3:
12706 case 4:
12707 ++j;
12708 ++result;
12709 if (j >= 2 && j <= 6)
12710 break;
12711 else
12712 continue;
12713 }
12714 ++result;
12715 } while (j < 8);
12716 ++i;
12717 } while (i < 10);
12718
12719 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12720 })";
12721
12722 runTest(kFS);
12723 }
12724
12725 } // anonymous namespace
12726
12727 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(GLSLTest, WithDirectSPIRVGeneration(ES2_VULKAN()));
12728
12729 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
12730
12731 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
12732 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTest_ES3, WithDirectSPIRVGeneration(ES3_VULKAN()));
12733
12734 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
12735 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTestLoops, WithDirectSPIRVGeneration(ES3_VULKAN()));
12736
12737 ANGLE_INSTANTIATE_TEST_ES2_AND(WebGLGLSLTest, WithDirectSPIRVGeneration(ES2_VULKAN()));
12738
12739 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
12740 ANGLE_INSTANTIATE_TEST_ES3_AND(WebGL2GLSLTest, WithDirectSPIRVGeneration(ES3_VULKAN()));
12741
12742 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
12743 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31, WithDirectSPIRVGeneration(ES31_VULKAN()));
12744