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 #include "test_utils/gl_raii.h"
9
10 using namespace angle;
11
12 class DrawBuffersTest : public ANGLETest
13 {
14 protected:
DrawBuffersTest()15 DrawBuffersTest()
16 {
17 setWindowWidth(128);
18 setWindowHeight(128);
19 setConfigRedBits(8);
20 setConfigGreenBits(8);
21 setConfigBlueBits(8);
22 setConfigAlphaBits(8);
23 setConfigDepthBits(24);
24 }
25
testTearDown()26 void testTearDown() override
27 {
28 glDeleteFramebuffers(1, &mFBO);
29 glDeleteFramebuffers(1, &mReadFramebuffer);
30 glDeleteTextures(4, mTextures);
31 }
32
33 // We must call a different DrawBuffers method depending on extension support. Use this
34 // method instead of calling on directly.
setDrawBuffers(GLsizei n,const GLenum * drawBufs)35 void setDrawBuffers(GLsizei n, const GLenum *drawBufs)
36 {
37 if (IsGLExtensionEnabled("GL_EXT_draw_buffers"))
38 {
39 glDrawBuffersEXT(n, drawBufs);
40 }
41 else
42 {
43 ASSERT_GE(getClientMajorVersion(), 3);
44 glDrawBuffers(n, drawBufs);
45 }
46 }
47
48 // Use this method to filter if we can support these tests.
setupTest()49 bool setupTest()
50 {
51 if (getClientMajorVersion() < 3 && (!EnsureGLExtensionEnabled("GL_EXT_draw_buffers") ||
52 !EnsureGLExtensionEnabled("GL_ANGLE_framebuffer_blit")))
53 {
54 return false;
55 }
56
57 // This test seems to fail on an nVidia machine when the window is hidden
58 setWindowVisible(getOSWindow(), true);
59
60 glGenFramebuffers(1, &mFBO);
61 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
62
63 glGenTextures(4, mTextures);
64
65 for (size_t texIndex = 0; texIndex < ArraySize(mTextures); texIndex++)
66 {
67 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
68 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
69 GL_UNSIGNED_BYTE, nullptr);
70 }
71
72 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &mMaxDrawBuffers);
73
74 glGenFramebuffers(1, &mReadFramebuffer);
75 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
76
77 return true;
78 }
79
setupMRTProgramESSL3(bool bufferEnabled[8],GLuint * programOut)80 void setupMRTProgramESSL3(bool bufferEnabled[8], GLuint *programOut)
81 {
82 std::stringstream strstr;
83
84 strstr << "#version 300 es\n"
85 "precision highp float;\n";
86
87 for (unsigned int index = 0; index < 8; index++)
88 {
89 if (bufferEnabled[index])
90 {
91 strstr << "layout(location = " << index
92 << ") "
93 "out vec4 value"
94 << index << ";\n";
95 }
96 }
97
98 strstr << "void main()\n"
99 "{\n";
100
101 for (unsigned int index = 0; index < 8; index++)
102 {
103 if (bufferEnabled[index])
104 {
105 unsigned int r = (index + 1) & 1;
106 unsigned int g = (index + 1) & 2;
107 unsigned int b = (index + 1) & 4;
108
109 strstr << " value" << index << " = vec4(" << r << ".0, " << g << ".0, " << b
110 << ".0, 1.0);\n";
111 }
112 }
113
114 strstr << "}\n";
115
116 *programOut = CompileProgram(essl3_shaders::vs::Simple(), strstr.str().c_str());
117 if (*programOut == 0)
118 {
119 FAIL() << "shader compilation failed.";
120 }
121 }
122
setupMRTProgramESSL1(bool bufferEnabled[8],GLuint * programOut)123 void setupMRTProgramESSL1(bool bufferEnabled[8], GLuint *programOut)
124 {
125 std::stringstream strstr;
126
127 strstr << "#extension GL_EXT_draw_buffers : enable\n"
128 "precision highp float;\n"
129 "void main()\n"
130 "{\n";
131
132 for (unsigned int index = 0; index < 8; index++)
133 {
134 if (bufferEnabled[index])
135 {
136 unsigned int r = (index + 1) & 1;
137 unsigned int g = (index + 1) & 2;
138 unsigned int b = (index + 1) & 4;
139
140 strstr << " gl_FragData[" << index << "] = vec4(" << r << ".0, " << g << ".0, "
141 << b << ".0, 1.0);\n";
142 }
143 }
144
145 strstr << "}\n";
146
147 *programOut = CompileProgram(essl1_shaders::vs::Simple(), strstr.str().c_str());
148 if (*programOut == 0)
149 {
150 FAIL() << "shader compilation failed.";
151 }
152 }
153
setupMRTProgram(bool bufferEnabled[8],GLuint * programOut)154 void setupMRTProgram(bool bufferEnabled[8], GLuint *programOut)
155 {
156 if (getClientMajorVersion() == 3)
157 {
158 setupMRTProgramESSL3(bufferEnabled, programOut);
159 }
160 else
161 {
162 ASSERT_EQ(getClientMajorVersion(), 2);
163 setupMRTProgramESSL1(bufferEnabled, programOut);
164 }
165 }
166
positionAttrib()167 const char *positionAttrib()
168 {
169 if (getClientMajorVersion() == 3)
170 {
171 return essl3_shaders::PositionAttrib();
172 }
173 else
174 {
175 return essl1_shaders::PositionAttrib();
176 }
177 }
178
getColorForIndex(unsigned int index)179 static GLColor getColorForIndex(unsigned int index)
180 {
181 GLubyte r = (((index + 1) & 1) > 0) ? 255 : 0;
182 GLubyte g = (((index + 1) & 2) > 0) ? 255 : 0;
183 GLubyte b = (((index + 1) & 4) > 0) ? 255 : 0;
184 return GLColor(r, g, b, 255u);
185 }
186
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)187 void verifyAttachment2DColor(unsigned int index,
188 GLuint textureName,
189 GLenum target,
190 GLint level,
191 GLColor color)
192 {
193 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, textureName,
194 level);
195 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
196 << "index " << index;
197 }
198
verifyAttachment2DUnwritten(unsigned int index,GLuint texture,GLenum target,GLint level)199 void verifyAttachment2DUnwritten(unsigned int index, GLuint texture, GLenum target, GLint level)
200 {
201 verifyAttachment2DColor(index, texture, target, level, GLColor::transparentBlack);
202 }
203
verifyAttachment2D(unsigned int index,GLuint texture,GLenum target,GLint level)204 void verifyAttachment2D(unsigned int index, GLuint texture, GLenum target, GLint level)
205 {
206 verifyAttachment2DColor(index, texture, target, level, getColorForIndex(index));
207 }
208
verifyAttachmentLayer(unsigned int index,GLuint texture,GLint level,GLint layer)209 void verifyAttachmentLayer(unsigned int index, GLuint texture, GLint level, GLint layer)
210 {
211 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, level, layer);
212 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, getColorForIndex(index));
213 }
214
215 GLuint mFBO = 0;
216 GLuint mReadFramebuffer = 0;
217 GLuint mTextures[4] = {};
218 GLint mMaxDrawBuffers = 0;
219 };
220
221 class DrawBuffersWebGL2Test : public DrawBuffersTest
222 {
223 public:
DrawBuffersWebGL2Test()224 DrawBuffersWebGL2Test()
225 {
226 setWebGLCompatibilityEnabled(true);
227 setRobustResourceInit(true);
228 }
229 };
230
231 // Verify that GL_MAX_DRAW_BUFFERS returns the expected values for D3D11
TEST_P(DrawBuffersTest,VerifyD3DLimits)232 TEST_P(DrawBuffersTest, VerifyD3DLimits)
233 {
234 EGLPlatformParameters platform = GetParam().eglParameters;
235
236 ANGLE_SKIP_TEST_IF(platform.renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
237
238 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &mMaxDrawBuffers);
239
240 if (platform.majorVersion == 9 && platform.minorVersion == 3)
241 {
242 // D3D11 Feature Level 9_3 supports 4 draw buffers
243 ASSERT_EQ(mMaxDrawBuffers, 4);
244 }
245 else
246 {
247 // D3D11 Feature Level 10_0+ supports 8 draw buffers
248 ASSERT_EQ(mMaxDrawBuffers, 8);
249 }
250 }
251
TEST_P(DrawBuffersTest,Gaps)252 TEST_P(DrawBuffersTest, Gaps)
253 {
254 ANGLE_SKIP_TEST_IF(!setupTest());
255
256 // TODO(ynovikov): Investigate the failure (http://anglebug.com/1535)
257 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
258
259 // TODO(syoussefi): Qualcomm driver crashes in the presence of VK_ATTACHMENT_UNUSED.
260 // http://anglebug.com/3423
261 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
262
263 // Fails on Intel Ubuntu 19.04 Mesa 19.0.2 Vulkan. http://anglebug.com/3616
264 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
265
266 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
267 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[0], 0);
268
269 bool flags[8] = {false, true};
270
271 GLuint program;
272 setupMRTProgram(flags, &program);
273
274 const GLenum bufs[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
275 setDrawBuffers(2, bufs);
276 drawQuad(program, positionAttrib(), 0.5);
277
278 verifyAttachment2D(1, mTextures[0], GL_TEXTURE_2D, 0);
279
280 glDeleteProgram(program);
281 }
282
TEST_P(DrawBuffersTest,FirstAndLast)283 TEST_P(DrawBuffersTest, FirstAndLast)
284 {
285 ANGLE_SKIP_TEST_IF(!setupTest());
286
287 // TODO(ynovikov): Investigate the failure (https://anglebug.com/1533)
288 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
289
290 // TODO(syoussefi): Qualcomm driver crashes in the presence of VK_ATTACHMENT_UNUSED.
291 // http://anglebug.com/3423
292 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
293
294 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
295 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
296
297 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
298 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTextures[1], 0);
299
300 bool flags[8] = {true, false, false, true};
301
302 GLuint program;
303 setupMRTProgram(flags, &program);
304
305 const GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
306
307 setDrawBuffers(4, bufs);
308 drawQuad(program, positionAttrib(), 0.5);
309
310 verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
311 verifyAttachment2D(3, mTextures[1], GL_TEXTURE_2D, 0);
312
313 EXPECT_GL_NO_ERROR();
314
315 glDeleteProgram(program);
316 }
317
TEST_P(DrawBuffersTest,FirstHalfNULL)318 TEST_P(DrawBuffersTest, FirstHalfNULL)
319 {
320 ANGLE_SKIP_TEST_IF(!setupTest());
321
322 // TODO(ynovikov): Investigate the failure (https://anglebug.com/1533)
323 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
324
325 // TODO(syoussefi): Qualcomm driver crashes in the presence of VK_ATTACHMENT_UNUSED.
326 // http://anglebug.com/3423
327 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
328
329 // Fails on Intel Ubuntu 19.04 Mesa 19.0.2 Vulkan. http://anglebug.com/3616
330 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
331
332 bool flags[8] = {false};
333 GLenum bufs[8] = {GL_NONE};
334
335 GLuint halfMaxDrawBuffers = static_cast<GLuint>(mMaxDrawBuffers) / 2;
336
337 for (GLuint texIndex = 0; texIndex < halfMaxDrawBuffers; texIndex++)
338 {
339 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
340 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + halfMaxDrawBuffers + texIndex,
341 GL_TEXTURE_2D, mTextures[texIndex], 0);
342 flags[texIndex + halfMaxDrawBuffers] = true;
343 bufs[texIndex + halfMaxDrawBuffers] = GL_COLOR_ATTACHMENT0 + halfMaxDrawBuffers + texIndex;
344 }
345
346 GLuint program;
347 setupMRTProgram(flags, &program);
348
349 setDrawBuffers(mMaxDrawBuffers, bufs);
350 drawQuad(program, positionAttrib(), 0.5);
351
352 for (GLuint texIndex = 0; texIndex < halfMaxDrawBuffers; texIndex++)
353 {
354 verifyAttachment2D(texIndex + halfMaxDrawBuffers, mTextures[texIndex], GL_TEXTURE_2D, 0);
355 }
356
357 EXPECT_GL_NO_ERROR();
358
359 glDeleteProgram(program);
360 }
361
362 // Test that non-zero draw buffers can be queried on the default framebuffer
TEST_P(DrawBuffersTest,DefaultFramebufferDrawBufferQuery)363 TEST_P(DrawBuffersTest, DefaultFramebufferDrawBufferQuery)
364 {
365 ANGLE_SKIP_TEST_IF(!setupTest());
366
367 glBindFramebuffer(GL_FRAMEBUFFER, 0);
368
369 GLint drawbuffer = 0;
370 glGetIntegerv(GL_DRAW_BUFFER1, &drawbuffer);
371 EXPECT_GL_NO_ERROR();
372
373 EXPECT_EQ(GL_NONE, drawbuffer);
374 }
375
376 // Same as above but adds a state change from a program with different masks after a clear.
TEST_P(DrawBuffersWebGL2Test,TwoProgramsWithDifferentOutputsAndClear)377 TEST_P(DrawBuffersWebGL2Test, TwoProgramsWithDifferentOutputsAndClear)
378 {
379 // TODO(http://anglebug.com/2872): Broken on the GL back-end.
380 ANGLE_SKIP_TEST_IF(IsOpenGL());
381
382 // TODO(ynovikov): Investigate the failure (https://anglebug.com/1533)
383 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
384
385 // TODO(syoussefi): Qualcomm driver crashes in the presence of VK_ATTACHMENT_UNUSED.
386 // http://anglebug.com/3423
387 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
388
389 ANGLE_SKIP_TEST_IF(!setupTest());
390
391 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &mMaxDrawBuffers);
392 ASSERT_GE(mMaxDrawBuffers, 4);
393
394 bool flags[8] = {false};
395 GLenum someBufs[4] = {GL_NONE};
396 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
397 GL_COLOR_ATTACHMENT3};
398
399 constexpr GLuint kMaxBuffers = 4;
400 constexpr GLuint kHalfMaxBuffers = 2;
401
402 // Enable all draw buffers.
403 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
404 {
405 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
406 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
407 mTextures[texIndex], 0);
408 someBufs[texIndex] =
409 texIndex >= kHalfMaxBuffers ? GL_COLOR_ATTACHMENT0 + texIndex : GL_NONE;
410
411 // Mask out the first two buffers.
412 flags[texIndex] = texIndex >= kHalfMaxBuffers;
413 }
414
415 GLuint program;
416 setupMRTProgram(flags, &program);
417
418 // Now set up a second simple program that draws to FragColor. Should be broadcast.
419 ANGLE_GL_PROGRAM(simpleProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
420
421 // Draw with simple program.
422 drawQuad(simpleProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
423 ASSERT_GL_NO_ERROR();
424
425 // Clear draw buffers.
426 setDrawBuffers(kMaxBuffers, someBufs);
427 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
428 glClear(GL_COLOR_BUFFER_BIT);
429
430 ASSERT_GL_NO_ERROR();
431
432 // Verify first is drawn red, second is untouched, and last two are cleared green.
433 verifyAttachment2DColor(0, mTextures[0], GL_TEXTURE_2D, 0, GLColor::red);
434 verifyAttachment2DColor(1, mTextures[1], GL_TEXTURE_2D, 0, GLColor::transparentBlack);
435 verifyAttachment2DColor(2, mTextures[2], GL_TEXTURE_2D, 0, GLColor::green);
436 verifyAttachment2DColor(3, mTextures[3], GL_TEXTURE_2D, 0, GLColor::green);
437
438 // Draw with MRT program.
439 setDrawBuffers(kMaxBuffers, someBufs);
440 drawQuad(program, positionAttrib(), 0.5, 1.0f, true);
441 ASSERT_GL_NO_ERROR();
442
443 // Only the last two attachments should be updated.
444 verifyAttachment2DColor(0, mTextures[0], GL_TEXTURE_2D, 0, GLColor::red);
445 verifyAttachment2DColor(1, mTextures[1], GL_TEXTURE_2D, 0, GLColor::transparentBlack);
446 verifyAttachment2D(2, mTextures[2], GL_TEXTURE_2D, 0);
447 verifyAttachment2D(3, mTextures[3], GL_TEXTURE_2D, 0);
448
449 // Active draw buffers with no fragment output is not allowed.
450 setDrawBuffers(kMaxBuffers, allBufs);
451 drawQuad(program, positionAttrib(), 0.5, 1.0f, true);
452 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
453 // Exception: when RASTERIZER_DISCARD is enabled.
454 glEnable(GL_RASTERIZER_DISCARD);
455 drawQuad(program, positionAttrib(), 0.5, 1.0f, true);
456 ASSERT_GL_NO_ERROR();
457 glDisable(GL_RASTERIZER_DISCARD);
458 // Exception: when all 4 channels of color mask are set to false.
459 glColorMask(false, false, false, false);
460 drawQuad(program, positionAttrib(), 0.5, 1.0f, true);
461 ASSERT_GL_NO_ERROR();
462 glColorMask(false, true, false, false);
463 drawQuad(program, positionAttrib(), 0.5, 1.0f, true);
464 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
465 glColorMask(true, true, true, true);
466 drawQuad(program, positionAttrib(), 0.5, 1.0f, true);
467 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
468
469 // Clear again. All attachments should be cleared.
470 glClear(GL_COLOR_BUFFER_BIT);
471 verifyAttachment2DColor(0, mTextures[0], GL_TEXTURE_2D, 0, GLColor::green);
472 verifyAttachment2DColor(1, mTextures[1], GL_TEXTURE_2D, 0, GLColor::green);
473 verifyAttachment2DColor(2, mTextures[2], GL_TEXTURE_2D, 0, GLColor::green);
474 verifyAttachment2DColor(3, mTextures[3], GL_TEXTURE_2D, 0, GLColor::green);
475
476 glDeleteProgram(program);
477 }
478
TEST_P(DrawBuffersTest,UnwrittenOutputVariablesShouldNotCrash)479 TEST_P(DrawBuffersTest, UnwrittenOutputVariablesShouldNotCrash)
480 {
481 ANGLE_SKIP_TEST_IF(!setupTest());
482
483 // Bind two render targets but use a shader which writes only to the first one.
484 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
485 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
486
487 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
488 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
489
490 bool flags[8] = {true, false};
491
492 GLuint program;
493 setupMRTProgram(flags, &program);
494
495 const GLenum bufs[] = {
496 GL_COLOR_ATTACHMENT0,
497 GL_COLOR_ATTACHMENT1,
498 GL_NONE,
499 GL_NONE,
500 };
501
502 setDrawBuffers(4, bufs);
503
504 // This call should not crash when we dynamically generate the HLSL code.
505 drawQuad(program, positionAttrib(), 0.5);
506
507 verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
508
509 EXPECT_GL_NO_ERROR();
510
511 glDeleteProgram(program);
512 }
513
TEST_P(DrawBuffersTest,BroadcastGLFragColor)514 TEST_P(DrawBuffersTest, BroadcastGLFragColor)
515 {
516 // Broadcast is not supported on GLES 3.0.
517 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
518 ANGLE_SKIP_TEST_IF(!setupTest());
519
520 // Bind two render targets. gl_FragColor should be broadcast to both.
521 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
522 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
523
524 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
525 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
526
527 const GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
528
529 constexpr char kFS[] =
530 "#extension GL_EXT_draw_buffers : enable\n"
531 "precision highp float;\n"
532 "uniform float u_zero;\n"
533 "void main()\n"
534 "{\n"
535 " gl_FragColor = vec4(1, 0, 0, 1);\n"
536 " if (u_zero < 1.0)\n"
537 " {\n"
538 " return;\n"
539 " }\n"
540 "}\n";
541
542 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
543 if (program == 0)
544 {
545 FAIL() << "shader compilation failed.";
546 }
547
548 setDrawBuffers(2, bufs);
549 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
550
551 verifyAttachment2D(0, mTextures[0], GL_TEXTURE_2D, 0);
552 verifyAttachment2D(0, mTextures[1], GL_TEXTURE_2D, 0);
553
554 EXPECT_GL_NO_ERROR();
555
556 glDeleteProgram(program);
557 }
558
559 class DrawBuffersTestES3 : public DrawBuffersTest
560 {};
561
562 // Test that binding multiple layers of a 3D texture works correctly
563 TEST_P(DrawBuffersTestES3, 3DTextures)
564 {
565 ANGLE_SKIP_TEST_IF(!setupTest());
566
567 GLTexture texture;
568 glBindTexture(GL_TEXTURE_3D, texture.get());
569 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), getWindowWidth(),
570 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
571
572 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
573 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture.get(), 0, 1);
574 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, texture.get(), 0, 2);
575 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, texture.get(), 0, 3);
576
577 bool flags[8] = {true, true, true, true, false};
578
579 GLuint program;
580 setupMRTProgram(flags, &program);
581
582 const GLenum bufs[] = {
583 GL_COLOR_ATTACHMENT0,
584 GL_COLOR_ATTACHMENT1,
585 GL_COLOR_ATTACHMENT2,
586 GL_COLOR_ATTACHMENT3,
587 };
588
589 glDrawBuffers(4, bufs);
590 drawQuad(program, positionAttrib(), 0.5);
591
592 verifyAttachmentLayer(0, texture.get(), 0, 0);
593 verifyAttachmentLayer(1, texture.get(), 0, 1);
594 verifyAttachmentLayer(2, texture.get(), 0, 2);
595 verifyAttachmentLayer(3, texture.get(), 0, 3);
596
597 EXPECT_GL_NO_ERROR();
598
599 glDeleteProgram(program);
600 }
601
602 // Test that binding multiple layers of a 2D array texture works correctly
603 TEST_P(DrawBuffersTestES3, 2DArrayTextures)
604 {
605 ANGLE_SKIP_TEST_IF(!setupTest());
606
607 GLTexture texture;
608 glBindTexture(GL_TEXTURE_2D_ARRAY, texture.get());
609 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, getWindowWidth(), getWindowHeight(),
610 getWindowWidth(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
611
612 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
613 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture.get(), 0, 1);
614 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, texture.get(), 0, 2);
615 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, texture.get(), 0, 3);
616
617 bool flags[8] = {true, true, true, true, false};
618
619 GLuint program;
620 setupMRTProgram(flags, &program);
621
622 const GLenum bufs[] = {
623 GL_COLOR_ATTACHMENT0,
624 GL_COLOR_ATTACHMENT1,
625 GL_COLOR_ATTACHMENT2,
626 GL_COLOR_ATTACHMENT3,
627 };
628
629 glDrawBuffers(4, bufs);
630 drawQuad(program, positionAttrib(), 0.5);
631
632 verifyAttachmentLayer(0, texture.get(), 0, 0);
633 verifyAttachmentLayer(1, texture.get(), 0, 1);
634 verifyAttachmentLayer(2, texture.get(), 0, 2);
635 verifyAttachmentLayer(3, texture.get(), 0, 3);
636
637 EXPECT_GL_NO_ERROR();
638
639 glDeleteProgram(program);
640 }
641
642 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
643 // tests should be run against.
644 ANGLE_INSTANTIATE_TEST(DrawBuffersTest,
645 ANGLE_ALL_TEST_PLATFORMS_ES2,
646 ANGLE_ALL_TEST_PLATFORMS_ES3,
647 WithNoTransformFeedback(ES2_VULKAN()));
648 ANGLE_INSTANTIATE_TEST_ES3(DrawBuffersWebGL2Test);
649
650 ANGLE_INSTANTIATE_TEST_ES3(DrawBuffersTestES3);
651