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