1 //
2 // Copyright 2019 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 // MultisampledRenderToTextureTest: Tests of EXT_multisampled_render_to_texture extension
8
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11
12 #include "common/mathutil.h"
13
14 using namespace angle;
15
16 namespace
17 {
18
19 using MultisampledRenderToTextureTestParams = std::tuple<angle::PlatformParameters, bool>;
20
PrintToStringParamName(const::testing::TestParamInfo<MultisampledRenderToTextureTestParams> & info)21 std::string PrintToStringParamName(
22 const ::testing::TestParamInfo<MultisampledRenderToTextureTestParams> &info)
23 {
24 std::stringstream ss;
25 ss << std::get<0>(info.param);
26 if (std::get<1>(info.param))
27 {
28 ss << "_RobustResourceInit";
29 }
30 return ss.str();
31 }
32
33 class MultisampledRenderToTextureTest : public ANGLETest<MultisampledRenderToTextureTestParams>
34 {
35 protected:
MultisampledRenderToTextureTest()36 MultisampledRenderToTextureTest()
37 {
38 setWindowWidth(64);
39 setWindowHeight(64);
40 setConfigRedBits(8);
41 setConfigGreenBits(8);
42 setConfigBlueBits(8);
43 setConfigAlphaBits(8);
44
45 setRobustResourceInit(::testing::get<1>(GetParam()));
46 forceNewDisplay();
47 }
48
testSetUp()49 void testSetUp() override
50 {
51 if (getClientMajorVersion() >= 3 && getClientMinorVersion() >= 1)
52 {
53 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
54 }
55 }
56
testTearDown()57 void testTearDown() override {}
58
assertErrorIfNotMSRTT2(GLenum error)59 void assertErrorIfNotMSRTT2(GLenum error)
60 {
61 if (EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"))
62 {
63 ASSERT_GL_NO_ERROR();
64 }
65 else
66 {
67 ASSERT_GL_ERROR(error);
68 }
69 }
70
setupCopyTexProgram()71 void setupCopyTexProgram()
72 {
73 mCopyTextureProgram.makeRaster(essl1_shaders::vs::Texture2D(),
74 essl1_shaders::fs::Texture2D());
75 ASSERT_GL_TRUE(mCopyTextureProgram.valid());
76
77 mCopyTextureUniformLocation =
78 glGetUniformLocation(mCopyTextureProgram, essl1_shaders::Texture2DUniform());
79
80 ASSERT_GL_NO_ERROR();
81 }
82
setupUniformColorProgramMultiRenderTarget(const bool bufferEnabled[8],GLuint * programOut)83 void setupUniformColorProgramMultiRenderTarget(const bool bufferEnabled[8], GLuint *programOut)
84 {
85 std::stringstream fs;
86
87 fs << "#extension GL_EXT_draw_buffers : enable\n"
88 "precision highp float;\n"
89 "uniform mediump vec4 "
90 << essl1_shaders::ColorUniform()
91 << ";\n"
92 "void main()\n"
93 "{\n";
94
95 for (unsigned int index = 0; index < 8; index++)
96 {
97 if (bufferEnabled[index])
98 {
99 fs << " gl_FragData[" << index << "] = " << essl1_shaders::ColorUniform()
100 << ";\n";
101 }
102 }
103
104 fs << "}\n";
105
106 *programOut = CompileProgram(essl1_shaders::vs::Simple(), fs.str().c_str());
107 ASSERT_NE(*programOut, 0u);
108 }
109
verifyResults(GLuint texture,const GLColor expected,GLint fboSize,GLint xs,GLint ys,GLint xe,GLint ye)110 void verifyResults(GLuint texture,
111 const GLColor expected,
112 GLint fboSize,
113 GLint xs,
114 GLint ys,
115 GLint xe,
116 GLint ye)
117 {
118 glViewport(0, 0, fboSize, fboSize);
119
120 glBindFramebuffer(GL_FRAMEBUFFER, 0);
121
122 // Draw a quad with the target texture
123 glUseProgram(mCopyTextureProgram);
124 glBindTexture(GL_TEXTURE_2D, texture);
125 glUniform1i(mCopyTextureUniformLocation, 0);
126
127 glDisable(GL_DEPTH_TEST);
128 glDisable(GL_STENCIL_TEST);
129 glDisable(GL_BLEND);
130 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
131 drawQuad(mCopyTextureProgram, essl1_shaders::PositionAttrib(), 0.5f);
132
133 // Expect that the rendered quad has the same color as the source texture
134 EXPECT_PIXEL_COLOR_NEAR(xs, ys, expected, 1.0);
135 EXPECT_PIXEL_COLOR_NEAR(xs, ye - 1, expected, 1.0);
136 EXPECT_PIXEL_COLOR_NEAR(xe - 1, ys, expected, 1.0);
137 EXPECT_PIXEL_COLOR_NEAR(xe - 1, ye - 1, expected, 1.0);
138 EXPECT_PIXEL_COLOR_NEAR((xs + xe) / 2, (ys + ye) / 2, expected, 1.0);
139 }
140
clearAndDrawQuad(GLuint program,GLsizei viewportWidth,GLsizei viewportHeight)141 void clearAndDrawQuad(GLuint program, GLsizei viewportWidth, GLsizei viewportHeight)
142 {
143 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
144 glClear(GL_COLOR_BUFFER_BIT);
145 glViewport(0, 0, viewportWidth, viewportHeight);
146 ASSERT_GL_NO_ERROR();
147
148 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
149 ASSERT_GL_NO_ERROR();
150 }
151
152 struct GLType
153 {
154 GLenum internalFormat;
155 GLenum format;
156 GLenum type;
157 };
158
159 void createAndAttachColorAttachment(bool useRenderbuffer,
160 GLsizei size,
161 GLenum renderbufferTarget,
162 const GLType *glType,
163 GLint samples,
164 GLTexture *textureOut,
165 GLRenderbuffer *renderbufferOut);
166 void createAndAttachDepthStencilAttachment(bool useRenderbuffer,
167 GLsizei size,
168 GLTexture *textureOut,
169 GLRenderbuffer *renderbufferOut);
170 void colorAttachmentMultisampleDrawTestCommon(bool useRenderbuffer);
171 void copyTexImageTestCommon(bool useRenderbuffer);
172 void copyTexSubImageTestCommon(bool useRenderbuffer);
173 void drawCopyThenBlendCommon(bool useRenderbuffer);
174 void clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer);
175 void drawCopyDrawThenMaskedClearCommon(bool useRenderbuffer);
176 void clearThenBlendCommon(bool useRenderbuffer);
177
178 GLProgram mCopyTextureProgram;
179 GLint mCopyTextureUniformLocation = -1;
180
181 const GLint mTestSampleCount = 4;
182 GLint mMaxIntegerSamples = 0;
183 };
184
185 class MultisampledRenderToTextureES3Test : public MultisampledRenderToTextureTest
186 {
187 protected:
188 void readPixelsTestCommon(bool useRenderbuffer);
189 void blitFramebufferTestCommon(bool useRenderbuffer);
190 void drawCopyDrawAttachInvalidatedThenDrawCommon(bool useRenderbuffer);
191 void drawCopyDrawAttachDepthStencilClearThenDrawCommon(bool useRenderbuffer);
192 void depthStencilClearThenDrawCommon(bool useRenderbuffer);
193 void colorAttachment1Common(bool useRenderbuffer);
194 void colorAttachments0And3Common(bool useRenderbuffer);
195 void blitFramebufferMixedColorAndDepthCommon(bool useRenderbuffer);
196 void renderbufferUnresolveColorAndDepthStencilThenTwoColors(bool withDepth, bool withStencil);
197 };
198
199 class MultisampledRenderToTextureES31Test : public MultisampledRenderToTextureTest
200 {
201 protected:
202 void blitFramebufferAttachment1Common(bool useRenderbuffer);
203 void drawCopyThenBlendAllAttachmentsMixed(bool useRenderbuffer);
204 };
205
206 // Checking against invalid parameters for RenderbufferStorageMultisampleEXT.
TEST_P(MultisampledRenderToTextureTest,RenderbufferParameterCheck)207 TEST_P(MultisampledRenderToTextureTest, RenderbufferParameterCheck)
208 {
209 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
210
211 // Linux Intel Vulkan returns 0 for GL_MAX_INTEGER_SAMPLES http://anglebug.com/5988
212 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
213
214 GLRenderbuffer renderbuffer;
215 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
216
217 // Positive test case. Formats required by the spec (GLES2.0 Table 4.5)
218 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, 64, 64);
219 ASSERT_GL_NO_ERROR();
220 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_STENCIL_INDEX8, 64, 64);
221 ASSERT_GL_NO_ERROR();
222 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_RGBA4, 64, 64);
223 ASSERT_GL_NO_ERROR();
224 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_RGB5_A1, 64, 64);
225 ASSERT_GL_NO_ERROR();
226 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_RGB565, 64, 64);
227 ASSERT_GL_NO_ERROR();
228
229 // Positive test case. A few of the ES3 formats
230 if (getClientMajorVersion() >= 3)
231 {
232 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, 64, 64);
233 ASSERT_GL_NO_ERROR();
234 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_RGBA8, 64, 64);
235 ASSERT_GL_NO_ERROR();
236
237 if (getClientMinorVersion() >= 1)
238 {
239 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, mMaxIntegerSamples, GL_RGBA32I, 64,
240 64);
241 ASSERT_GL_NO_ERROR();
242 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, mMaxIntegerSamples, GL_RGBA32UI,
243 64, 64);
244 ASSERT_GL_NO_ERROR();
245 }
246 }
247
248 GLint samples;
249 glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
250 ASSERT_GL_NO_ERROR();
251 EXPECT_GE(samples, 1);
252
253 // Samples too large
254 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples + 1, GL_DEPTH_COMPONENT16, 64, 64);
255 ASSERT_GL_ERROR(GL_INVALID_VALUE);
256
257 // Renderbuffer size too large
258 GLint maxSize;
259 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
260 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 2, GL_RGBA4, maxSize + 1, maxSize);
261 ASSERT_GL_ERROR(GL_INVALID_VALUE);
262 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT16, maxSize,
263 maxSize + 1);
264 ASSERT_GL_ERROR(GL_INVALID_VALUE);
265
266 // Retrieving samples
267 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, 64, 64);
268 GLint param = 0;
269 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES_EXT, ¶m);
270 // GE because samples may vary base on implementation. Spec says "the resulting value for
271 // RENDERBUFFER_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more
272 // than the next larger sample count supported by the implementation"
273 EXPECT_GE(param, 4);
274 }
275
276 // Checking against invalid parameters for FramebufferTexture2DMultisampleEXT.
TEST_P(MultisampledRenderToTextureTest,Texture2DParameterCheck)277 TEST_P(MultisampledRenderToTextureTest, Texture2DParameterCheck)
278 {
279 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
280 bool isES3 = getClientMajorVersion() >= 3;
281
282 GLTexture texture;
283 glBindTexture(GL_TEXTURE_2D, texture);
284 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
285 ASSERT_GL_NO_ERROR();
286
287 GLTexture depthTexture;
288 if (isES3)
289 {
290 glBindTexture(GL_TEXTURE_2D, depthTexture);
291 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 64, 64, 0, GL_DEPTH_STENCIL,
292 GL_UNSIGNED_INT_24_8_OES, nullptr);
293 }
294
295 GLFramebuffer fbo;
296 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
297 // Positive test case
298 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
299 texture, 0, 4);
300 ASSERT_GL_NO_ERROR();
301 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
302
303 if (EnsureGLExtensionEnabled("GL_EXT_draw_buffers") || isES3)
304 {
305 // Attachment not COLOR_ATTACHMENT0. Allowed only in EXT_multisampled_render_to_texture2
306 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
307 texture, 0, 4);
308 assertErrorIfNotMSRTT2(GL_INVALID_ENUM);
309 }
310
311 // Depth/stencil attachment. Allowed only in EXT_multisampled_render_to_texture2
312 if (isES3)
313 {
314 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
315 depthTexture, 0, 4);
316 assertErrorIfNotMSRTT2(GL_INVALID_ENUM);
317
318 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
319 depthTexture, 0, 4);
320 assertErrorIfNotMSRTT2(GL_INVALID_ENUM);
321
322 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
323 GL_TEXTURE_2D, depthTexture, 0, 4);
324 assertErrorIfNotMSRTT2(GL_INVALID_ENUM);
325
326 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
327 depthTexture, 0, 4);
328 assertErrorIfNotMSRTT2(GL_INVALID_ENUM);
329 }
330
331 // Target not framebuffer
332 glFramebufferTexture2DMultisampleEXT(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
333 texture, 0, 4);
334 ASSERT_GL_ERROR(GL_INVALID_ENUM);
335
336 GLint samples;
337 glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
338 ASSERT_GL_NO_ERROR();
339 EXPECT_GE(samples, 1);
340
341 // Samples too large
342 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
343 texture, 0, samples + 1);
344 ASSERT_GL_ERROR(GL_INVALID_VALUE);
345
346 // Retrieving samples
347 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
348 texture, 0, 4);
349 GLint param = 0;
350 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
351 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT, ¶m);
352 // GE because samples may vary base on implementation. Spec says "the resulting value for
353 // TEXTURE_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more than the
354 // next larger sample count supported by the implementation"
355 EXPECT_GE(param, 4);
356 }
357
358 // Checking against invalid parameters for FramebufferTexture2DMultisampleEXT (cubemap).
TEST_P(MultisampledRenderToTextureTest,TextureCubeMapParameterCheck)359 TEST_P(MultisampledRenderToTextureTest, TextureCubeMapParameterCheck)
360 {
361 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
362 bool isES3 = getClientMajorVersion() >= 3;
363
364 GLTexture texture;
365 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
366 for (GLenum face = 0; face < 6; face++)
367 {
368 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 64, 64, 0, GL_RGBA,
369 GL_UNSIGNED_BYTE, nullptr);
370 ASSERT_GL_NO_ERROR();
371 }
372
373 GLint samples;
374 glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
375 ASSERT_GL_NO_ERROR();
376 EXPECT_GE(samples, 1);
377
378 GLFramebuffer FBO;
379 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
380 for (GLenum face = 0; face < 6; face++)
381 {
382 // Positive test case
383 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
384 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
385 ASSERT_GL_NO_ERROR();
386 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
387
388 if (EnsureGLExtensionEnabled("GL_EXT_draw_buffers") || isES3)
389 {
390 // Attachment not COLOR_ATTACHMENT0. Allowed only in
391 // EXT_multisampled_render_to_texture2
392 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
393 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0,
394 4);
395 assertErrorIfNotMSRTT2(GL_INVALID_ENUM);
396 }
397
398 // Target not framebuffer
399 glFramebufferTexture2DMultisampleEXT(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0,
400 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
401 ASSERT_GL_ERROR(GL_INVALID_ENUM);
402
403 // Samples too large
404 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
405 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0,
406 samples + 1);
407 ASSERT_GL_ERROR(GL_INVALID_VALUE);
408
409 // Retrieving samples
410 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
411 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
412 GLint param = 0;
413 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
414 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT,
415 ¶m);
416 // GE because samples may vary base on implementation. Spec says "the resulting value for
417 // TEXTURE_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more than
418 // the next larger sample count supported by the implementation"
419 EXPECT_GE(param, 4);
420 }
421 }
422
423 // Checking for framebuffer completeness using extension methods.
TEST_P(MultisampledRenderToTextureTest,FramebufferCompleteness)424 TEST_P(MultisampledRenderToTextureTest, FramebufferCompleteness)
425 {
426 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
427
428 // Checking that Renderbuffer and texture2d having different number of samples results
429 // in a FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
430 GLTexture texture;
431 glBindTexture(GL_TEXTURE_2D, texture);
432 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
433 ASSERT_GL_NO_ERROR();
434
435 // Texture attachment for color attachment 0. Framebuffer should be complete.
436 GLFramebuffer FBO;
437 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
438 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
439 texture, 0, 4);
440 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
441
442 GLsizei maxSamples = 0;
443 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
444
445 // Depth/stencil renderbuffer, potentially with a different sample count.
446 GLRenderbuffer dsRenderbuffer;
447 glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbuffer);
448 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, maxSamples, GL_DEPTH_COMPONENT16, 64, 64);
449 ASSERT_GL_NO_ERROR();
450 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, dsRenderbuffer);
451
452 if (maxSamples > 4)
453 {
454 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
455 glCheckFramebufferStatus(GL_FRAMEBUFFER));
456 }
457 else
458 {
459 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
460 }
461
462 // Color renderbuffer for color attachment 0.
463 GLRenderbuffer colorRenderbuffer;
464 glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
465 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, maxSamples, GL_RGBA4, 64, 64);
466 ASSERT_GL_NO_ERROR();
467 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
468 colorRenderbuffer);
469 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
470
471 // D3D backend doesn't implement multisampled render to texture renderbuffers correctly.
472 // http://anglebug.com/3107
473 ANGLE_SKIP_TEST_IF(IsD3D());
474
475 if (getClientMajorVersion() >= 3)
476 {
477 // Texture attachment for color attachment 1.
478 GLTexture texture2;
479 glBindTexture(GL_TEXTURE_2D, texture2);
480 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
481 ASSERT_GL_NO_ERROR();
482
483 // Attach with a potentially different number of samples.
484 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
485 texture, 0, 4);
486
487 if (maxSamples > 4)
488 {
489 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
490 glCheckFramebufferStatus(GL_FRAMEBUFFER));
491 }
492 else
493 {
494 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
495 }
496
497 // Attach with same number of samples.
498 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
499 texture, 0, maxSamples);
500 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
501 }
502 }
503
504 // Checking for framebuffer completeness using extension methods.
TEST_P(MultisampledRenderToTextureTest,FramebufferCompletenessSmallSampleCount)505 TEST_P(MultisampledRenderToTextureTest, FramebufferCompletenessSmallSampleCount)
506 {
507 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
508
509 // A sample count of '2' can be rounded up to '4' on some systems (e.g., ARM+Android).
510 GLsizei samples = 2;
511
512 // Checking that Renderbuffer and texture2d having different number of samples results
513 // in a FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
514 GLTexture texture;
515 glBindTexture(GL_TEXTURE_2D, texture);
516 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
517 ASSERT_GL_NO_ERROR();
518
519 // Texture attachment for color attachment 0. Framebuffer should be complete.
520 GLFramebuffer FBO;
521 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
522 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
523 texture, 0, samples);
524 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
525
526 // Depth/stencil renderbuffer, potentially with a different sample count.
527 GLRenderbuffer dsRenderbuffer;
528 glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbuffer);
529 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT16, 64, 64);
530 ASSERT_GL_NO_ERROR();
531 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, dsRenderbuffer);
532 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
533
534 // Color renderbuffer for color attachment 0.
535 GLRenderbuffer colorRenderbuffer;
536 glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
537 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA4, 64, 64);
538 ASSERT_GL_NO_ERROR();
539 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
540 colorRenderbuffer);
541 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
542 }
543
544 // Test mixing unsized and sized formats with multisampling. Regression test for
545 // http://crbug.com/1238327
TEST_P(MultisampledRenderToTextureTest,UnsizedTextureFormatSampleMissmatch)546 TEST_P(MultisampledRenderToTextureTest, UnsizedTextureFormatSampleMissmatch)
547 {
548 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
549 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_texture_rg"));
550
551 // Test failure introduced by Apple's changes (anglebug.com/5505)
552 ANGLE_SKIP_TEST_IF(IsMetal() && IsAMD());
553
554 GLsizei samples = 0;
555 glGetIntegerv(GL_MAX_SAMPLES, &samples);
556
557 GLTexture texture;
558 glBindTexture(GL_TEXTURE_2D, texture);
559 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 64, 64, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
560 ASSERT_GL_NO_ERROR();
561
562 // Texture attachment for color attachment 0. Framebuffer should be complete.
563 GLFramebuffer FBO;
564 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
565 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
566 texture, 0, samples);
567 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
568
569 // Depth/stencil renderbuffer, potentially with a different sample count.
570 GLRenderbuffer dsRenderbuffer;
571 glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbuffer);
572 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_STENCIL_INDEX8, 64, 64);
573 ASSERT_GL_NO_ERROR();
574 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
575 dsRenderbuffer);
576 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
577 }
578
createAndAttachColorAttachment(bool useRenderbuffer,GLsizei size,GLenum renderbufferTarget,const GLType * glType,GLint samples,GLTexture * textureOut,GLRenderbuffer * renderbufferOut)579 void MultisampledRenderToTextureTest::createAndAttachColorAttachment(
580 bool useRenderbuffer,
581 GLsizei size,
582 GLenum renderbufferTarget,
583 const GLType *glType,
584 GLint samples,
585 GLTexture *textureOut,
586 GLRenderbuffer *renderbufferOut)
587 {
588 GLenum internalFormat = glType ? glType->internalFormat : GL_RGBA;
589 GLenum format = glType ? glType->format : GL_RGBA;
590 GLenum type = glType ? glType->type : GL_UNSIGNED_BYTE;
591
592 if (useRenderbuffer)
593 {
594 if (internalFormat == GL_RGBA)
595 {
596 internalFormat = GL_RGBA8;
597 }
598 glBindRenderbuffer(GL_RENDERBUFFER, *renderbufferOut);
599 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, internalFormat, size, size);
600 glFramebufferRenderbuffer(GL_FRAMEBUFFER, renderbufferTarget, GL_RENDERBUFFER,
601 *renderbufferOut);
602 }
603 else
604 {
605 glBindTexture(GL_TEXTURE_2D, *textureOut);
606 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size, size, 0, format, type, nullptr);
607 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
609 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, renderbufferTarget, GL_TEXTURE_2D,
610 *textureOut, 0, samples);
611 }
612 ASSERT_GL_NO_ERROR();
613 }
614
createAndAttachDepthStencilAttachment(bool useRenderbuffer,GLsizei size,GLTexture * textureOut,GLRenderbuffer * renderbufferOut)615 void MultisampledRenderToTextureTest::createAndAttachDepthStencilAttachment(
616 bool useRenderbuffer,
617 GLsizei size,
618 GLTexture *textureOut,
619 GLRenderbuffer *renderbufferOut)
620 {
621 if (useRenderbuffer)
622 {
623 glBindRenderbuffer(GL_RENDERBUFFER, *renderbufferOut);
624 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, mTestSampleCount, GL_DEPTH24_STENCIL8,
625 size, size);
626 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
627 *renderbufferOut);
628 }
629 else
630 {
631 glBindTexture(GL_TEXTURE_2D, *textureOut);
632 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, size, size, 0, GL_DEPTH_STENCIL,
633 GL_UNSIGNED_INT_24_8_OES, nullptr);
634 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
635 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
636 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
637 GL_TEXTURE_2D, *textureOut, 0, mTestSampleCount);
638 }
639 ASSERT_GL_NO_ERROR();
640 }
641
colorAttachmentMultisampleDrawTestCommon(bool useRenderbuffer)642 void MultisampledRenderToTextureTest::colorAttachmentMultisampleDrawTestCommon(bool useRenderbuffer)
643 {
644 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
645
646 GLFramebuffer FBO;
647 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
648
649 // Set up color attachment and bind to FBO
650 constexpr GLsizei kSize = 6;
651 GLTexture texture;
652 GLRenderbuffer renderbuffer;
653 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
654 mTestSampleCount, &texture, &renderbuffer);
655 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
656
657 // Set viewport and clear to black
658 glViewport(0, 0, kSize, kSize);
659 glClearColor(0.0, 0.0, 0.0, 1.0);
660 glClear(GL_COLOR_BUFFER_BIT);
661
662 // Set up Green square program
663 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
664 glUseProgram(program);
665 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
666 ASSERT_NE(-1, positionLocation);
667
668 setupQuadVertexBuffer(0.5f, 0.5f);
669 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
670 glEnableVertexAttribArray(positionLocation);
671
672 // Draw green square
673 glDrawArrays(GL_TRIANGLES, 0, 6);
674 ASSERT_GL_NO_ERROR();
675
676 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
677 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
678
679 // Set up Red square program
680 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
681 glUseProgram(program2);
682 GLint positionLocation2 = glGetAttribLocation(program2, essl1_shaders::PositionAttrib());
683 ASSERT_NE(-1, positionLocation2);
684
685 setupQuadVertexBuffer(0.5f, 0.75f);
686 glVertexAttribPointer(positionLocation2, 3, GL_FLOAT, GL_FALSE, 0, 0);
687
688 // Draw red square
689 glDrawArrays(GL_TRIANGLES, 0, 6);
690 ASSERT_GL_NO_ERROR();
691
692 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
693 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::red);
694
695 glDisableVertexAttribArray(0);
696 glBindBuffer(GL_ARRAY_BUFFER, 0);
697 }
698
699 // Draw test with color attachment only.
700 TEST_P(MultisampledRenderToTextureTest, 2DColorAttachmentMultisampleDrawTest)
701 {
702 colorAttachmentMultisampleDrawTestCommon(false);
703 }
704
705 // Draw test with renderbuffer color attachment only
TEST_P(MultisampledRenderToTextureTest,RenderbufferColorAttachmentMultisampleDrawTest)706 TEST_P(MultisampledRenderToTextureTest, RenderbufferColorAttachmentMultisampleDrawTest)
707 {
708 colorAttachmentMultisampleDrawTestCommon(true);
709 }
710
711 // Test draw with a scissored region.
TEST_P(MultisampledRenderToTextureTest,ScissoredDrawTest)712 TEST_P(MultisampledRenderToTextureTest, ScissoredDrawTest)
713 {
714 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
715
716 GLFramebuffer FBO;
717 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
718
719 // Set up color attachment and bind to FBO
720 constexpr GLsizei kSize = 1024;
721 GLTexture texture;
722 GLRenderbuffer renderbuffer;
723 createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT0, nullptr, mTestSampleCount,
724 &texture, &renderbuffer);
725 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
726
727 // Set viewport and clear to black
728 glViewport(0, 0, kSize, kSize);
729 glClearColor(0.0, 0.0, 0.0, 1.0);
730 glClear(GL_COLOR_BUFFER_BIT);
731
732 // Set up Green square program
733 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
734 glUseProgram(drawGreen);
735
736 // Draw green square
737 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
738 ASSERT_GL_NO_ERROR();
739
740 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
741 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
742 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
743 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
744 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
745
746 // Set up Red square program
747 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
748 glUseProgram(drawRed);
749
750 // Draw a scissored red square
751
752 constexpr GLint kScissorStartX = 1;
753 constexpr GLint kScissorStartY = 103;
754 constexpr GLint kScissorEndX = 285;
755 constexpr GLint kScissorEndY = 402;
756
757 glEnable(GL_SCISSOR_TEST);
758 glScissor(kScissorStartX, kScissorStartY, kScissorEndX - kScissorStartX + 1,
759 kScissorEndY - kScissorStartY + 1);
760 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
761 ASSERT_GL_NO_ERROR();
762
763 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
764 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
765 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
766 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
767 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
768
769 EXPECT_PIXEL_COLOR_EQ(kScissorStartX, kScissorStartY, GLColor::red);
770 EXPECT_PIXEL_COLOR_EQ(kScissorEndX, kScissorStartY, GLColor::red);
771 EXPECT_PIXEL_COLOR_EQ(kScissorStartX, kScissorEndY, GLColor::red);
772 EXPECT_PIXEL_COLOR_EQ(kScissorEndX, kScissorEndY, GLColor::red);
773
774 EXPECT_PIXEL_COLOR_EQ(kScissorStartX - 1, kScissorStartY, GLColor::green);
775 EXPECT_PIXEL_COLOR_EQ(kScissorStartX, kScissorStartY - 1, GLColor::green);
776 EXPECT_PIXEL_COLOR_EQ(kScissorEndX + 1, kScissorStartY, GLColor::green);
777 EXPECT_PIXEL_COLOR_EQ(kScissorEndX, kScissorStartY - 1, GLColor::green);
778 EXPECT_PIXEL_COLOR_EQ(kScissorStartX - 1, kScissorEndY, GLColor::green);
779 EXPECT_PIXEL_COLOR_EQ(kScissorStartX, kScissorEndY + 1, GLColor::green);
780 EXPECT_PIXEL_COLOR_EQ(kScissorEndX + 1, kScissorEndY, GLColor::green);
781 EXPECT_PIXEL_COLOR_EQ(kScissorEndX, kScissorEndY + 1, GLColor::green);
782 }
783
784 // Test transform feedback with state change. In the Vulkan backend, this results in an implicit
785 // break of the render pass, and must work correctly with respect to the subpass index that's used.
TEST_P(MultisampledRenderToTextureES3Test,TransformFeedbackTest)786 TEST_P(MultisampledRenderToTextureES3Test, TransformFeedbackTest)
787 {
788 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
789
790 GLFramebuffer FBO;
791 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
792
793 // Set up color attachment and bind to FBO
794 constexpr GLsizei kSize = 1024;
795 GLTexture texture;
796 GLRenderbuffer renderbuffer;
797 createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT0, nullptr, mTestSampleCount,
798 &texture, &renderbuffer);
799 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
800
801 // Set up transform feedback.
802 GLTransformFeedback xfb;
803 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
804
805 constexpr size_t kXfbBufferSize = 1024; // arbitrary number
806 GLBuffer xfbBuffer;
807 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
808 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kXfbBufferSize, nullptr, GL_STATIC_DRAW);
809 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
810
811 // Set up program with transform feedback
812 std::vector<std::string> tfVaryings = {"gl_Position"};
813 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(drawColor, essl1_shaders::vs::Simple(),
814 essl1_shaders::fs::UniformColor(), tfVaryings,
815 GL_INTERLEAVED_ATTRIBS);
816 glUseProgram(drawColor);
817 GLint colorUniformLocation =
818 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
819 ASSERT_NE(colorUniformLocation, -1);
820
821 // Start transform feedback
822 glBeginTransformFeedback(GL_TRIANGLES);
823
824 // Set viewport and clear to black
825 glViewport(0, 0, kSize, kSize);
826 glClearColor(0.0, 0.0, 0.0, 1.0);
827 glClear(GL_COLOR_BUFFER_BIT);
828
829 // Draw green. There's no unresolve operation as the framebuffer has just been cleared.
830 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
831 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
832 ASSERT_GL_NO_ERROR();
833
834 // Incur a state change while transform feedback is active. This will result in a pipeline
835 // rebind in the Vulkan backend, which should necessarily break the render pass when
836 // VK_EXT_transform_feedback is used.
837 glEnable(GL_BLEND);
838 glBlendFunc(GL_ONE, GL_ONE);
839
840 // Draw red. The implicit render pass break means that there's an unresolve operation.
841 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
842 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
843
844 // End transform feedback
845 glEndTransformFeedback();
846
847 // Expect yellow.
848 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
849 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::yellow);
850 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::yellow);
851 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::yellow);
852 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
853 }
854
855 // Draw test using both color and depth attachments.
856 TEST_P(MultisampledRenderToTextureTest, 2DColorDepthMultisampleDrawTest)
857 {
858 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
859
860 constexpr GLsizei kSize = 6;
861 // create complete framebuffer with depth buffer
862 GLTexture texture;
863 glBindTexture(GL_TEXTURE_2D, texture);
864 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
865 ASSERT_GL_NO_ERROR();
866
867 GLFramebuffer FBO;
868 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
869 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
870 texture, 0, 4);
871
872 GLRenderbuffer renderbuffer;
873 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
874 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kSize, kSize);
875 ASSERT_GL_NO_ERROR();
876 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
877 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
878
879 // Set viewport and clear framebuffer
880 glViewport(0, 0, kSize, kSize);
881 glClearColor(0.0, 0.0, 0.0, 1.0);
882 glClearDepthf(0.5f);
883 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
884
885 // Draw first green square
886 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
887 glEnable(GL_DEPTH_TEST);
888 glDepthFunc(GL_GREATER);
889 glUseProgram(program);
890 GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
891 ASSERT_NE(-1, positionLocation);
892
893 setupQuadVertexBuffer(0.8f, 0.5f);
894 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
895 glEnableVertexAttribArray(positionLocation);
896
897 // Tests that TRIANGLES works.
898 glDrawArrays(GL_TRIANGLES, 0, 6);
899 ASSERT_GL_NO_ERROR();
900
901 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
902 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
903
904 // Draw red square behind green square
905 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
906 glUseProgram(program2);
907 GLint positionLocation2 = glGetAttribLocation(program2, essl1_shaders::PositionAttrib());
908 ASSERT_NE(-1, positionLocation2);
909
910 setupQuadVertexBuffer(0.7f, 1.0f);
911 glVertexAttribPointer(positionLocation2, 3, GL_FLOAT, GL_FALSE, 0, 0);
912
913 glDrawArrays(GL_TRIANGLES, 0, 6);
914 ASSERT_GL_NO_ERROR();
915 glDisable(GL_DEPTH_TEST);
916
917 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
918 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
919
920 glDisableVertexAttribArray(0);
921 glBindBuffer(GL_ARRAY_BUFFER, 0);
922 }
923
924 // Draw test using color attachment with multiple levels.
TEST_P(MultisampledRenderToTextureTest,MultipleLevelsMultisampleDraw2DColor)925 TEST_P(MultisampledRenderToTextureTest, MultipleLevelsMultisampleDraw2DColor)
926 {
927 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
928
929 constexpr GLsizei kSize = 256;
930 const GLuint desiredLevelCount = gl::log2(kSize) + 1;
931 const std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
932
933 // Create texture to be used as color attachment
934 GLTexture texture;
935 glBindTexture(GL_TEXTURE_2D, texture);
936
937 // Initialize all levels
938 for (GLuint level = 0; level < desiredLevelCount; level++)
939 {
940 GLsizei levelSize = kSize >> level;
941 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
942 GL_UNSIGNED_BYTE, greenColor.data());
943 }
944
945 GLFramebuffer FBO;
946 GLFramebuffer readFbo;
947
948 // Multisample draw and verify with each level
949 for (GLuint currentLevel = 0; currentLevel < desiredLevelCount; currentLevel++)
950 {
951 GLsizei currentLevelSize = kSize >> currentLevel;
952
953 // Attach a texture level as color attachment
954 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
955 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
956 texture, currentLevel, 4);
957 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
958
959 // Draw blue color
960 glViewport(0, 0, currentLevelSize, currentLevelSize);
961 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
962 glUseProgram(program);
963 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
964 ASSERT_GL_NO_ERROR();
965
966 // Verify blue color
967 glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
968 glBindTexture(GL_TEXTURE_2D, texture);
969 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
970 currentLevel);
971 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
972
973 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
974 EXPECT_PIXEL_COLOR_EQ(currentLevelSize / 2, currentLevelSize / 2, GLColor::blue);
975 }
976 }
977
978 // Draw test using color attachment with multiple levels and multiple render targets.
TEST_P(MultisampledRenderToTextureES3Test,MultipleLevelsMultisampleMRTDraw2DColor)979 TEST_P(MultisampledRenderToTextureES3Test, MultipleLevelsMultisampleMRTDraw2DColor)
980 {
981 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
982 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
983
984 constexpr GLsizei kSize = 256;
985 const GLuint desiredLevelCount = gl::log2(kSize) + 1;
986 const std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
987
988 // Create texture to be used as color attachment
989 GLTexture texture;
990 glBindTexture(GL_TEXTURE_2D, texture);
991
992 // Initialize all levels
993 for (GLuint level = 0; level < desiredLevelCount; level++)
994 {
995 GLsizei levelSize = kSize >> level;
996 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
997 GL_UNSIGNED_BYTE, greenColor.data());
998 }
999
1000 // Multisample MRT draw and verify
1001 const std::string frag = R"(#extension GL_EXT_draw_buffers : enable
1002 precision highp float;
1003 uniform mediump vec4 u_color;
1004 void main()
1005 {
1006 gl_FragData[0] = u_color;
1007 gl_FragData[1] = u_color;
1008 })";
1009 ANGLE_GL_PROGRAM(mrtProgram, essl1_shaders::vs::Simple(), frag.c_str());
1010 glUseProgram(mrtProgram);
1011 GLint colorUniformLocation = glGetUniformLocation(mrtProgram, "u_color");
1012 ASSERT_NE(colorUniformLocation, -1);
1013 glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
1014
1015 // Attach texture level 0 and 1 as color attachment
1016 GLFramebuffer FBO;
1017 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
1018 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1019 texture, 0, 4);
1020 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
1021 texture, 1, 4);
1022 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1023
1024 // Draw yellow color to both attachments
1025 glViewport(0, 0, kSize, kSize);
1026 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1027 glDrawBuffers(2, kDrawBuffers);
1028 ASSERT_GL_NO_ERROR();
1029 drawQuad(mrtProgram, essl1_shaders::PositionAttrib(), 0.5f);
1030 ASSERT_GL_NO_ERROR();
1031
1032 // Verify yellow color in common render area of both attachments
1033 GLFramebuffer readFbo;
1034 glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
1035 glBindTexture(GL_TEXTURE_2D, texture);
1036
1037 // Verify level 0
1038 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1039 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1040 EXPECT_PIXEL_COLOR_EQ((kSize >> 1) - 1, (kSize >> 1) - 1, GLColor::yellow);
1041
1042 // Verify level 1
1043 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
1044 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1045 EXPECT_PIXEL_COLOR_EQ((kSize >> 1) - 1, (kSize >> 1) - 1, GLColor::yellow);
1046 }
1047
readPixelsTestCommon(bool useRenderbuffer)1048 void MultisampledRenderToTextureES3Test::readPixelsTestCommon(bool useRenderbuffer)
1049 {
1050 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1051
1052 GLFramebuffer FBO;
1053 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
1054
1055 constexpr GLsizei kSize = 6;
1056 GLTexture texture;
1057 GLRenderbuffer renderbuffer;
1058 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1059 mTestSampleCount, &texture, &renderbuffer);
1060 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1061
1062 // Set viewport and clear to red
1063 glViewport(0, 0, kSize, kSize);
1064 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1065 glClear(GL_COLOR_BUFFER_BIT);
1066 ASSERT_GL_NO_ERROR();
1067
1068 // Bind Pack Pixel Buffer and read to it
1069 GLBuffer PBO;
1070 glBindBuffer(GL_PIXEL_PACK_BUFFER, PBO);
1071 glBufferData(GL_PIXEL_PACK_BUFFER, 4 * kSize * kSize, nullptr, GL_STATIC_DRAW);
1072 glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1073 ASSERT_GL_NO_ERROR();
1074
1075 // Retrieving pixel color
1076 void *mappedPtr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
1077 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
1078 EXPECT_GL_NO_ERROR();
1079
1080 EXPECT_EQ(GLColor::red, dataColor[0]);
1081
1082 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
1083 EXPECT_GL_NO_ERROR();
1084 }
1085
1086 // Read pixels with pack buffer. ES3+.
TEST_P(MultisampledRenderToTextureES3Test,ReadPixelsTest)1087 TEST_P(MultisampledRenderToTextureES3Test, ReadPixelsTest)
1088 {
1089 readPixelsTestCommon(false);
1090 }
1091
1092 // Read pixels with pack buffer from renderbuffer. ES3+.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferReadPixelsTest)1093 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferReadPixelsTest)
1094 {
1095 // D3D backend doesn't implement multisampled render to texture renderbuffers correctly.
1096 // http://anglebug.com/3107
1097 ANGLE_SKIP_TEST_IF(IsD3D());
1098
1099 readPixelsTestCommon(true);
1100 }
1101
copyTexImageTestCommon(bool useRenderbuffer)1102 void MultisampledRenderToTextureTest::copyTexImageTestCommon(bool useRenderbuffer)
1103 {
1104 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1105 constexpr GLsizei kSize = 16;
1106
1107 setupCopyTexProgram();
1108
1109 GLFramebuffer FBO;
1110 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
1111
1112 GLTexture texture;
1113 GLRenderbuffer renderbuffer;
1114 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1115 mTestSampleCount, &texture, &renderbuffer);
1116 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1117
1118 // Set color for framebuffer
1119 glClearColor(0.25f, 1.0f, 0.75f, 0.5f);
1120 glClear(GL_COLOR_BUFFER_BIT);
1121 ASSERT_GL_NO_ERROR();
1122
1123 GLTexture copyToTex;
1124 glBindTexture(GL_TEXTURE_2D, copyToTex);
1125
1126 // Disable mipmapping
1127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1129
1130 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kSize, kSize, 0);
1131 ASSERT_GL_NO_ERROR();
1132
1133 verifyResults(copyToTex, {64, 255, 191, 255}, kSize, 0, 0, kSize, kSize);
1134 }
1135
1136 // CopyTexImage from a multisampled texture functionality test.
TEST_P(MultisampledRenderToTextureTest,CopyTexImageTest)1137 TEST_P(MultisampledRenderToTextureTest, CopyTexImageTest)
1138 {
1139 copyTexImageTestCommon(false);
1140 }
1141
1142 // CopyTexImage from a multisampled texture functionality test using renderbuffer.
TEST_P(MultisampledRenderToTextureTest,RenderbufferCopyTexImageTest)1143 TEST_P(MultisampledRenderToTextureTest, RenderbufferCopyTexImageTest)
1144 {
1145 copyTexImageTestCommon(true);
1146 }
1147
copyTexSubImageTestCommon(bool useRenderbuffer)1148 void MultisampledRenderToTextureTest::copyTexSubImageTestCommon(bool useRenderbuffer)
1149 {
1150 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1151 constexpr GLsizei kSize = 16;
1152
1153 setupCopyTexProgram();
1154
1155 GLFramebuffer copyFBO0;
1156 glBindFramebuffer(GL_FRAMEBUFFER, copyFBO0);
1157
1158 // Create color attachment for copyFBO0
1159 GLTexture texture;
1160 GLRenderbuffer renderbuffer;
1161 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1162 mTestSampleCount, &texture, &renderbuffer);
1163 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1164
1165 GLFramebuffer copyFBO1;
1166 glBindFramebuffer(GL_FRAMEBUFFER, copyFBO1);
1167
1168 // Create color attachment for copyFBO1
1169 GLTexture texture1;
1170 GLRenderbuffer renderbuffer1;
1171 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1172 mTestSampleCount, &texture1, &renderbuffer1);
1173 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1174
1175 // Set color for copyFBO0
1176 glBindFramebuffer(GL_FRAMEBUFFER, copyFBO0);
1177 glClearColor(0.25f, 1.0f, 0.75f, 0.5f);
1178 glClear(GL_COLOR_BUFFER_BIT);
1179 ASSERT_GL_NO_ERROR();
1180
1181 // Set color for copyFBO1
1182 glBindFramebuffer(GL_FRAMEBUFFER, copyFBO1);
1183 glClearColor(1.0f, 0.75f, 0.5f, 0.25f);
1184 glClear(GL_COLOR_BUFFER_BIT);
1185 ASSERT_GL_NO_ERROR();
1186
1187 GLTexture copyToTex;
1188 glBindTexture(GL_TEXTURE_2D, copyToTex);
1189
1190 // Disable mipmapping
1191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1193
1194 // copyFBO0 -> copyToTex
1195 // copyToTex should hold what was originally in copyFBO0 : (.25, 1, .75, .5)
1196 glBindFramebuffer(GL_FRAMEBUFFER, copyFBO0);
1197 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kSize, kSize, 0);
1198 ASSERT_GL_NO_ERROR();
1199
1200 const GLColor expected0(64, 255, 191, 255);
1201 verifyResults(copyToTex, expected0, kSize, 0, 0, kSize, kSize);
1202
1203 // copyFBO[1] - copySubImage -> copyToTex
1204 // copyToTex should have subportion what was in copyFBO[1] : (1, .75, .5, .25)
1205 // The rest should still be untouched: (.25, 1, .75, .5)
1206 GLint half = kSize / 2;
1207 glBindFramebuffer(GL_FRAMEBUFFER, copyFBO1);
1208 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, half, half, half, half, half, half);
1209 ASSERT_GL_NO_ERROR();
1210
1211 const GLColor expected1(255, 191, 127, 255);
1212 verifyResults(copyToTex, expected1, kSize, half, half, kSize, kSize);
1213
1214 // Verify rest is untouched
1215 verifyResults(copyToTex, expected0, kSize, 0, 0, half, half);
1216 verifyResults(copyToTex, expected0, kSize, 0, half, half, kSize);
1217 verifyResults(copyToTex, expected0, kSize, half, 0, kSize, half);
1218 }
1219
1220 // CopyTexSubImage from a multisampled texture functionality test.
TEST_P(MultisampledRenderToTextureTest,CopyTexSubImageTest)1221 TEST_P(MultisampledRenderToTextureTest, CopyTexSubImageTest)
1222 {
1223 copyTexSubImageTestCommon(false);
1224 }
1225
1226 // CopyTexSubImage from a multisampled texture functionality test with renderbuffers
TEST_P(MultisampledRenderToTextureTest,RenderbufferCopyTexSubImageTest)1227 TEST_P(MultisampledRenderToTextureTest, RenderbufferCopyTexSubImageTest)
1228 {
1229 copyTexSubImageTestCommon(true);
1230 }
1231
blitFramebufferTestCommon(bool useRenderbuffer)1232 void MultisampledRenderToTextureES3Test::blitFramebufferTestCommon(bool useRenderbuffer)
1233 {
1234 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1235
1236 constexpr GLsizei kSize = 16;
1237
1238 GLFramebuffer fboMS;
1239 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1240
1241 // Create multisampled framebuffer to use as source.
1242 GLRenderbuffer depthMS;
1243 glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
1244 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, kSize, kSize);
1245 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
1246 ASSERT_GL_NO_ERROR();
1247
1248 GLTexture textureMS;
1249 GLRenderbuffer renderbufferMS;
1250 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1251 mTestSampleCount, &textureMS, &renderbufferMS);
1252 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1253
1254 // Clear depth to 0.5 and color to green.
1255 glClearDepthf(0.5f);
1256 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1257 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1258 glFlush();
1259 ASSERT_GL_NO_ERROR();
1260
1261 // Draw red into the multisampled color buffer.
1262 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1263 ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1264 glEnable(GL_DEPTH_TEST);
1265 drawQuad(drawRed, essl1_shaders::PositionAttrib(), -0.05f);
1266 drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.05f);
1267 ASSERT_GL_NO_ERROR();
1268
1269 // Create single sampled framebuffer to use as dest.
1270 GLFramebuffer fboSS;
1271 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
1272 GLTexture colorSS;
1273 glBindTexture(GL_TEXTURE_2D, colorSS);
1274 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1275 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorSS, 0);
1276 ASSERT_GL_NO_ERROR();
1277
1278 // Bind MS to READ as SS is already bound to DRAW.
1279 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMS);
1280 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1281 ASSERT_GL_NO_ERROR();
1282
1283 // Bind SS to READ so we can readPixels from it
1284 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
1285
1286 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1287 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
1288 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
1289 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
1290 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::red);
1291 ASSERT_GL_NO_ERROR();
1292 }
1293
1294 // BlitFramebuffer functionality test. ES3+.
TEST_P(MultisampledRenderToTextureES3Test,BlitFramebufferTest)1295 TEST_P(MultisampledRenderToTextureES3Test, BlitFramebufferTest)
1296 {
1297 blitFramebufferTestCommon(false);
1298 }
1299
1300 // BlitFramebuffer functionality test with renderbuffer. ES3+.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferBlitFramebufferTest)1301 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferBlitFramebufferTest)
1302 {
1303 blitFramebufferTestCommon(true);
1304 }
1305
1306 // GenerateMipmap functionality test
TEST_P(MultisampledRenderToTextureTest,GenerateMipmapTest)1307 TEST_P(MultisampledRenderToTextureTest, GenerateMipmapTest)
1308 {
1309 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1310 constexpr GLsizei kSize = 64;
1311
1312 setupCopyTexProgram();
1313 glUseProgram(mCopyTextureProgram);
1314
1315 // Initialize texture with blue
1316 GLTexture texture;
1317 glBindTexture(GL_TEXTURE_2D, texture);
1318 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kSize, kSize, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
1319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1321
1322 GLFramebuffer FBO;
1323 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
1324 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1325 texture, 0, 4);
1326 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1327 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
1328 glClear(GL_COLOR_BUFFER_BIT);
1329 glViewport(0, 0, kSize, kSize);
1330 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1331 ASSERT_GL_NO_ERROR();
1332
1333 // Generate mipmap
1334 glGenerateMipmap(GL_TEXTURE_2D);
1335 ASSERT_GL_NO_ERROR();
1336
1337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1338
1339 // Now draw the texture to various different sized areas.
1340 clearAndDrawQuad(mCopyTextureProgram, kSize, kSize);
1341 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::blue);
1342
1343 // Use mip level 1
1344 clearAndDrawQuad(mCopyTextureProgram, kSize / 2, kSize / 2);
1345 EXPECT_PIXEL_COLOR_EQ(kSize / 4, kSize / 4, GLColor::blue);
1346
1347 // Use mip level 2
1348 clearAndDrawQuad(mCopyTextureProgram, kSize / 4, kSize / 4);
1349 EXPECT_PIXEL_COLOR_EQ(kSize / 8, kSize / 8, GLColor::blue);
1350
1351 ASSERT_GL_NO_ERROR();
1352 }
1353
drawCopyThenBlendCommon(bool useRenderbuffer)1354 void MultisampledRenderToTextureTest::drawCopyThenBlendCommon(bool useRenderbuffer)
1355 {
1356 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1357 constexpr GLsizei kSize = 64;
1358
1359 setupCopyTexProgram();
1360
1361 GLFramebuffer fboMS;
1362 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1363
1364 // Create multisampled framebuffer to draw into
1365 GLTexture textureMS;
1366 GLRenderbuffer renderbufferMS;
1367 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1368 mTestSampleCount, &textureMS, &renderbufferMS);
1369 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1370
1371 // Draw red into the multisampled color buffer.
1372 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1373 glUseProgram(drawColor);
1374 GLint colorUniformLocation =
1375 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1376 ASSERT_NE(colorUniformLocation, -1);
1377
1378 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1379 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1380 ASSERT_GL_NO_ERROR();
1381
1382 // Create a texture and copy into it.
1383 GLTexture texture;
1384 glBindTexture(GL_TEXTURE_2D, texture);
1385 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1387 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1388
1389 // Draw again into the framebuffer, this time blending. This tests that the framebuffer's data,
1390 // residing in the single-sampled texture, is available to the multisampled intermediate image
1391 // for blending.
1392
1393 // Blend half-transparent green into the multisampled color buffer.
1394 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
1395 glEnable(GL_BLEND);
1396 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1397 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1398 ASSERT_GL_NO_ERROR();
1399
1400 // Verify that the texture is now yellow
1401 const GLColor kExpected(127, 127, 0, 191);
1402 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
1403 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
1404 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
1405 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
1406
1407 // For completeness, verify that the texture used as copy target is red.
1408 ASSERT_GL_NO_ERROR();
1409 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
1410
1411 ASSERT_GL_NO_ERROR();
1412 }
1413
1414 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
1415 // following draw should retain the data written by the first draw command.
TEST_P(MultisampledRenderToTextureTest,DrawCopyThenBlend)1416 TEST_P(MultisampledRenderToTextureTest, DrawCopyThenBlend)
1417 {
1418 drawCopyThenBlendCommon(false);
1419 }
1420
1421 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
1422 // following draw should retain the data written by the first draw command. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureTest,RenderbufferDrawCopyThenBlend)1423 TEST_P(MultisampledRenderToTextureTest, RenderbufferDrawCopyThenBlend)
1424 {
1425 drawCopyThenBlendCommon(true);
1426 }
1427
clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer)1428 void MultisampledRenderToTextureTest::clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer)
1429 {
1430 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1431 constexpr GLsizei kSize = 64;
1432
1433 setupCopyTexProgram();
1434
1435 GLFramebuffer fboMS;
1436 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1437
1438 // Create multisampled framebuffer to draw into
1439 GLTexture textureMS;
1440 GLRenderbuffer renderbufferMS;
1441 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1442 mTestSampleCount, &textureMS, &renderbufferMS);
1443 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1444
1445 // Draw red into the multisampled color buffer.
1446 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1447 glUseProgram(drawColor);
1448 GLint colorUniformLocation =
1449 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1450 ASSERT_NE(colorUniformLocation, -1);
1451
1452 // Clear the framebuffer.
1453 glClearColor(0.1f, 0.9f, 0.2f, 0.8f);
1454 glClear(GL_COLOR_BUFFER_BIT);
1455
1456 // Then draw into it.
1457 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1458 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1459 ASSERT_GL_NO_ERROR();
1460
1461 // Blend green into it. This makes sure that the blend after the resolve doesn't have different
1462 // state from the one used here.
1463 glEnable(GL_BLEND);
1464 glBlendFunc(GL_ONE, GL_ONE);
1465 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1466 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1467 ASSERT_GL_NO_ERROR();
1468
1469 // Create a texture and copy into it.
1470 GLTexture texture;
1471 glBindTexture(GL_TEXTURE_2D, texture);
1472 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1475
1476 // Draw again into the framebuffer, this time blending. This tests that the framebuffer's data,
1477 // residing in the single-sampled texture, is available to the multisampled intermediate image
1478 // for blending.
1479
1480 // Blend blue into the multisampled color buffer.
1481 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1482 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1483 ASSERT_GL_NO_ERROR();
1484
1485 // Verify that the texture is now white
1486 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
1487 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::white);
1488 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::white);
1489 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::white);
1490
1491 // Once again, clear and draw so the program is used again in the way it was first used.
1492 glClear(GL_COLOR_BUFFER_BIT);
1493 glDisable(GL_BLEND);
1494 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1495 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1496
1497 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1498 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
1499 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
1500 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
1501
1502 // For completeness, verify that the texture used as copy target is yellow.
1503 ASSERT_GL_NO_ERROR();
1504 verifyResults(texture, GLColor::yellow, kSize, 0, 0, kSize, kSize);
1505
1506 ASSERT_GL_NO_ERROR();
1507 }
1508
1509 // Clear&Draw, copy, then blend with same program. The copy will make sure an implicit resolve
1510 // happens. The second draw should retain the data written by the first draw command ("unresolve"
1511 // operation). The same program is used for the first and second draw calls, and the fact that the
1512 // attachment is cleared or unresolved should not cause issues. In the Vulkan backend, the program
1513 // will be used in different subpass indices, so two graphics pipelines should be created for it.
TEST_P(MultisampledRenderToTextureTest,ClearDrawCopyThenBlendSameProgram)1514 TEST_P(MultisampledRenderToTextureTest, ClearDrawCopyThenBlendSameProgram)
1515 {
1516 clearDrawCopyThenBlendSameProgramCommon(false);
1517 }
1518
1519 // Same as ClearDrawCopyThenBlendSameProgram but with renderbuffers
TEST_P(MultisampledRenderToTextureTest,RenderbufferClearDrawCopyThenBlendSameProgram)1520 TEST_P(MultisampledRenderToTextureTest, RenderbufferClearDrawCopyThenBlendSameProgram)
1521 {
1522 clearDrawCopyThenBlendSameProgramCommon(true);
1523 }
1524
1525 // Similar to RenderbufferClearDrawCopyThenBlendSameProgram, but with the depth/stencil attachment
1526 // being unresolved only.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferClearDrawCopyThenBlendWithDepthStencilSameProgram)1527 TEST_P(MultisampledRenderToTextureES3Test,
1528 RenderbufferClearDrawCopyThenBlendWithDepthStencilSameProgram)
1529 {
1530 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1531
1532 constexpr GLsizei kSize = 64;
1533
1534 setupCopyTexProgram();
1535
1536 GLFramebuffer fboMS;
1537 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1538
1539 // Create multisampled framebuffer to draw into
1540 GLTexture color;
1541 glBindTexture(GL_TEXTURE_2D, color);
1542 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1543 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
1544 0, 4);
1545
1546 GLRenderbuffer depthStencil;
1547 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
1548 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
1549 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1550 depthStencil);
1551 ASSERT_GL_NO_ERROR();
1552 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1553
1554 // Draw red into the multisampled color buffer.
1555 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1556 glUseProgram(drawColor);
1557 GLint colorUniformLocation =
1558 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1559 ASSERT_NE(colorUniformLocation, -1);
1560
1561 // Enable write to depth/stencil so the attachment has valid contents, but always pass the test.
1562 glEnable(GL_DEPTH_TEST);
1563 glDepthFunc(GL_ALWAYS);
1564
1565 glEnable(GL_STENCIL_TEST);
1566 glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
1567 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1568 glStencilMask(0xFF);
1569
1570 // Clear the framebuffer.
1571 glClearColor(0.1f, 0.9f, 0.2f, 0.8f);
1572 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1573
1574 // Then draw into it.
1575 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1576 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f);
1577 ASSERT_GL_NO_ERROR();
1578
1579 // Blend green into it. This makes sure that the blend after the resolve doesn't have different
1580 // state from the one used here. Additionally, test that the previous draw output the correct
1581 // depth/stencil data. Again, this makes sure that the draw call after the resolve doesn't have
1582 // different has depth/stencil test state.
1583
1584 // If depth is not set to 1, rendering would fail.
1585 glDepthFunc(GL_LESS);
1586
1587 // If stencil is not set to 0x55, rendering would fail.
1588 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
1589 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1590
1591 glEnable(GL_BLEND);
1592 glBlendFunc(GL_ONE, GL_ONE);
1593 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1594 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
1595 ASSERT_GL_NO_ERROR();
1596
1597 // Create a texture and copy into it.
1598 GLTexture texture;
1599 glBindTexture(GL_TEXTURE_2D, texture);
1600 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1601 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1602 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1603
1604 // Clear color (but not depth/stencil), and draw again into the framebuffer, this time blending.
1605 // Additionally, make sure the depth/stencil data are retained.
1606
1607 // Clear color (to blue), but not depth/stencil.
1608 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
1609 glClear(GL_COLOR_BUFFER_BIT);
1610
1611 // Blend green into the multisampled color buffer.
1612 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1613 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.9f);
1614 ASSERT_GL_NO_ERROR();
1615
1616 // Verify that the texture is now cyan
1617 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
1618 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::cyan);
1619 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::cyan);
1620 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::cyan);
1621
1622 // Once again, clear and draw so the program is used again in the way it was first used.
1623 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1624 glDisable(GL_BLEND);
1625 glDepthFunc(GL_ALWAYS);
1626 glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
1627 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1628 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1629 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1630
1631 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1632 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
1633 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
1634 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
1635
1636 // For completeness, verify that the texture used as copy target is yellow.
1637 ASSERT_GL_NO_ERROR();
1638 verifyResults(texture, GLColor::yellow, kSize, 0, 0, kSize, kSize);
1639
1640 ASSERT_GL_NO_ERROR();
1641 }
1642
drawCopyDrawThenMaskedClearCommon(bool useRenderbuffer)1643 void MultisampledRenderToTextureTest::drawCopyDrawThenMaskedClearCommon(bool useRenderbuffer)
1644 {
1645 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1646 constexpr GLsizei kSize = 64;
1647
1648 setupCopyTexProgram();
1649
1650 GLFramebuffer fboMS;
1651 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1652
1653 // Create multisampled framebuffer to draw into
1654 GLTexture textureMS;
1655 GLRenderbuffer renderbufferMS;
1656 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1657 mTestSampleCount, &textureMS, &renderbufferMS);
1658 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1659
1660 // Draw red into the multisampled color buffer.
1661 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1662 glUseProgram(drawColor);
1663 GLint colorUniformLocation =
1664 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1665 ASSERT_NE(colorUniformLocation, -1);
1666
1667 // Draw into framebuffer.
1668 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1669 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1670 ASSERT_GL_NO_ERROR();
1671
1672 // Create a texture and copy into it.
1673 GLTexture texture;
1674 glBindTexture(GL_TEXTURE_2D, texture);
1675 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1676 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1677 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1678
1679 // Draw again into the framebuffer, this time blending. Afterwards, issue a masked clear. This
1680 // ensures that previous resolved data is unresolved, and mid-render-pass clears work correctly.
1681
1682 // Draw green into the multisampled color buffer.
1683 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1684 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1685 ASSERT_GL_NO_ERROR();
1686
1687 // Issue a masked clear.
1688 glClearColor(0.1f, 0.9f, 1.0f, 0.8f);
1689 glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
1690 glClear(GL_COLOR_BUFFER_BIT);
1691
1692 // Verify that the texture is now cyan
1693 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
1694 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::cyan);
1695 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::cyan);
1696 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::cyan);
1697
1698 // For completeness, verify that the texture used as copy target is red.
1699 ASSERT_GL_NO_ERROR();
1700 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
1701
1702 ASSERT_GL_NO_ERROR();
1703 }
1704
1705 // Draw, copy, draw then issue a masked clear. The copy will make sure an implicit resolve
1706 // happens. The second draw should retain the data written by the first draw command ("unresolve"
1707 // operation). The final clear uses a draw call to perform the clear in the Vulkan backend, and it
1708 // should use the correct subpass index.
TEST_P(MultisampledRenderToTextureTest,DrawCopyDrawThenMaskedClear)1709 TEST_P(MultisampledRenderToTextureTest, DrawCopyDrawThenMaskedClear)
1710 {
1711 drawCopyDrawThenMaskedClearCommon(false);
1712 }
1713
1714 // Same as DrawCopyDrawThenMaskedClearCommon but with renderbuffers
TEST_P(MultisampledRenderToTextureTest,RenderbufferDrawCopyDrawThenMaskedClear)1715 TEST_P(MultisampledRenderToTextureTest, RenderbufferDrawCopyDrawThenMaskedClear)
1716 {
1717 drawCopyDrawThenMaskedClearCommon(true);
1718 }
1719
drawCopyDrawAttachInvalidatedThenDrawCommon(bool useRenderbuffer)1720 void MultisampledRenderToTextureES3Test::drawCopyDrawAttachInvalidatedThenDrawCommon(
1721 bool useRenderbuffer)
1722 {
1723 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1724 constexpr GLsizei kSize = 64;
1725
1726 setupCopyTexProgram();
1727
1728 GLFramebuffer fboMS;
1729 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1730
1731 // Create multisampled framebuffer to draw into
1732 GLTexture textureMS;
1733 GLRenderbuffer renderbufferMS;
1734 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1735 mTestSampleCount, &textureMS, &renderbufferMS);
1736 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1737
1738 // Draw red into the multisampled color buffer.
1739 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1740 glUseProgram(drawColor);
1741 GLint colorUniformLocation =
1742 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1743 ASSERT_NE(colorUniformLocation, -1);
1744
1745 // Clear and draw into framebuffer.
1746 glClear(GL_COLOR_BUFFER_BIT);
1747 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1748 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1749 ASSERT_GL_NO_ERROR();
1750
1751 // Create a texture and copy into it.
1752 GLTexture texture;
1753 glBindTexture(GL_TEXTURE_2D, texture);
1754 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1755 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1756 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1757
1758 // Draw green into framebuffer. This will unresolve color.
1759 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1760 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1761 ASSERT_GL_NO_ERROR();
1762
1763 // Create multisampled framebuffer and invalidate its attachment.
1764 GLFramebuffer invalidateFboMS;
1765 glBindFramebuffer(GL_FRAMEBUFFER, invalidateFboMS);
1766
1767 // Create multisampled framebuffer to draw into
1768 GLTexture invalidateTextureMS;
1769 GLRenderbuffer invalidateRenderbufferMS;
1770 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1771 mTestSampleCount, &invalidateTextureMS,
1772 &invalidateRenderbufferMS);
1773 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1774
1775 // Invalidate the attachment.
1776 GLenum invalidateAttachments[] = {GL_COLOR_ATTACHMENT0};
1777 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, invalidateAttachments);
1778
1779 // Replace the original framebuffer's attachment with the invalidated one.
1780 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1781 if (useRenderbuffer)
1782 {
1783 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1784 invalidateRenderbufferMS);
1785 }
1786 else
1787 {
1788 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1789 invalidateTextureMS, 0, 4);
1790 }
1791 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1792
1793 // Draw blue into the multisampled color buffer.
1794 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1795 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1796 ASSERT_GL_NO_ERROR();
1797
1798 // Verify that the texture is now blue
1799 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1800 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
1801 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
1802 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
1803
1804 // For completeness, verify that the texture used as copy target is red.
1805 ASSERT_GL_NO_ERROR();
1806 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
1807
1808 ASSERT_GL_NO_ERROR();
1809 }
1810
1811 // Draw, copy, draw, attach an invalidated image then draw. The second draw will need to unresolve
1812 // color. Attaching an invalidated image changes the framebuffer, and the following draw doesn't
1813 // require an unresolve. In the Vulkan backend, mismatches in unresolve state between framebuffer
1814 // and render pass will result in an ASSERT.
TEST_P(MultisampledRenderToTextureES3Test,DrawCopyDrawAttachInvalidatedThenDraw)1815 TEST_P(MultisampledRenderToTextureES3Test, DrawCopyDrawAttachInvalidatedThenDraw)
1816 {
1817 drawCopyDrawAttachInvalidatedThenDrawCommon(false);
1818 }
1819
1820 // Same as DrawCopyDrawAttachInvalidatedThenDraw but with renderbuffers
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDrawCopyDrawAttachInvalidatedThenDraw)1821 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawCopyDrawAttachInvalidatedThenDraw)
1822 {
1823 drawCopyDrawAttachInvalidatedThenDrawCommon(true);
1824 }
1825
1826 // Draw with a stencil-only attachment once without needing to unresolve it, and once needing to.
1827 // Regression test for a bug in the Vulkan backend where the state of stencil unresolve attachment's
1828 // existence was masked out by mistake in the framebuffer cache key, so the same framebuffer object
1829 // was used for both render passes, even though they could have different subpass counts due to
1830 // stencil unresolve.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDrawStencilThenUnresolveStencil)1831 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawStencilThenUnresolveStencil)
1832 {
1833 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1834 constexpr GLsizei kSize = 64;
1835
1836 setupCopyTexProgram();
1837
1838 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1839 glUseProgram(drawColor);
1840 GLint colorUniformLocation =
1841 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1842 ASSERT_NE(colorUniformLocation, -1);
1843
1844 GLFramebuffer fboMS;
1845 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1846
1847 // Create multisampled framebuffer to draw into
1848 GLTexture textureMS;
1849 createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT0, nullptr, mTestSampleCount,
1850 &textureMS, nullptr);
1851 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1852
1853 GLRenderbuffer dsRenderbufferMS;
1854 glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbufferMS);
1855 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, mTestSampleCount, GL_STENCIL_INDEX8, kSize,
1856 kSize);
1857 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1858 dsRenderbufferMS);
1859 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1860
1861 // Draw red once with stencil cleared, not needing unresolve
1862 glClearColor(0.1, 0.2, 0.3, 0.4);
1863 glClearStencil(0);
1864 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1865
1866 glEnable(GL_STENCIL_TEST);
1867 glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
1868 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1869 glStencilMask(0xFF);
1870
1871 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1872 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f);
1873 ASSERT_GL_NO_ERROR();
1874
1875 // Create a texture and copy color into it, this breaks the render pass
1876 GLTexture texture;
1877 glBindTexture(GL_TEXTURE_2D, texture);
1878 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1879 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1880 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1881
1882 // Clear the color, so that only stencil needs unresolving.
1883 glClear(GL_COLOR_BUFFER_BIT);
1884
1885 // Draw green, expecting correct stencil. This unresolves stencil.
1886 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
1887 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1888
1889 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1890 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f);
1891 ASSERT_GL_NO_ERROR();
1892
1893 // Verify that the texture is now green
1894 verifyResults(textureMS, GLColor::green, kSize, 0, 0, kSize, kSize);
1895
1896 // For completeness, also verify that the copy texture is red
1897 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
1898
1899 ASSERT_GL_NO_ERROR();
1900 }
1901
drawCopyDrawAttachDepthStencilClearThenDrawCommon(bool useRenderbuffer)1902 void MultisampledRenderToTextureES3Test::drawCopyDrawAttachDepthStencilClearThenDrawCommon(
1903 bool useRenderbuffer)
1904 {
1905 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
1906 constexpr GLsizei kSize = 64;
1907
1908 // http://anglebug.com/4935
1909 ANGLE_SKIP_TEST_IF(IsD3D11());
1910
1911 setupCopyTexProgram();
1912
1913 GLFramebuffer fboMS;
1914 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
1915
1916 // Create multisampled framebuffer to draw into
1917 GLTexture textureMS;
1918 GLRenderbuffer renderbufferMS;
1919 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
1920 mTestSampleCount, &textureMS, &renderbufferMS);
1921 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1922
1923 // Draw red into the multisampled color buffer.
1924 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1925 glUseProgram(drawColor);
1926 GLint colorUniformLocation =
1927 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1928 ASSERT_NE(colorUniformLocation, -1);
1929
1930 // Clear and draw into framebuffer. There is no unresolve due to clear. The clear value is
1931 // irrelevant as the contents are immediately overdrawn with the draw call.
1932 glClear(GL_COLOR_BUFFER_BIT);
1933 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
1934 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1935 ASSERT_GL_NO_ERROR();
1936
1937 // Create a texture and copy into it.
1938 GLTexture texture;
1939 glBindTexture(GL_TEXTURE_2D, texture);
1940 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
1941 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1942 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1943
1944 // Draw green into framebuffer. This will unresolve color.
1945 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
1946 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
1947 ASSERT_GL_NO_ERROR();
1948
1949 // Attach a depth/stencil attachment.
1950 GLTexture dsTextureMS;
1951 GLRenderbuffer dsRenderbufferMS;
1952 createAndAttachDepthStencilAttachment(useRenderbuffer, kSize, &dsTextureMS, &dsRenderbufferMS);
1953 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1954
1955 // Clear all attachments, so no unresolve would be necessary.
1956 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
1957 glClearDepthf(1);
1958 glClearStencil(0x55);
1959 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1960
1961 // If depth is not cleared to 1, rendering would fail.
1962 glEnable(GL_DEPTH_TEST);
1963 glDepthFunc(GL_LESS);
1964
1965 // If stencil is not cleared to 0x55, rendering would fail.
1966 glEnable(GL_STENCIL_TEST);
1967 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
1968 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1969 glStencilMask(0xFF);
1970
1971 // Blend half-transparent green into the multisampled color buffer.
1972 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
1973 glEnable(GL_BLEND);
1974 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1975 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
1976 ASSERT_GL_NO_ERROR();
1977
1978 // Verify that the texture is now cyan
1979 const GLColor kExpected2(0, 127, 127, 191);
1980 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected2, 1);
1981 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected2, 1);
1982 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected2, 1);
1983 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected2, 1);
1984
1985 // For completeness, verify that the texture used as copy target is red.
1986 ASSERT_GL_NO_ERROR();
1987 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
1988
1989 ASSERT_GL_NO_ERROR();
1990 }
1991
1992 // Draw, copy, draw, attach depth/stencil, clear then draw. The second draw will need to unresolve
1993 // color. Attaching depth/stencil changes the framebuffer, and the following clear ensures no
1994 // unresolve is necessary. In the Vulkan backend, mismatches in unresolve state between framebuffer
1995 // and render pass will result in an ASSERT.
TEST_P(MultisampledRenderToTextureES3Test,DrawCopyDrawAttachDepthStencilClearThenDraw)1996 TEST_P(MultisampledRenderToTextureES3Test, DrawCopyDrawAttachDepthStencilClearThenDraw)
1997 {
1998 drawCopyDrawAttachDepthStencilClearThenDrawCommon(false);
1999 }
2000
2001 // Same as DrawCopyDrawAttachDepthStencilClearThenDraw but with renderbuffers
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDrawCopyDrawAttachDepthStencilClearThenDraw)2002 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawCopyDrawAttachDepthStencilClearThenDraw)
2003 {
2004 drawCopyDrawAttachDepthStencilClearThenDrawCommon(true);
2005 }
2006
2007 // Draw, copy, redefine the color attachment with a different format, clear, copy then draw. The
2008 // initial draw will need to unresolve color as the color attachment is preinitilized with data.
2009 // Redefining the color attachment forces framebuffer to recreate when the clear is called. The
2010 // second copy resolves the clear and the final draw unresolves again. In the Vulkan backend,
2011 // mismatches in unresolve state between framebuffer and render pass will result in an ASSERT and a
2012 // validation error (if ASSERT is removed).
TEST_P(MultisampledRenderToTextureES3Test,DrawCopyRedefineClearCopyThenDraw)2013 TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRedefineClearCopyThenDraw)
2014 {
2015 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2016 constexpr GLsizei kSize = 64;
2017
2018 setupCopyTexProgram();
2019
2020 GLFramebuffer fboMS;
2021 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2022
2023 std::vector<GLColor> initialColorData(kSize * kSize, GLColor::black);
2024
2025 // Create multisampled framebuffer to draw into
2026 GLTexture colorMS;
2027 glBindTexture(GL_TEXTURE_2D, colorMS);
2028 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2029 initialColorData.data());
2030 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2031 colorMS, 0, 4);
2032 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2033
2034 // Draw red into the multisampled color buffer.
2035 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2036 glUseProgram(drawColor);
2037 GLint colorUniformLocation =
2038 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2039 ASSERT_NE(colorUniformLocation, -1);
2040
2041 // Draw into framebuffer. This will unresolve color.
2042 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2043 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
2044 ASSERT_GL_NO_ERROR();
2045
2046 // Create a texture and copy into it.
2047 GLTexture texture;
2048 glBindTexture(GL_TEXTURE_2D, texture);
2049 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2050 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2051 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2052
2053 // Incompatibly redefine the texture, forcing its image to be recreated.
2054 glBindTexture(GL_TEXTURE_2D, colorMS);
2055 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kSize, kSize, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
2056 ASSERT_GL_NO_ERROR();
2057 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2058
2059 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2060 glClear(GL_COLOR_BUFFER_BIT);
2061
2062 // Create another texture and copy into it.
2063 GLTexture texture2;
2064 glBindTexture(GL_TEXTURE_2D, texture2);
2065 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kSize, kSize, 0);
2066
2067 // Clear to green and blend blue into the multisampled color buffer.
2068 glUseProgram(drawColor);
2069 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2070 glEnable(GL_BLEND);
2071 glBlendFunc(GL_ONE, GL_ONE);
2072 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
2073 ASSERT_GL_NO_ERROR();
2074
2075 // Verify that the texture is now cyan
2076 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2077 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::cyan);
2078 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::cyan);
2079 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::cyan);
2080
2081 // For completeness, verify that the texture used as copy target is red.
2082 ASSERT_GL_NO_ERROR();
2083 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
2084
2085 ASSERT_GL_NO_ERROR();
2086 }
2087
2088 // Draw, copy, rebind the attachment, clear then draw. The initial draw will need to unresolve
2089 // color. The framebuffer attachment is temporary changed and then reset back to the original.
2090 // This causes the framebuffer to be recreated on the following clear and draw. The clear prevents
2091 // the final draw from doing an unresolve. In the Vulkan backend, mismatches in unresolve state
2092 // between framebuffer and render pass will result in an ASSERT and a validation error (if ASSERT is
2093 // removed).
TEST_P(MultisampledRenderToTextureES3Test,DrawCopyRebindAttachmentClearThenDraw)2094 TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRebindAttachmentClearThenDraw)
2095 {
2096 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2097 constexpr GLsizei kSize = 64;
2098
2099 setupCopyTexProgram();
2100
2101 GLFramebuffer fboMS;
2102 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2103
2104 std::vector<GLColor> initialColorData(kSize * kSize, GLColor::black);
2105
2106 // Create multisampled framebuffer to draw into
2107 GLTexture colorMS;
2108 glBindTexture(GL_TEXTURE_2D, colorMS);
2109 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2110 initialColorData.data());
2111 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2112 colorMS, 0, 4);
2113 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2114
2115 // Draw red into the multisampled color buffer.
2116 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2117 glUseProgram(drawColor);
2118 GLint colorUniformLocation =
2119 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2120 ASSERT_NE(colorUniformLocation, -1);
2121
2122 // Draw into framebuffer. This will unresolve color.
2123 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2124 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
2125 ASSERT_GL_NO_ERROR();
2126
2127 // Create a texture and copy into it.
2128 GLTexture texture;
2129 glBindTexture(GL_TEXTURE_2D, texture);
2130 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2133
2134 // Bind the framebuffer to another texture.
2135 GLTexture color;
2136 glBindTexture(GL_TEXTURE_2D, color);
2137 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2138 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
2139 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2140
2141 // Do whatever.
2142 glClear(GL_COLOR_BUFFER_BIT);
2143
2144 // Rebind the framebuffer back to the original texture.
2145 glBindTexture(GL_TEXTURE_2D, colorMS);
2146 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2147 colorMS, 0, 4);
2148
2149 // Clear to green and blend blue into the multisampled color buffer.
2150 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2151 glClear(GL_COLOR_BUFFER_BIT);
2152 glUseProgram(drawColor);
2153 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2154 glEnable(GL_BLEND);
2155 glBlendFunc(GL_ONE, GL_ONE);
2156 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
2157 ASSERT_GL_NO_ERROR();
2158
2159 // Verify that the texture is now cyan
2160 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2161 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::cyan);
2162 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::cyan);
2163 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::cyan);
2164
2165 // For completeness, verify that the texture used as copy target is red.
2166 ASSERT_GL_NO_ERROR();
2167 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
2168
2169 ASSERT_GL_NO_ERROR();
2170 }
2171
clearThenBlendCommon(bool useRenderbuffer)2172 void MultisampledRenderToTextureTest::clearThenBlendCommon(bool useRenderbuffer)
2173 {
2174 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2175 constexpr GLsizei kSize = 64;
2176
2177 setupCopyTexProgram();
2178
2179 GLFramebuffer fboMS;
2180 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2181
2182 // Create multisampled framebuffer to draw into
2183 GLTexture textureMS;
2184 GLRenderbuffer renderbufferMS;
2185 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
2186 mTestSampleCount, &textureMS, &renderbufferMS);
2187 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2188
2189 // Clear the framebuffer.
2190 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2191 glClear(GL_COLOR_BUFFER_BIT);
2192
2193 // Blend half-transparent green into the multisampled color buffer.
2194 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2195 glUseProgram(drawColor);
2196 GLint colorUniformLocation =
2197 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2198 ASSERT_NE(colorUniformLocation, -1);
2199
2200 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
2201 glEnable(GL_BLEND);
2202 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2203 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
2204 ASSERT_GL_NO_ERROR();
2205
2206 // Verify that the texture is now yellow
2207 const GLColor kExpected(127, 127, 0, 191);
2208 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
2209 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
2210 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
2211 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
2212 }
2213
2214 // Clear then blend. The clear should be applied correctly.
TEST_P(MultisampledRenderToTextureTest,ClearThenBlend)2215 TEST_P(MultisampledRenderToTextureTest, ClearThenBlend)
2216 {
2217 clearThenBlendCommon(false);
2218 }
2219
2220 // Clear then blend. The clear should be applied correctly. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureTest,RenderbufferClearThenBlend)2221 TEST_P(MultisampledRenderToTextureTest, RenderbufferClearThenBlend)
2222 {
2223 clearThenBlendCommon(true);
2224 }
2225
depthStencilClearThenDrawCommon(bool useRenderbuffer)2226 void MultisampledRenderToTextureES3Test::depthStencilClearThenDrawCommon(bool useRenderbuffer)
2227 {
2228 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2229 if (!useRenderbuffer)
2230 {
2231 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
2232 }
2233
2234 constexpr GLsizei kSize = 64;
2235
2236 setupCopyTexProgram();
2237
2238 GLFramebuffer fboMS;
2239 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2240
2241 // Create framebuffer to draw into, with both color and depth attachments.
2242 GLTexture textureMS;
2243 GLRenderbuffer renderbufferMS;
2244 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
2245 mTestSampleCount, &textureMS, &renderbufferMS);
2246
2247 GLTexture dsTextureMS;
2248 GLRenderbuffer dsRenderbufferMS;
2249 createAndAttachDepthStencilAttachment(useRenderbuffer, kSize, &dsTextureMS, &dsRenderbufferMS);
2250 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2251
2252 // Set viewport and clear depth/stencil
2253 glViewport(0, 0, kSize, kSize);
2254 glClearDepthf(1);
2255 glClearStencil(0x55);
2256 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2257
2258 // If depth is not cleared to 1, rendering would fail.
2259 glEnable(GL_DEPTH_TEST);
2260 glDepthFunc(GL_LESS);
2261
2262 // If stencil is not cleared to 0x55, rendering would fail.
2263 glEnable(GL_STENCIL_TEST);
2264 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
2265 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2266 glStencilMask(0xFF);
2267
2268 // Set up program
2269 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2270
2271 // Draw red
2272 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
2273 ASSERT_GL_NO_ERROR();
2274
2275 // Create a texture and copy into it.
2276 GLTexture texture;
2277 glBindTexture(GL_TEXTURE_2D, texture);
2278 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2281 ASSERT_GL_NO_ERROR();
2282
2283 // Verify.
2284 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
2285 }
2286
2287 // Clear depth stencil, then draw. The clear should be applied correctly.
TEST_P(MultisampledRenderToTextureES3Test,DepthStencilClearThenDraw)2288 TEST_P(MultisampledRenderToTextureES3Test, DepthStencilClearThenDraw)
2289 {
2290 depthStencilClearThenDrawCommon(false);
2291 }
2292
2293 // Clear depth stencil, then draw. The clear should be applied correctly. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDepthStencilClearThenDraw)2294 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearThenDraw)
2295 {
2296 depthStencilClearThenDrawCommon(true);
2297 }
2298
2299 // Clear&Draw, copy, then blend similarly to RenderbufferClearDrawCopyThenBlendSameProgram. This
2300 // tests uses a depth/stencil buffer and makes sure the second draw (in the second render pass)
2301 // succeeds (i.e. depth/stencil data is not lost). Note that this test doesn't apply to
2302 // depth/stencil textures as they are explicitly autoinvalidated between render passes.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDepthStencilClearDrawCopyThenBlend)2303 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearDrawCopyThenBlend)
2304 {
2305 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2306
2307 // http://anglebug.com/5096
2308 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
2309
2310 constexpr GLsizei kSize = 64;
2311
2312 setupCopyTexProgram();
2313
2314 GLFramebuffer fbo;
2315 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2316
2317 // Create framebuffer to draw into, with both color and depth/stencil attachments.
2318 GLTexture color;
2319 glBindTexture(GL_TEXTURE_2D, color);
2320 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2321 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
2322 0, 4);
2323
2324 GLRenderbuffer depthStencil;
2325 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2326 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
2327 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2328 depthStencil);
2329 ASSERT_GL_NO_ERROR();
2330 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2331
2332 // Set viewport and clear depth/stencil
2333 glViewport(0, 0, kSize, kSize);
2334 glClearDepthf(1);
2335 glClearStencil(0x55);
2336 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2337
2338 // If depth is not cleared to 1, rendering would fail.
2339 glEnable(GL_DEPTH_TEST);
2340 glDepthFunc(GL_LESS);
2341
2342 // If stencil is not cleared to 0x55, rendering would fail.
2343 glEnable(GL_STENCIL_TEST);
2344 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
2345 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2346 glStencilMask(0xFF);
2347
2348 // Set up program
2349 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2350 glUseProgram(drawColor);
2351 GLint colorUniformLocation =
2352 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2353 ASSERT_NE(colorUniformLocation, -1);
2354
2355 // Draw red
2356 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2357 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f);
2358 ASSERT_GL_NO_ERROR();
2359
2360 // Create a texture and copy into it.
2361 GLTexture texture;
2362 glBindTexture(GL_TEXTURE_2D, texture);
2363 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2366 ASSERT_GL_NO_ERROR();
2367
2368 // Draw again into the framebuffer, this time blending. This tests that both the color and
2369 // depth/stencil data are preserved after the resolve incurred by the copy above.
2370 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
2371 glEnable(GL_BLEND);
2372 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2373 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
2374 ASSERT_GL_NO_ERROR();
2375
2376 // Verify that the texture is now yellow
2377 const GLColor kExpected(127, 127, 0, 191);
2378 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
2379 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
2380 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
2381 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
2382
2383 // For completeness, verify that the texture used as copy target is red.
2384 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
2385 }
2386
2387 // Draw, copy, then clear&blend. This tests uses a depth/stencil buffer and makes sure the second
2388 // draw (in the second render pass) succeeds (i.e. depth/stencil data is not lost). The difference
2389 // with RenderbufferDepthStencilClearDrawCopyThenBlend is that color is cleared in the second render
2390 // pass, so only depth/stencil data is unresolved. This test doesn't apply to depth/stencil
2391 // textures as they are explicitly autoinvalidated between render passes.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDepthStencilDrawCopyClearThenBlend)2392 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilDrawCopyClearThenBlend)
2393 {
2394 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2395
2396 // http://anglebug.com/5096
2397 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
2398
2399 constexpr GLsizei kSize = 64;
2400
2401 setupCopyTexProgram();
2402
2403 GLFramebuffer fbo;
2404 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2405
2406 // Create framebuffer to draw into, with both color and depth/stencil attachments.
2407 GLTexture color;
2408 glBindTexture(GL_TEXTURE_2D, color);
2409 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2410 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
2411 0, 4);
2412
2413 GLRenderbuffer depthStencil;
2414 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2415 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
2416 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2417 depthStencil);
2418 ASSERT_GL_NO_ERROR();
2419 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2420
2421 // Set viewport and clear depth/stencil through draw
2422 glViewport(0, 0, kSize, kSize);
2423
2424 glEnable(GL_DEPTH_TEST);
2425 glDepthFunc(GL_ALWAYS);
2426
2427 glEnable(GL_STENCIL_TEST);
2428 glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
2429 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2430 glStencilMask(0xFF);
2431
2432 // Set up program
2433 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2434 glUseProgram(drawColor);
2435 GLint colorUniformLocation =
2436 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2437 ASSERT_NE(colorUniformLocation, -1);
2438
2439 // Draw red
2440 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2441 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f);
2442 ASSERT_GL_NO_ERROR();
2443
2444 // Create a texture and copy into it.
2445 GLTexture texture;
2446 glBindTexture(GL_TEXTURE_2D, texture);
2447 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2450 ASSERT_GL_NO_ERROR();
2451
2452 // Clear color to blue
2453 glClearColor(0.0, 0.0, 1.0, 1.0);
2454 glClear(GL_COLOR_BUFFER_BIT);
2455
2456 // If depth is not cleared to 1, rendering would fail.
2457 glEnable(GL_DEPTH_TEST);
2458 glDepthFunc(GL_LESS);
2459
2460 // If stencil is not cleared to 0x55, rendering would fail.
2461 glEnable(GL_STENCIL_TEST);
2462 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
2463 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2464 glStencilMask(0xFF);
2465
2466 // Draw again into the framebuffer, this time blending. This tests that depth/stencil data are
2467 // preserved after the resolve incurred by the copy above and color is cleared correctly.
2468 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
2469 glEnable(GL_BLEND);
2470 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2471 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
2472 ASSERT_GL_NO_ERROR();
2473
2474 // Copy into the texture again.
2475 glBindTexture(GL_TEXTURE_2D, texture);
2476 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2477 ASSERT_GL_NO_ERROR();
2478
2479 // Verify that the texture is now cyan
2480 const GLColor kExpected(0, 127, 127, 191);
2481 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
2482 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
2483 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
2484 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
2485
2486 // For completeness, verify that the texture used as copy target is also cyan.
2487 const GLColor expectedCopyResult(0, 127, 127, 191);
2488 verifyResults(texture, expectedCopyResult, kSize, 0, 0, kSize, kSize);
2489 }
2490
2491 // Clear, then blit depth/stencil with renderbuffers. This test makes sure depth/stencil blit uses
2492 // the correct image. Note that this test doesn't apply to depth/stencil textures as they are
2493 // explicitly autoinvalidated between render passes.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferClearThenBlitDepthStencil)2494 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferClearThenBlitDepthStencil)
2495 {
2496 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2497
2498 // D3D backend doesn't implement multisampled render to texture renderbuffers correctly.
2499 // http://anglebug.com/3107
2500 ANGLE_SKIP_TEST_IF(IsD3D());
2501
2502 constexpr GLsizei kSize = 64;
2503
2504 setupCopyTexProgram();
2505
2506 GLFramebuffer fboMS;
2507 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2508
2509 // Create framebuffer to draw into, with both color and depth/stencil attachments.
2510 GLTexture color;
2511 glBindTexture(GL_TEXTURE_2D, color);
2512 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2513 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
2514 0, 4);
2515
2516 GLRenderbuffer depthStencilMS;
2517 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
2518 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
2519 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2520 depthStencilMS);
2521 ASSERT_GL_NO_ERROR();
2522 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2523
2524 // Clear depth/stencil
2525 glClearDepthf(1);
2526 glClearStencil(0x55);
2527 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2528
2529 // Create framebuffer as blit target.
2530 GLFramebuffer fbo;
2531 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2532
2533 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
2534
2535 GLRenderbuffer depthStencil;
2536 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2537 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
2538 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2539 depthStencil);
2540 ASSERT_GL_NO_ERROR();
2541 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2542
2543 // Blit depth/stencil
2544 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
2545 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2546
2547 // Draw into the framebuffer that was the destination of blit, verifying that depth and stencil
2548 // values are correct.
2549
2550 // If depth is not 1, rendering would fail.
2551 glEnable(GL_DEPTH_TEST);
2552 glDepthFunc(GL_LESS);
2553
2554 // If stencil is not 0x55, rendering would fail.
2555 glEnable(GL_STENCIL_TEST);
2556 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
2557 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2558 glStencilMask(0xFF);
2559
2560 // Set up program
2561 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2562 glUseProgram(drawColor);
2563 GLint colorUniformLocation =
2564 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2565 ASSERT_NE(colorUniformLocation, -1);
2566
2567 // Draw red
2568 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2569 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
2570 ASSERT_GL_NO_ERROR();
2571
2572 // Verify that the texture is now red
2573 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2574 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
2575 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
2576 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
2577
2578 // Clear depth/stencil to a different value, and blit again but this time flipped.
2579 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboMS);
2580 glClearDepthf(0);
2581 glClearStencil(0x3E);
2582 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2583
2584 // Blit
2585 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2586 glBlitFramebuffer(0, 0, kSize, kSize, kSize, kSize, 0, 0,
2587 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2588
2589 // Draw green
2590 glDepthFunc(GL_GREATER);
2591 glStencilFunc(GL_EQUAL, 0x3E, 0xFF);
2592 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2593 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
2594 ASSERT_GL_NO_ERROR();
2595
2596 // Verify that the texture is now green
2597 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2598 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2599 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2600 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2601 }
2602
2603 // Draw, then blit depth/stencil with renderbuffers. This test makes sure depth/stencil resolve is
2604 // correctly implemented. Note that this test doesn't apply to depth/stencil textures as they are
2605 // explicitly autoinvalidated between render passes.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDrawThenBlitDepthStencil)2606 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencil)
2607 {
2608 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2609
2610 // http://anglebug.com/5096
2611 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
2612
2613 constexpr GLsizei kSize = 64;
2614
2615 GLFramebuffer fboMS;
2616 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2617
2618 // Create framebuffer to draw into, with both color and depth/stencil attachments.
2619 GLTexture color;
2620 glBindTexture(GL_TEXTURE_2D, color);
2621 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2622 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
2623 0, 4);
2624
2625 GLRenderbuffer depthStencilMS;
2626 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
2627 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
2628 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2629 depthStencilMS);
2630 ASSERT_GL_NO_ERROR();
2631 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2632
2633 // Set up program
2634 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2635 glUseProgram(drawColor);
2636 GLint colorUniformLocation =
2637 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2638 ASSERT_NE(colorUniformLocation, -1);
2639
2640 // Output depth/stencil through draw
2641 glEnable(GL_DEPTH_TEST);
2642 glDepthFunc(GL_ALWAYS);
2643
2644 glEnable(GL_STENCIL_TEST);
2645 glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
2646 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2647 glStencilMask(0xFF);
2648
2649 // Draw blue
2650 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2651 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f);
2652 ASSERT_GL_NO_ERROR();
2653
2654 // Create framebuffer as blit target.
2655 GLFramebuffer fbo;
2656 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2657
2658 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
2659
2660 GLRenderbuffer depthStencil;
2661 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2662 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
2663 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2664 depthStencil);
2665 ASSERT_GL_NO_ERROR();
2666 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2667
2668 // Blit depth/stencil
2669 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
2670 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2671
2672 // Draw into the framebuffer that was the destination of blit, verifying that depth and stencil
2673 // values are correct.
2674
2675 // If depth is not 1, rendering would fail.
2676 glDepthFunc(GL_LESS);
2677
2678 // If stencil is not 0x55, rendering would fail.
2679 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
2680 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2681 glStencilMask(0xFF);
2682
2683 // Draw red
2684 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2685 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
2686 ASSERT_GL_NO_ERROR();
2687
2688 // Verify that the texture is now red
2689 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2690 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
2691 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
2692 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
2693 }
2694
2695 // Draw, then blit depth/stencil with renderbuffers, without a color attachment. Note that this test
2696 // doesn't apply to depth/stencil textures as they are explicitly autoinvalidated between render
2697 // passes.
2698 //
2699 // This test first uses a draw call to fill in the depth/stencil buffer, then blits it to force a
2700 // resolve. Then it uses a no-op draw call to start a "fullscreen" render pass followed by a
2701 // scissored draw to modify parts of the depth buffer:
2702 //
2703 // +--------------------+
2704 // | D=1, S=0x55 |
2705 // | |
2706 // | +--------+ |
2707 // | | D=0 | |
2708 // | | S=0xAA | |
2709 // | +--------+ |
2710 // | |
2711 // | |
2712 // +--------------------+
2713 //
2714 // Blit is used again to copy the depth/stencil attachment data, and the result is verified.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferDrawThenBlitDepthStencilOnly)2715 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDrawThenBlitDepthStencilOnly)
2716 {
2717 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2718
2719 // http://anglebug.com/5096
2720 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
2721
2722 // http://anglebug.com/5110
2723 ANGLE_SKIP_TEST_IF(IsD3D());
2724
2725 constexpr GLsizei kSize = 64;
2726
2727 GLFramebuffer fboMS;
2728 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2729
2730 // Create framebuffer to draw into, with depth/stencil attachment only.
2731 GLRenderbuffer depthStencilMS;
2732 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
2733 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
2734 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2735 depthStencilMS);
2736 ASSERT_GL_NO_ERROR();
2737 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2738
2739 // Set up program
2740 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2741 glUseProgram(drawColor);
2742 GLint colorUniformLocation =
2743 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2744 ASSERT_NE(colorUniformLocation, -1);
2745 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
2746
2747 // Output depth/stencil through draw
2748 glEnable(GL_DEPTH_TEST);
2749 glDepthFunc(GL_ALWAYS);
2750
2751 glEnable(GL_STENCIL_TEST);
2752 glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
2753 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2754 glStencilMask(0xFF);
2755
2756 // Draw. Depth/stencil is now:
2757 //
2758 // +--------------------+
2759 // | D=1, S=0x55 |
2760 // | |
2761 // | |
2762 // | |
2763 // | |
2764 // | |
2765 // | |
2766 // | |
2767 // +--------------------+
2768 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1.0f);
2769 ASSERT_GL_NO_ERROR();
2770
2771 // Create framebuffer as blit target.
2772 GLFramebuffer fbo;
2773 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2774
2775 GLRenderbuffer depthStencil;
2776 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2777 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
2778 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2779 depthStencil);
2780 ASSERT_GL_NO_ERROR();
2781 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2782
2783 // Blit depth/stencil
2784 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
2785 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2786
2787 // Disable depth/stencil and draw again. Depth/stencil is not modified.
2788 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboMS);
2789 glDisable(GL_DEPTH_TEST);
2790 glDisable(GL_STENCIL_TEST);
2791 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
2792 ASSERT_GL_NO_ERROR();
2793
2794 // Enable depth/stencil and do a scissored draw. Depth/stencil is now:
2795 //
2796 // +--------------------+
2797 // | D=1, S=0x55 |
2798 // | |
2799 // | +--------+ |
2800 // | | D=0 | |
2801 // | | S=0xAA | |
2802 // | +--------+ |
2803 // | |
2804 // | |
2805 // +--------------------+
2806 glEnable(GL_DEPTH_TEST);
2807 glEnable(GL_STENCIL_TEST);
2808 glStencilFunc(GL_ALWAYS, 0xAA, 0xFF);
2809 glEnable(GL_SCISSOR_TEST);
2810 glScissor(kSize / 4, kSize / 4, kSize / 2, kSize / 2);
2811 drawQuad(drawColor, essl1_shaders::PositionAttrib(), -1.0f);
2812 glDisable(GL_SCISSOR_TEST);
2813 ASSERT_GL_NO_ERROR();
2814
2815 // Blit depth/stencil again.
2816 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2817 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
2818 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2819 ASSERT_GL_NO_ERROR();
2820
2821 // Draw into the framebuffer that was the destination of blit, verifying that depth and stencil
2822 // values are correct.
2823 GLTexture color;
2824 glBindTexture(GL_TEXTURE_2D, color);
2825 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2826 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
2827 ASSERT_GL_NO_ERROR();
2828 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2829
2830 // First, verify the outside border, where D=1 and S=0x55
2831 glDepthFunc(GL_LESS);
2832 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
2833 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2834 glStencilMask(0xFF);
2835 ASSERT_GL_NO_ERROR();
2836
2837 // Draw green
2838 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2839 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
2840 ASSERT_GL_NO_ERROR();
2841
2842 // Then, verify the center, where D=0 and S=0xAA
2843 glDepthFunc(GL_GREATER);
2844 glStencilFunc(GL_EQUAL, 0xAA, 0xFF);
2845 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2846 glStencilMask(0xFF);
2847
2848 // Draw blue
2849 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2850 drawQuad(drawColor, essl1_shaders::PositionAttrib(), -0.95f);
2851 ASSERT_GL_NO_ERROR();
2852
2853 // Verify that the border is now green
2854 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
2855 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2856 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2857 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2858 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2859
2860 // Verify that the center is now blue
2861 EXPECT_PIXEL_COLOR_EQ(kSize / 4, kSize / 4, GLColor::blue);
2862 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 4 - 1, kSize / 4, GLColor::blue);
2863 EXPECT_PIXEL_COLOR_EQ(kSize / 4, 3 * kSize / 4 - 1, GLColor::blue);
2864 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 4 - 1, 3 * kSize / 4 - 1, GLColor::blue);
2865 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::blue);
2866 }
2867
2868 // Test the depth read/write mode change within the renderpass while there is color unresolve
2869 // attachment
TEST_P(MultisampledRenderToTextureTest,DepthReadWriteToggleWithStartedRenderPass)2870 TEST_P(MultisampledRenderToTextureTest, DepthReadWriteToggleWithStartedRenderPass)
2871 {
2872 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2873
2874 constexpr GLsizei kSize = 64;
2875
2876 setupCopyTexProgram();
2877
2878 GLFramebuffer fboMS;
2879 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2880
2881 // Create framebuffer to draw into, with both color and depth attachments.
2882 GLTexture textureMS;
2883 GLRenderbuffer renderbufferMS;
2884 createAndAttachColorAttachment(true, kSize, GL_COLOR_ATTACHMENT0, nullptr, mTestSampleCount,
2885 &textureMS, &renderbufferMS);
2886
2887 GLTexture dsTextureMS;
2888 GLRenderbuffer dsRenderbufferMS;
2889 glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbufferMS);
2890 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kSize, kSize);
2891 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2892 dsRenderbufferMS);
2893 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2894
2895 // First renderpass: draw with depth value 0.5f
2896 glViewport(0, 0, kSize, kSize);
2897 glEnable(GL_DEPTH_TEST);
2898 glDepthFunc(GL_ALWAYS);
2899 glDepthMask(GL_TRUE);
2900 glClearColor(0.0, 0.0, 0.0, 1.0);
2901 glClear(GL_COLOR_BUFFER_BIT);
2902 glEnable(GL_BLEND);
2903 glBlendFunc(GL_ONE, GL_ZERO);
2904 ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
2905 drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.5f);
2906 ASSERT_GL_NO_ERROR();
2907 // The color check should end the renderpass
2908 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2909
2910 // Create another FBO and render, jus so try to clear rendering cache. At least on pixel4,
2911 // the test now properly fail if I force the loadOP to DontCare in the next renderpass.
2912 constexpr bool clearRenderingCacheWithFBO = true;
2913 if (clearRenderingCacheWithFBO)
2914 {
2915 GLFramebuffer fboMS2;
2916 glBindFramebuffer(GL_FRAMEBUFFER, fboMS2);
2917 GLTexture textureMS2;
2918 GLRenderbuffer renderbufferMS2;
2919 createAndAttachColorAttachment(true, 2048, GL_COLOR_ATTACHMENT0, nullptr, mTestSampleCount,
2920 &textureMS2, &renderbufferMS2);
2921 GLTexture dsTextureMS2;
2922 GLRenderbuffer dsRenderbufferMS2;
2923 glBindRenderbuffer(GL_RENDERBUFFER, dsRenderbufferMS2);
2924 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, 2048, 2048);
2925 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2926 dsRenderbufferMS2);
2927 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2928 ASSERT_GL_NO_ERROR();
2929 glViewport(0, 0, 2048, 2048);
2930 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2931 glUseProgram(drawColor);
2932 GLint colorUniformLocation =
2933 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
2934 ASSERT_NE(colorUniformLocation, -1);
2935 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 0.0f, 0.0f);
2936 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
2937 ASSERT_GL_NO_ERROR();
2938 }
2939
2940 // Second renderpass: Start with depth read only and then switch to depth write
2941 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2942 glViewport(0, 0, kSize, kSize);
2943 glDepthFunc(GL_LESS);
2944 // Draw red with depth read only. pass depth test, Result: color=Red, depth=0.5
2945 glDepthMask(GL_FALSE);
2946 glBlendFunc(GL_ONE, GL_ONE);
2947 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2948 glUseProgram(drawRed);
2949 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.1f);
2950 ASSERT_GL_NO_ERROR();
2951
2952 // Draw green with depth write. Pass depth test. Result: color=Green, depth=0.3
2953 glDepthMask(GL_TRUE);
2954 glBlendFunc(GL_ONE, GL_ONE);
2955 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2956 glUseProgram(drawGreen);
2957 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.3f);
2958 ASSERT_GL_NO_ERROR();
2959
2960 // Create a texture and copy into it.
2961 GLTexture texture;
2962 glBindTexture(GL_TEXTURE_2D, texture);
2963 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2964 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2965 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2966 ASSERT_GL_NO_ERROR();
2967
2968 // Verify the color has all three color in it.
2969 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::white);
2970 }
2971
colorAttachment1Common(bool useRenderbuffer)2972 void MultisampledRenderToTextureES3Test::colorAttachment1Common(bool useRenderbuffer)
2973 {
2974 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
2975 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
2976 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2977
2978 constexpr GLsizei kSize = 64;
2979
2980 setupCopyTexProgram();
2981
2982 GLFramebuffer fboMS;
2983 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
2984
2985 // Create multisampled framebuffer to draw into, use color attachment 1
2986 GLTexture textureMS;
2987 GLRenderbuffer renderbufferMS;
2988 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT1, nullptr,
2989 mTestSampleCount, &textureMS, &renderbufferMS);
2990 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2991
2992 // Setup program to render into attachment 1.
2993 constexpr bool kBuffersEnabled[8] = {false, true};
2994
2995 GLuint drawColor;
2996 setupUniformColorProgramMultiRenderTarget(kBuffersEnabled, &drawColor);
2997 glUseProgram(drawColor);
2998 GLint colorUniformLocation =
2999 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3000 ASSERT_NE(colorUniformLocation, -1);
3001
3002 constexpr GLenum kDrawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
3003 glDrawBuffers(2, kDrawBuffers);
3004 glReadBuffer(GL_COLOR_ATTACHMENT1);
3005 ASSERT_GL_NO_ERROR();
3006
3007 // Draw red into the multisampled color buffer.
3008 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3009 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3010 ASSERT_GL_NO_ERROR();
3011
3012 // Create a texture and copy into it.
3013 GLTexture texture;
3014 glBindTexture(GL_TEXTURE_2D, texture);
3015 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
3016 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3017 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3018 ASSERT_GL_NO_ERROR();
3019
3020 // Blend half-transparent green into the multisampled color buffer.
3021 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
3022 glEnable(GL_BLEND);
3023 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3024 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3025 ASSERT_GL_NO_ERROR();
3026
3027 // Verify that the texture is now yellow
3028 const GLColor kExpected(127, 127, 0, 191);
3029 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
3030 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
3031 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
3032 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
3033
3034 // For completeness, verify that the texture used as copy target is red.
3035 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
3036
3037 ASSERT_GL_NO_ERROR();
3038
3039 glDeleteProgram(drawColor);
3040 }
3041
3042 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
3043 // following draw should retain the data written by the first draw command.
3044 // Uses color attachment 1.
TEST_P(MultisampledRenderToTextureES3Test,ColorAttachment1)3045 TEST_P(MultisampledRenderToTextureES3Test, ColorAttachment1)
3046 {
3047 colorAttachment1Common(false);
3048 }
3049
3050 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
3051 // following draw should retain the data written by the first draw command.
3052 // Uses color attachment 1. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferColorAttachment1)3053 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferColorAttachment1)
3054 {
3055 colorAttachment1Common(true);
3056 }
3057
colorAttachments0And3Common(bool useRenderbuffer)3058 void MultisampledRenderToTextureES3Test::colorAttachments0And3Common(bool useRenderbuffer)
3059 {
3060 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3061 ANGLE_SKIP_TEST_IF(!useRenderbuffer &&
3062 !EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
3063 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3064
3065 constexpr GLsizei kSize = 64;
3066
3067 setupCopyTexProgram();
3068
3069 GLFramebuffer fboMS;
3070 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3071
3072 // Create multisampled framebuffer to draw into, use color attachment 1
3073 GLTexture textureMS0;
3074 GLRenderbuffer renderbufferMS0;
3075 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
3076 mTestSampleCount, &textureMS0, &renderbufferMS0);
3077
3078 GLTexture textureMS3;
3079 GLRenderbuffer renderbufferMS3;
3080 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT3, nullptr,
3081 mTestSampleCount, &textureMS3, &renderbufferMS3);
3082
3083 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3084
3085 // Setup program to render into attachments 0 and 3.
3086 constexpr bool kBuffersEnabled[8] = {true, false, false, true};
3087
3088 GLuint drawColor;
3089 setupUniformColorProgramMultiRenderTarget(kBuffersEnabled, &drawColor);
3090 glUseProgram(drawColor);
3091 GLint colorUniformLocation =
3092 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3093 ASSERT_NE(colorUniformLocation, -1);
3094
3095 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE,
3096 GL_COLOR_ATTACHMENT3};
3097 glDrawBuffers(4, kDrawBuffers);
3098 glReadBuffer(GL_COLOR_ATTACHMENT3);
3099 ASSERT_GL_NO_ERROR();
3100
3101 // Draw red into the multisampled color buffers.
3102 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3103 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3104 ASSERT_GL_NO_ERROR();
3105
3106 // Create a texture and copy from one of them.
3107 GLTexture texture;
3108 glBindTexture(GL_TEXTURE_2D, texture);
3109 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
3110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3112 ASSERT_GL_NO_ERROR();
3113
3114 // Blend half-transparent green into the multisampled color buffers.
3115 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
3116 glEnable(GL_BLEND);
3117 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3118 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3119 ASSERT_GL_NO_ERROR();
3120
3121 // Verify that the textures are now yellow
3122 const GLColor kExpected(127, 127, 0, 191);
3123 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
3124 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
3125 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
3126 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
3127
3128 glReadBuffer(GL_COLOR_ATTACHMENT0);
3129 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
3130 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
3131 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
3132 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
3133 ASSERT_GL_NO_ERROR();
3134
3135 // Test color unresolve with these attachments too, by adding blue into the attachments.
3136 glBlendFunc(GL_ONE, GL_ONE);
3137 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 0.0f);
3138 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3139
3140 const GLColor kExpected2(127, 127, 255, 191);
3141
3142 glReadBuffer(GL_COLOR_ATTACHMENT0);
3143 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected2, 1);
3144 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected2, 1);
3145 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected2, 1);
3146 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected2, 1);
3147
3148 glReadBuffer(GL_COLOR_ATTACHMENT3);
3149 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected2, 1);
3150 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected2, 1);
3151 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected2, 1);
3152 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected2, 1);
3153
3154 // For completeness, verify that the texture used as copy target is red.
3155 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
3156
3157 ASSERT_GL_NO_ERROR();
3158
3159 glDeleteProgram(drawColor);
3160 }
3161
3162 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
3163 // following draw should retain the data written by the first draw command.
3164 // Uses color attachments 0 and 3.
TEST_P(MultisampledRenderToTextureES3Test,ColorAttachments0And3)3165 TEST_P(MultisampledRenderToTextureES3Test, ColorAttachments0And3)
3166 {
3167 colorAttachments0And3Common(false);
3168 }
3169
3170 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
3171 // following draw should retain the data written by the first draw command.
3172 // Uses color attachments 0 and 3. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferColorAttachments0And3)3173 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferColorAttachments0And3)
3174 {
3175 colorAttachments0And3Common(true);
3176 }
3177
3178 // Draw with depth buffer. Uses EXT_multisampled_render_to_texture2.
3179 // The test works with a 64x1 texture. The first draw call will render geometry whose depth is
3180 // different between top and bottom. The second draw call will enable depth test and draw with the
3181 // average of the two depths. Only half of the samples will take the new color. Once resolved, the
3182 // expected color would be the average of the two draw colors.
TEST_P(MultisampledRenderToTextureES3Test,DepthStencilAttachment)3183 TEST_P(MultisampledRenderToTextureES3Test, DepthStencilAttachment)
3184 {
3185 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3186 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
3187
3188 constexpr GLsizei kWidth = 64;
3189
3190 // Create multisampled framebuffer to draw into, with both color and depth attachments.
3191 GLTexture colorMS;
3192 glBindTexture(GL_TEXTURE_2D, colorMS);
3193 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3194
3195 GLTexture depthMS;
3196 glBindTexture(GL_TEXTURE_2D, depthMS);
3197 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kWidth, 1, 0, GL_DEPTH_STENCIL,
3198 GL_UNSIGNED_INT_24_8_OES, nullptr);
3199
3200 GLFramebuffer fboMS;
3201 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3202 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3203 colorMS, 0, 4);
3204 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3205 depthMS, 0, 4);
3206 ASSERT_GL_NO_ERROR();
3207
3208 // Setup draw program
3209 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3210 glUseProgram(drawColor);
3211 GLint colorUniformLocation =
3212 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3213 ASSERT_NE(colorUniformLocation, -1);
3214 GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
3215 ASSERT_NE(-1, positionLocation);
3216
3217 // Setup vertices such that depth is varied from top to bottom.
3218 std::array<Vector3, 6> quadVertices = {
3219 Vector3(-1.0f, 1.0f, 0.8f), Vector3(-1.0f, -1.0f, 0.2f), Vector3(1.0f, -1.0f, 0.2f),
3220 Vector3(-1.0f, 1.0f, 0.8f), Vector3(1.0f, -1.0f, 0.2f), Vector3(1.0f, 1.0f, 0.8f),
3221 };
3222 GLBuffer quadVertexBuffer;
3223 glBindBuffer(GL_ARRAY_BUFFER, quadVertexBuffer);
3224 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
3225 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3226 glEnableVertexAttribArray(positionLocation);
3227
3228 // Draw red into the framebuffer.
3229 glViewport(0, 0, kWidth, 1);
3230 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3231 glEnable(GL_DEPTH_TEST);
3232 glDepthFunc(GL_ALWAYS);
3233 glDrawArrays(GL_TRIANGLES, 0, 6);
3234 ASSERT_GL_NO_ERROR();
3235
3236 // Draw green such that half the samples of each pixel pass the depth test.
3237 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3238 glDepthFunc(GL_GREATER);
3239 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3240 ASSERT_GL_NO_ERROR();
3241
3242 const GLColor kExpected(127, 127, 0, 255);
3243 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
3244 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpected, 1);
3245 EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, 0, kExpected, 1);
3246
3247 glDisableVertexAttribArray(0);
3248 glBindBuffer(GL_ARRAY_BUFFER, 0);
3249 }
3250
3251 // Draw with depth buffer, with depth discard before the end of the render
3252 // pass. On desktop Windows AMD drivers, this would previously cause a crash
3253 // because of a NULL pDepthStencilResolveAttachment pointer when ending the
3254 // render pass. Other vendors don't seem to mind the NULL pointer.
TEST_P(MultisampledRenderToTextureES3Test,DepthStencilInvalidate)3255 TEST_P(MultisampledRenderToTextureES3Test, DepthStencilInvalidate)
3256 {
3257 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3258
3259 constexpr GLsizei kWidth = 64;
3260
3261 // Create multisampled framebuffer to draw into, with both color and depth attachments.
3262 GLTexture colorMS;
3263 glBindTexture(GL_TEXTURE_2D, colorMS);
3264 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3265
3266 GLRenderbuffer depthMS;
3267 glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
3268 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, kWidth, 1);
3269
3270 GLFramebuffer fboMS;
3271 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3272 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3273 colorMS, 0, 4);
3274 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
3275 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3276 ASSERT_GL_NO_ERROR();
3277
3278 // Setup draw program
3279 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3280 glUseProgram(drawColor);
3281 GLint colorUniformLocation =
3282 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3283 ASSERT_NE(colorUniformLocation, -1);
3284 GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
3285 ASSERT_NE(-1, positionLocation);
3286
3287 // Setup vertices such that depth is varied from top to bottom.
3288 std::array<Vector3, 6> quadVertices = {
3289 Vector3(-1.0f, 1.0f, 0.8f), Vector3(-1.0f, -1.0f, 0.2f), Vector3(1.0f, -1.0f, 0.2f),
3290 Vector3(-1.0f, 1.0f, 0.8f), Vector3(1.0f, -1.0f, 0.2f), Vector3(1.0f, 1.0f, 0.8f),
3291 };
3292 GLBuffer quadVertexBuffer;
3293 glBindBuffer(GL_ARRAY_BUFFER, quadVertexBuffer);
3294 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
3295 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3296 glEnableVertexAttribArray(positionLocation);
3297
3298 // Draw red into the framebuffer.
3299 glViewport(0, 0, kWidth, 1);
3300 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3301 glEnable(GL_DEPTH_TEST);
3302 glDepthFunc(GL_ALWAYS);
3303 glDrawArrays(GL_TRIANGLES, 0, 6);
3304 ASSERT_GL_NO_ERROR();
3305
3306 // Draw green such that half the samples of each pixel pass the depth test.
3307 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3308 glDepthFunc(GL_GREATER);
3309 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3310 ASSERT_GL_NO_ERROR();
3311
3312 // Invalidate depth attachment
3313 GLenum discardDepth[] = {GL_DEPTH_ATTACHMENT};
3314 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, discardDepth);
3315
3316 // End render pass with pixel reads, ensure no crash occurs here.
3317 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3318 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMS);
3319
3320 const GLColor kExpected(127, 127, 0, 255);
3321 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
3322 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpected, 1);
3323 EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, 0, kExpected, 1);
3324
3325 glDisableVertexAttribArray(0);
3326 glBindBuffer(GL_ARRAY_BUFFER, 0);
3327 }
3328
3329 // Draw, copy, then blend. The copy will make sure an implicit resolve happens. Regardless, the
3330 // following draw should retain the data written by the first draw command.
3331 // Uses color attachments 0 and 1. Attachment 0 is a normal multisampled texture, while attachment
3332 // 1 is a multisampled-render-to-texture texture.
TEST_P(MultisampledRenderToTextureES31Test,MixedMultisampledAndMultisampledRenderToTexture)3333 TEST_P(MultisampledRenderToTextureES31Test, MixedMultisampledAndMultisampledRenderToTexture)
3334 {
3335 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3336 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
3337 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3338
3339 constexpr GLsizei kSize = 64;
3340
3341 setupCopyTexProgram();
3342
3343 // Create multisampled framebuffer to draw into, use color attachment 1
3344 GLTexture colorMS0;
3345 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, colorMS0);
3346 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);
3347
3348 GLTexture colorMS1;
3349 glBindTexture(GL_TEXTURE_2D, colorMS1);
3350 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3351
3352 GLFramebuffer fboMS;
3353 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3354 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3355 colorMS0, 0);
3356 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
3357 colorMS1, 0, 4);
3358 ASSERT_GL_NO_ERROR();
3359
3360 // Setup program to render into attachments 0 and 1.
3361 constexpr bool kBuffersEnabled[8] = {true, true};
3362
3363 GLuint drawColor;
3364 setupUniformColorProgramMultiRenderTarget(kBuffersEnabled, &drawColor);
3365 glUseProgram(drawColor);
3366 GLint colorUniformLocation =
3367 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3368 ASSERT_NE(colorUniformLocation, -1);
3369
3370 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3371 glDrawBuffers(2, kDrawBuffers);
3372 glReadBuffer(GL_COLOR_ATTACHMENT1);
3373 ASSERT_GL_NO_ERROR();
3374
3375 // Draw red into the multisampled color buffers.
3376 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3377 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3378 ASSERT_GL_NO_ERROR();
3379
3380 // Create a texture and copy from one of them.
3381 GLTexture texture;
3382 glBindTexture(GL_TEXTURE_2D, texture);
3383 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
3384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3386 ASSERT_GL_NO_ERROR();
3387
3388 // Blend half-transparent green into the multisampled color buffers.
3389 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
3390 glEnable(GL_BLEND);
3391 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3392 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3393 ASSERT_GL_NO_ERROR();
3394
3395 // Verify that the textures are now yellow
3396 const GLColor kExpected(127, 127, 0, 191);
3397 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
3398 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
3399 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
3400 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
3401
3402 // For completeness, verify that the texture used as copy target is red.
3403 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
3404
3405 ASSERT_GL_NO_ERROR();
3406
3407 glDeleteProgram(drawColor);
3408 }
3409
blitFramebufferAttachment1Common(bool useRenderbuffer)3410 void MultisampledRenderToTextureES31Test::blitFramebufferAttachment1Common(bool useRenderbuffer)
3411 {
3412 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3413 ANGLE_SKIP_TEST_IF(!useRenderbuffer &&
3414 !EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
3415 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3416
3417 constexpr GLsizei kSize = 16;
3418
3419 GLFramebuffer fboMS;
3420 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3421
3422 // Create multisampled framebuffer to draw into, use color attachment 1
3423 GLTexture colorMS0;
3424 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, colorMS0);
3425 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);
3426 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3427 colorMS0, 0);
3428
3429 GLTexture textureMS1;
3430 GLRenderbuffer renderbufferMS1;
3431 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT1, nullptr,
3432 mTestSampleCount, &textureMS1, &renderbufferMS1);
3433 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3434
3435 // Setup program to render into attachments 0 and 1.
3436 constexpr bool kBuffersEnabled[8] = {true, true};
3437
3438 GLuint drawColor;
3439 setupUniformColorProgramMultiRenderTarget(kBuffersEnabled, &drawColor);
3440 glUseProgram(drawColor);
3441 GLint colorUniformLocation =
3442 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3443 ASSERT_NE(colorUniformLocation, -1);
3444
3445 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3446 glDrawBuffers(2, kDrawBuffers);
3447 glReadBuffer(GL_COLOR_ATTACHMENT1);
3448 ASSERT_GL_NO_ERROR();
3449
3450 // Draw red into the multisampled color buffers.
3451 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3452 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3453 ASSERT_GL_NO_ERROR();
3454
3455 // Create single sampled framebuffer to use as dest.
3456 GLFramebuffer fboSS;
3457 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3458 GLTexture colorSS;
3459 glBindTexture(GL_TEXTURE_2D, colorSS);
3460 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3461 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorSS, 0);
3462 ASSERT_GL_NO_ERROR();
3463
3464 // Bind MS to READ as SS is already bound to DRAW.
3465 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMS);
3466 glReadBuffer(GL_COLOR_ATTACHMENT1);
3467 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3468 ASSERT_GL_NO_ERROR();
3469
3470 // Bind SS to READ so we can readPixels from it
3471 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3472
3473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3474 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
3475 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
3476 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
3477 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::red);
3478 ASSERT_GL_NO_ERROR();
3479 }
3480
3481 // BlitFramebuffer functionality test with mixed color attachments where multisampled render to
3482 // texture as attachment 1 and is the read buffer. This test makes sure the fact that attachment 0
3483 // is a true multisampled texture doesn't cause issues.
3484 // Uses EXT_multisampled_render_to_texture2.
TEST_P(MultisampledRenderToTextureES31Test,BlitFramebufferAttachment1)3485 TEST_P(MultisampledRenderToTextureES31Test, BlitFramebufferAttachment1)
3486 {
3487 blitFramebufferAttachment1Common(false);
3488 }
3489
3490 // BlitFramebuffer functionality test with mixed color attachments where multisampled render to
3491 // texture as attachment 1 and is the read buffer. This test makes sure the fact that attachment 0
3492 // is a true multisampled texture doesn't cause issues.
3493 // Uses renderbuffer.
TEST_P(MultisampledRenderToTextureES31Test,RenderbufferBlitFramebufferAttachment1)3494 TEST_P(MultisampledRenderToTextureES31Test, RenderbufferBlitFramebufferAttachment1)
3495 {
3496 blitFramebufferAttachment1Common(true);
3497 }
3498
blitFramebufferMixedColorAndDepthCommon(bool useRenderbuffer)3499 void MultisampledRenderToTextureES3Test::blitFramebufferMixedColorAndDepthCommon(
3500 bool useRenderbuffer)
3501 {
3502 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3503
3504 constexpr GLsizei kSize = 16;
3505
3506 GLFramebuffer fboMS;
3507 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3508
3509 // Create multisampled framebuffer to use as source.
3510 GLRenderbuffer depthMS;
3511 glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
3512 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, kSize, kSize);
3513 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
3514
3515 GLTexture textureMS;
3516 GLRenderbuffer renderbufferMS;
3517 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
3518 mTestSampleCount, &textureMS, &renderbufferMS);
3519 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3520
3521 // Clear depth to 0.5 and color to red.
3522 glClearDepthf(0.5f);
3523 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
3524 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
3525 ASSERT_GL_NO_ERROR();
3526
3527 // Create single sampled framebuffer to use as dest.
3528 GLRenderbuffer depthSS;
3529 glBindRenderbuffer(GL_RENDERBUFFER, depthSS);
3530 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
3531
3532 GLTexture colorSS;
3533 glBindTexture(GL_TEXTURE_2D, colorSS);
3534 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3535
3536 GLFramebuffer fboSS;
3537 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3538 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthSS);
3539 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorSS, 0);
3540 ASSERT_GL_NO_ERROR();
3541
3542 // Bind MS to READ as SS is already bound to DRAW.
3543 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMS);
3544 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
3545 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3546 ASSERT_GL_NO_ERROR();
3547
3548 // Bind SS to READ so we can readPixels from it
3549 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3550
3551 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3552 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
3553 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
3554 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
3555 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::red);
3556 ASSERT_GL_NO_ERROR();
3557
3558 // Use a small shader to verify depth.
3559 ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
3560 ANGLE_GL_PROGRAM(depthTestProgramFail, essl1_shaders::vs::Passthrough(),
3561 essl1_shaders::fs::Green());
3562 glEnable(GL_DEPTH_TEST);
3563 glDepthFunc(GL_LESS);
3564 drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), -0.01f);
3565 drawQuad(depthTestProgramFail, essl1_shaders::PositionAttrib(), 0.01f);
3566 glDisable(GL_DEPTH_TEST);
3567 ASSERT_GL_NO_ERROR();
3568
3569 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3570 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3571 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
3572 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3573 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::blue);
3574 ASSERT_GL_NO_ERROR();
3575 }
3576
3577 // BlitFramebuffer functionality test with mixed multisampled-render-to-texture color attachment and
3578 // multisampled depth buffer. This test makes sure that the color attachment is blitted, while
3579 // the depth/stencil attachment is resolved.
TEST_P(MultisampledRenderToTextureES3Test,BlitFramebufferMixedColorAndDepth)3580 TEST_P(MultisampledRenderToTextureES3Test, BlitFramebufferMixedColorAndDepth)
3581 {
3582 blitFramebufferMixedColorAndDepthCommon(false);
3583 }
3584
3585 // BlitFramebuffer functionality test with mixed multisampled-render-to-texture color attachment and
3586 // multisampled depth buffer. This test makes sure that the color attachment is blitted, while
3587 // the depth/stencil attachment is resolved. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferBlitFramebufferMixedColorAndDepth)3588 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferBlitFramebufferMixedColorAndDepth)
3589 {
3590 blitFramebufferMixedColorAndDepthCommon(true);
3591 }
3592
3593 // Draw non-multisampled, draw multisampled, repeat. This tests the same texture being bound
3594 // differently to two FBOs.
TEST_P(MultisampledRenderToTextureTest,DrawNonMultisampledThenMultisampled)3595 TEST_P(MultisampledRenderToTextureTest, DrawNonMultisampledThenMultisampled)
3596 {
3597 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3598 constexpr GLsizei kSize = 64;
3599
3600 // http://anglebug.com/4935
3601 ANGLE_SKIP_TEST_IF(IsD3D11());
3602
3603 // Texture attachment to the two framebuffers.
3604 GLTexture color;
3605 glBindTexture(GL_TEXTURE_2D, color);
3606 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3607
3608 // Create singlesampled framebuffer.
3609 GLFramebuffer fboSS;
3610 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3611 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3612 ASSERT_GL_NO_ERROR();
3613
3614 // Create multisampled framebuffer.
3615 GLFramebuffer fboMS;
3616 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3617 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
3618 0, 4);
3619 ASSERT_GL_NO_ERROR();
3620
3621 // Draw red into the multisampled color buffer.
3622 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3623 glUseProgram(drawColor);
3624 GLint colorUniformLocation =
3625 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3626 ASSERT_NE(colorUniformLocation, -1);
3627
3628 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3629 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3630 ASSERT_GL_NO_ERROR();
3631
3632 // Draw green into the singlesampled color buffer
3633 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3634 glEnable(GL_SCISSOR_TEST);
3635 glScissor(kSize / 8, kSize / 8, 3 * kSize / 4, 3 * kSize / 4);
3636 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3637 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3638 ASSERT_GL_NO_ERROR();
3639
3640 // Draw blue into the multisampled color buffer
3641 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3642 glScissor(kSize / 4, kSize / 4, kSize / 2, kSize / 2);
3643 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3644 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3645 ASSERT_GL_NO_ERROR();
3646
3647 // Verify that the texture is red on the border, blue in the middle and green in between.
3648 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboSS);
3649
3650 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3651 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
3652 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
3653 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
3654
3655 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 16, 3 * kSize / 16, GLColor::green);
3656 EXPECT_PIXEL_COLOR_EQ(13 * kSize / 16, 3 * kSize / 16, GLColor::green);
3657 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 16, 13 * kSize / 16, GLColor::green);
3658 EXPECT_PIXEL_COLOR_EQ(13 * kSize / 16, 13 * kSize / 16, GLColor::green);
3659
3660 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 8, 3 * kSize / 8, GLColor::blue);
3661 EXPECT_PIXEL_COLOR_EQ(5 * kSize / 8, 3 * kSize / 8, GLColor::blue);
3662 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 8, 5 * kSize / 8, GLColor::blue);
3663 EXPECT_PIXEL_COLOR_EQ(5 * kSize / 8, 5 * kSize / 8, GLColor::blue);
3664 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::blue);
3665
3666 ASSERT_GL_NO_ERROR();
3667 }
3668
3669 // Draw multisampled, draw multisampled with another sample count, repeat. This tests the same
3670 // texture being bound as multisampled-render-to-texture with different sample counts to two FBOs.
TEST_P(MultisampledRenderToTextureTest,DrawMultisampledDifferentSamples)3671 TEST_P(MultisampledRenderToTextureTest, DrawMultisampledDifferentSamples)
3672 {
3673 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3674 constexpr GLsizei kSize = 64;
3675
3676 GLsizei maxSamples = 0;
3677 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
3678 ASSERT_GE(maxSamples, 4);
3679
3680 // Texture attachment to the two framebuffers.
3681 GLTexture color;
3682 glBindTexture(GL_TEXTURE_2D, color);
3683 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3684
3685 // Create two multisampled framebuffers.
3686 GLFramebuffer fboMS1;
3687 glBindFramebuffer(GL_FRAMEBUFFER, fboMS1);
3688 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
3689 0, 4);
3690
3691 GLFramebuffer fboMS2;
3692 glBindFramebuffer(GL_FRAMEBUFFER, fboMS2);
3693 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
3694 0, maxSamples);
3695 ASSERT_GL_NO_ERROR();
3696
3697 // Draw red into the first multisampled color buffer.
3698 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3699 glUseProgram(drawColor);
3700 GLint colorUniformLocation =
3701 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3702 ASSERT_NE(colorUniformLocation, -1);
3703
3704 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3705 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3706 ASSERT_GL_NO_ERROR();
3707
3708 // Draw green into the second multisampled color buffer
3709 glBindFramebuffer(GL_FRAMEBUFFER, fboMS1);
3710 glEnable(GL_SCISSOR_TEST);
3711 glScissor(kSize / 8, kSize / 8, 3 * kSize / 4, 3 * kSize / 4);
3712 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3713 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3714 ASSERT_GL_NO_ERROR();
3715
3716 // Draw blue into the first multisampled color buffer
3717 glBindFramebuffer(GL_FRAMEBUFFER, fboMS2);
3718 glScissor(kSize / 4, kSize / 4, kSize / 2, kSize / 2);
3719 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3720 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3721 ASSERT_GL_NO_ERROR();
3722
3723 // Verify that the texture is red on the border, blue in the middle and green in between.
3724 GLFramebuffer fboSS;
3725 glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
3726 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3727 ASSERT_GL_NO_ERROR();
3728
3729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3730 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
3731 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
3732 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
3733
3734 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 16, 3 * kSize / 16, GLColor::green);
3735 EXPECT_PIXEL_COLOR_EQ(13 * kSize / 16, 3 * kSize / 16, GLColor::green);
3736 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 16, 13 * kSize / 16, GLColor::green);
3737 EXPECT_PIXEL_COLOR_EQ(13 * kSize / 16, 13 * kSize / 16, GLColor::green);
3738
3739 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 8, 3 * kSize / 8, GLColor::blue);
3740 EXPECT_PIXEL_COLOR_EQ(5 * kSize / 8, 3 * kSize / 8, GLColor::blue);
3741 EXPECT_PIXEL_COLOR_EQ(3 * kSize / 8, 5 * kSize / 8, GLColor::blue);
3742 EXPECT_PIXEL_COLOR_EQ(5 * kSize / 8, 5 * kSize / 8, GLColor::blue);
3743 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::blue);
3744
3745 ASSERT_GL_NO_ERROR();
3746 }
3747
drawCopyThenBlendAllAttachmentsMixed(bool useRenderbuffer)3748 void MultisampledRenderToTextureES31Test::drawCopyThenBlendAllAttachmentsMixed(bool useRenderbuffer)
3749 {
3750 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3751 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
3752
3753 GLint maxDrawBuffers = 0;
3754 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3755
3756 // At least 4 draw buffers per GLES3.0 spec.
3757 ASSERT_GE(maxDrawBuffers, 4);
3758
3759 // Maximum 8 draw buffers exposed by ANGLE.
3760 constexpr GLint kImplMaxDrawBuffers = 8;
3761 maxDrawBuffers = std::min(maxDrawBuffers, kImplMaxDrawBuffers);
3762
3763 // Integer formats are mixed in which have different sample count limits. A framebuffer must
3764 // have the same sample count for all attachments.
3765 const GLint sampleCount = std::min(mTestSampleCount, mMaxIntegerSamples);
3766
3767 constexpr const char *kDecl[kImplMaxDrawBuffers] = {
3768 "layout(location = 0) out vec4 out0;", "layout(location = 1) out ivec4 out1;",
3769 "layout(location = 2) out uvec4 out2;", "layout(location = 3) out vec4 out3;",
3770 "layout(location = 4) out uvec4 out4;", "layout(location = 5) out ivec4 out5;",
3771 "layout(location = 6) out ivec4 out6;", "layout(location = 7) out vec4 out7;",
3772 };
3773
3774 constexpr GLType kGLType[kImplMaxDrawBuffers] = {
3775 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT},
3776 {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
3777 {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT},
3778 {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
3779 };
3780
3781 constexpr const char *kAssign1[kImplMaxDrawBuffers] = {
3782 "out0 = vec4(1.0f, 0.0f, 0.0f, 1.0f);",
3783 "out1 = ivec4(-19, 13, 123456, -654321);",
3784 "out2 = uvec4(98765, 43210, 2, 0);",
3785 "out3 = vec4(0.0f, 1.0f, 0.0f, 1.0f);",
3786 "out4 = uvec4(10101010, 2345, 0, 991);",
3787 "out5 = ivec4(615243, -948576, -222, 111);",
3788 "out6 = ivec4(-8127931, -1392781, 246810, 1214161820);",
3789 "out7 = vec4(0.0f, 0.0f, 1.0f, 1.0f);",
3790 };
3791
3792 constexpr const char *kAssign2[kImplMaxDrawBuffers] = {
3793 "out0 = vec4(0.0f, 1.0f, 0.0f, 0.5f);",
3794 "out1 = ivec4(0, 0, 0, 0);",
3795 "out2 = uvec4(0, 0, 0, 0);",
3796 "out3 = vec4(0.0f, 0.0f, 1.0f, 0.5f);",
3797 "out4 = uvec4(0, 0, 0, 0);",
3798 "out5 = ivec4(0, 0, 0, 0);",
3799 "out6 = ivec4(0, 0, 0, 0);",
3800 "out7 = vec4(1.0f, 0.0f, 0.0f, 0.5f);",
3801 };
3802
3803 // Generate the shaders, [0] for first draw and [1] for second.
3804 std::stringstream fsStr[2];
3805 for (unsigned int index = 0; index < 2; ++index)
3806 {
3807 fsStr[index] << R"(#version 300 es
3808 precision highp float;
3809 )";
3810
3811 for (GLint drawBuffer = 0; drawBuffer < maxDrawBuffers; ++drawBuffer)
3812 {
3813 fsStr[index] << kDecl[drawBuffer] << "\n";
3814 }
3815
3816 fsStr[index] << R"(void main()
3817 {
3818 )";
3819
3820 const char *const *assign = index == 0 ? kAssign1 : kAssign2;
3821 for (GLint drawBuffer = 0; drawBuffer < maxDrawBuffers; ++drawBuffer)
3822 {
3823 fsStr[index] << assign[drawBuffer] << "\n";
3824 }
3825
3826 fsStr[index] << "}\n";
3827 }
3828
3829 constexpr GLsizei kSize = 64;
3830
3831 setupCopyTexProgram();
3832
3833 // Create multisampled framebuffer to draw into
3834 GLFramebuffer fboMS;
3835 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3836
3837 GLTexture textureMS[kImplMaxDrawBuffers];
3838 GLRenderbuffer renderbufferMS[kImplMaxDrawBuffers];
3839 for (GLint drawBuffer = 0; drawBuffer < maxDrawBuffers; ++drawBuffer)
3840 {
3841 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0 + drawBuffer,
3842 &kGLType[drawBuffer], sampleCount, &textureMS[drawBuffer],
3843 &renderbufferMS[drawBuffer]);
3844 }
3845 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3846
3847 // Setup programs
3848 ANGLE_GL_PROGRAM(drawProg, essl3_shaders::vs::Simple(), fsStr[0].str().c_str());
3849 ANGLE_GL_PROGRAM(blendProg, essl3_shaders::vs::Simple(), fsStr[1].str().c_str());
3850
3851 constexpr GLenum kDrawBuffers[] = {
3852 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3853 GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7};
3854 glDrawBuffers(maxDrawBuffers, kDrawBuffers);
3855 ASSERT_GL_NO_ERROR();
3856
3857 // Draw into the multisampled color buffers.
3858 glUseProgram(drawProg);
3859 drawQuad(drawProg, essl3_shaders::PositionAttrib(), 0.5f);
3860 ASSERT_GL_NO_ERROR();
3861
3862 // Create a texture and copy from one of them.
3863 GLTexture texture;
3864 glBindTexture(GL_TEXTURE_2D, texture);
3865 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
3866 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3867 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3868 ASSERT_GL_NO_ERROR();
3869
3870 // Blend color buffers.
3871 glUseProgram(blendProg);
3872 glEnable(GL_BLEND);
3873 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3874 drawQuad(blendProg, essl3_shaders::PositionAttrib(), 0.5f);
3875 ASSERT_GL_NO_ERROR();
3876
3877 // Verify texture colors.
3878 glReadBuffer(GL_COLOR_ATTACHMENT0);
3879 const GLColor kExpected0(127, 127, 0, 191);
3880 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected0, 1);
3881 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected0, 1);
3882 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected0, 1);
3883 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected0, 1);
3884
3885 glReadBuffer(GL_COLOR_ATTACHMENT3);
3886 const GLColor kExpected3(0, 127, 127, 191);
3887 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected3, 1);
3888 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected3, 1);
3889 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected3, 1);
3890 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected3, 1);
3891
3892 if (maxDrawBuffers > 7)
3893 {
3894 glReadBuffer(GL_COLOR_ATTACHMENT7);
3895 const GLColor kExpected7(127, 0, 127, 191);
3896 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected7, 1);
3897 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected7, 1);
3898 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected7, 1);
3899 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected7, 1);
3900 }
3901
3902 // For completeness, verify that the texture used as copy target is red.
3903 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
3904
3905 ASSERT_GL_NO_ERROR();
3906 }
3907
3908 // Draw, copy, then blend with 8 mixed format attachments. The copy will make sure an implicit
3909 // resolve happens. Regardless, the following draw should retain the data written by the first draw
3910 // command.
TEST_P(MultisampledRenderToTextureES31Test,DrawCopyThenBlendAllAttachmentsMixed)3911 TEST_P(MultisampledRenderToTextureES31Test, DrawCopyThenBlendAllAttachmentsMixed)
3912 {
3913 drawCopyThenBlendAllAttachmentsMixed(false);
3914 }
3915
3916 // Same as DrawCopyThenBlendAllAttachmentsMixed but with renderbuffers.
TEST_P(MultisampledRenderToTextureES31Test,RenderbufferDrawCopyThenBlendAllAttachmentsMixed)3917 TEST_P(MultisampledRenderToTextureES31Test, RenderbufferDrawCopyThenBlendAllAttachmentsMixed)
3918 {
3919 // Linux Intel Vulkan returns 0 for GL_MAX_INTEGER_SAMPLES http://anglebug.com/5988
3920 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
3921
3922 drawCopyThenBlendAllAttachmentsMixed(true);
3923 }
3924
renderbufferUnresolveColorAndDepthStencilThenTwoColors(bool withDepth,bool withStencil)3925 void MultisampledRenderToTextureES3Test::renderbufferUnresolveColorAndDepthStencilThenTwoColors(
3926 bool withDepth,
3927 bool withStencil)
3928 {
3929 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3930 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
3931 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3932
3933 // http://anglebug.com/5096
3934 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
3935
3936 constexpr GLsizei kSize = 64;
3937
3938 setupCopyTexProgram();
3939
3940 GLFramebuffer fboColorAndDepthStencil;
3941 glBindFramebuffer(GL_FRAMEBUFFER, fboColorAndDepthStencil);
3942
3943 // Create framebuffer to draw into, with both color and depth/stencil attachments.
3944 GLTexture color1;
3945 glBindTexture(GL_TEXTURE_2D, color1);
3946 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3947 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3948 color1, 0, 4);
3949
3950 GLenum depthStencilFormat = GL_DEPTH24_STENCIL8;
3951 GLenum depthStencilTarget = GL_DEPTH_STENCIL_ATTACHMENT;
3952
3953 ASSERT_TRUE(withDepth || withStencil);
3954 if (withDepth && !withStencil)
3955 {
3956 depthStencilFormat = GL_DEPTH_COMPONENT24;
3957 depthStencilTarget = GL_DEPTH_ATTACHMENT;
3958 }
3959 if (!withDepth && withStencil)
3960 {
3961 depthStencilFormat = GL_STENCIL_INDEX8;
3962 depthStencilTarget = GL_STENCIL_ATTACHMENT;
3963 }
3964
3965 GLRenderbuffer depthStencil;
3966 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
3967 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, depthStencilFormat, kSize, kSize);
3968 glFramebufferRenderbuffer(GL_FRAMEBUFFER, depthStencilTarget, GL_RENDERBUFFER, depthStencil);
3969 ASSERT_GL_NO_ERROR();
3970 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3971
3972 // Set viewport and clear depth/stencil
3973 glViewport(0, 0, kSize, kSize);
3974 glClearDepthf(1);
3975 glClearStencil(0x55);
3976 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3977
3978 // If depth is not cleared to 1, rendering would fail.
3979 if (withDepth)
3980 {
3981 glEnable(GL_DEPTH_TEST);
3982 glDepthFunc(GL_LESS);
3983 }
3984
3985 // If stencil is not cleared to 0x55, rendering would fail.
3986 if (withStencil)
3987 {
3988 glEnable(GL_STENCIL_TEST);
3989 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
3990 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3991 glStencilMask(0xFF);
3992 }
3993
3994 // Set up program
3995 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3996 glUseProgram(drawColor);
3997 GLint colorUniformLocation =
3998 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3999 ASSERT_NE(colorUniformLocation, -1);
4000
4001 // Draw red
4002 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4003 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f);
4004 ASSERT_GL_NO_ERROR();
4005
4006 // Create a texture and copy into it.
4007 GLTexture texture;
4008 glBindTexture(GL_TEXTURE_2D, texture);
4009 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
4010 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4011 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4012 ASSERT_GL_NO_ERROR();
4013
4014 // Draw again into the framebuffer, this time blending. This tests that both the color and
4015 // depth/stencil data are preserved after the resolve incurred by the copy above.
4016 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
4017 glEnable(GL_BLEND);
4018 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4019 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4020 ASSERT_GL_NO_ERROR();
4021
4022 // Verify that the texture is now yellow
4023 const GLColor kExpected(127, 127, 0, 191);
4024 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
4025 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
4026 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
4027 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
4028
4029 // For completeness, verify that the texture used as copy target is red.
4030 verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
4031
4032 // Now create a framebuffer with two color attachments and do something similar. This makes
4033 // sure that the fact that both these framebuffers have 2 attachments does not cause confusion,
4034 // for example by having the unresolve shader generated for the first framebuffer used for the
4035 // second framebuffer.
4036 GLFramebuffer fboTwoColors;
4037 glBindFramebuffer(GL_FRAMEBUFFER, fboTwoColors);
4038
4039 GLTexture color2;
4040 glBindTexture(GL_TEXTURE_2D, color2);
4041 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4042 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
4043 color2, 0, 4);
4044
4045 GLTexture color3;
4046 glBindTexture(GL_TEXTURE_2D, color3);
4047 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4048 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
4049 color3, 0, 4);
4050
4051 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4052
4053 glDisable(GL_DEPTH_TEST);
4054 glDisable(GL_STENCIL_TEST);
4055 glDisable(GL_BLEND);
4056
4057 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
4058 glDrawBuffers(2, kDrawBuffers);
4059 glReadBuffer(GL_COLOR_ATTACHMENT1);
4060
4061 // Setup program
4062 constexpr bool kBuffersEnabled[8] = {true, true};
4063
4064 GLuint drawColorMRT;
4065 setupUniformColorProgramMultiRenderTarget(kBuffersEnabled, &drawColorMRT);
4066 glUseProgram(drawColorMRT);
4067 GLint colorUniformLocationMRT =
4068 glGetUniformLocation(drawColorMRT, angle::essl1_shaders::ColorUniform());
4069 ASSERT_NE(colorUniformLocationMRT, -1);
4070
4071 // Draw blue
4072 glUniform4f(colorUniformLocationMRT, 0.0f, 0.0f, 1.0f, 1.0f);
4073 drawQuad(drawColorMRT, essl1_shaders::PositionAttrib(), 0.5f);
4074 ASSERT_GL_NO_ERROR();
4075
4076 // Copy into texture
4077 glBindTexture(GL_TEXTURE_2D, texture);
4078 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
4079
4080 // Blend.
4081 glUniform4f(colorUniformLocationMRT, 0.0f, 1.0f, 0.0f, 0.5f);
4082 glEnable(GL_BLEND);
4083 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4084 drawQuad(drawColorMRT, essl1_shaders::PositionAttrib(), 0.0f);
4085 ASSERT_GL_NO_ERROR();
4086
4087 // Verify that the texture is now cyan
4088 const GLColor kExpected2(0, 127, 127, 191);
4089 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected2, 1);
4090 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected2, 1);
4091 EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected2, 1);
4092 EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected2, 1);
4093
4094 // For completeness, verify that the texture used as copy target is blue.
4095 verifyResults(texture, GLColor::blue, kSize, 0, 0, kSize, kSize);
4096 }
4097
4098 // Draw, copy, then blend once on a framebuffer with color and depth attachments, and once with two
4099 // color attachments. Tests that unresolve is done correctly on two framebuffers with the same
4100 // number of attachments, but differing in depth being there. Note that this test doesn't apply to
4101 // depth/stencil textures as they are explicitly autoinvalidated between render passes.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferUnresolveColorAndDepthThenTwoColors)4102 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndDepthThenTwoColors)
4103 {
4104 renderbufferUnresolveColorAndDepthStencilThenTwoColors(true, false);
4105 }
4106
4107 // Similar to RenderbufferUnresolveColorAndDepthThenTwoColors, but with stencil.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferUnresolveColorAndStencilThenTwoColors)4108 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndStencilThenTwoColors)
4109 {
4110 renderbufferUnresolveColorAndDepthStencilThenTwoColors(false, true);
4111 }
4112
4113 // Similar to RenderbufferUnresolveColorAndDepthThenTwoColors, but with depth and stencil.
TEST_P(MultisampledRenderToTextureES3Test,RenderbufferUnresolveColorAndDepthStencilThenTwoColors)4114 TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndDepthStencilThenTwoColors)
4115 {
4116 renderbufferUnresolveColorAndDepthStencilThenTwoColors(true, true);
4117 }
4118
4119 // Make sure deferred clears are flushed correctly when the framebuffer switches between
4120 // needing unresolve and not needing it.
TEST_P(MultisampledRenderToTextureES3Test,ClearThenMaskedClearFramebufferTest)4121 TEST_P(MultisampledRenderToTextureES3Test, ClearThenMaskedClearFramebufferTest)
4122 {
4123 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4124
4125 constexpr GLsizei kSize = 16;
4126
4127 GLFramebuffer fboMS;
4128 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
4129
4130 // Create multisampled framebuffer to use as source.
4131 GLRenderbuffer depthMS;
4132 glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
4133 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, kSize, kSize);
4134 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
4135 ASSERT_GL_NO_ERROR();
4136
4137 GLTexture textureMS;
4138 GLRenderbuffer renderbufferMS;
4139 createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT0, nullptr, mTestSampleCount,
4140 &textureMS, &renderbufferMS);
4141 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4142
4143 // Clear depth to 0.5 and color to green.
4144 glClearDepthf(0.5f);
4145 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
4146 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
4147 ASSERT_GL_NO_ERROR();
4148
4149 // Break the render pass.
4150 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4151
4152 // Draw red into the multisampled color buffer. An unresolve operation is needed.
4153 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4154 ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4155 glEnable(GL_DEPTH_TEST);
4156 glDepthFunc(GL_LEQUAL);
4157 drawQuad(drawRed, essl1_shaders::PositionAttrib(), -0.05f);
4158 drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.05f);
4159 ASSERT_GL_NO_ERROR();
4160
4161 // Break the render pass.
4162 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4163
4164 // Clear color to transparent blue.
4165 glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
4166 glClear(GL_COLOR_BUFFER_BIT);
4167
4168 // Clear both color and depth, with color masked.
4169 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
4170 glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
4171 glClearDepthf(0.3f);
4172 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4173
4174 // Make sure the result is blue.
4175 EXPECT_PIXEL_RECT_EQ(0, 0, kSize - 1, kSize - 1, GLColor::blue);
4176 ASSERT_GL_NO_ERROR();
4177 }
4178
4179 // Make sure mid render pass clear works correctly.
TEST_P(MultisampledRenderToTextureES3Test,RenderToTextureMidRenderPassDepthClear)4180 TEST_P(MultisampledRenderToTextureES3Test, RenderToTextureMidRenderPassDepthClear)
4181 {
4182 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4183
4184 constexpr GLsizei kSize = 6;
4185
4186 // Create multisampled framebuffer to draw into, with both color and depth attachments.
4187 GLTexture colorMS;
4188 glBindTexture(GL_TEXTURE_2D, colorMS);
4189 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4190
4191 GLRenderbuffer depthStencilMS;
4192 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
4193 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
4194
4195 GLFramebuffer fboMS;
4196 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
4197 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
4198 colorMS, 0, 4);
4199 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
4200 depthStencilMS);
4201 ASSERT_GL_NO_ERROR();
4202
4203 // Set up texture for copy operation that breaks the render pass
4204 GLTexture copyTex;
4205 glBindTexture(GL_TEXTURE_2D, copyTex);
4206 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4207
4208 // First render pass: draw and then break the render pass so that we have initial data in the
4209 // depth buffer 0.75f
4210 glViewport(0, 0, kSize, kSize);
4211 glClearColor(0, 0, 0, 0.0f);
4212 glClearDepthf(0.0);
4213 glClearStencil(0x55);
4214 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4215 glEnable(GL_DEPTH_TEST);
4216 glDepthFunc(GL_ALWAYS);
4217 glDepthMask(GL_TRUE);
4218 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4219 // depthValue = 1/2 * 0.5f + 1/2 = 0.75f
4220 drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
4221 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize, kSize);
4222 ASSERT_GL_NO_ERROR();
4223
4224 // Second render pass: set depth test to always pass and then draw. ANGLE may optimize to not
4225 // load depth value. Depth buffer should still be 0.75f with color buffer being green.
4226 glDepthMask(GL_FALSE);
4227 glEnable(GL_DEPTH_TEST);
4228 glDepthFunc(GL_ALWAYS);
4229 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4230 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 1.0f);
4231
4232 // Now do mid-renderPass clear to 0.4f
4233 glDepthMask(GL_TRUE);
4234 glClearDepthf(0.4f);
4235 glClear(GL_DEPTH_BUFFER_BIT);
4236
4237 // Draw blue with depth value 0.5f. This should pass depth test (0.5f>=0.4f) and we see blue.
4238 // If mid-RenderPass clear not working properly, depthBuffer should still have 0.75 and depth
4239 // test will fail and you see Green.
4240 glDepthFunc(GL_GEQUAL);
4241 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4242 // depthValue = 1/2 * 0.0f + 1/2 = 0.5f
4243 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.0f);
4244
4245 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4246 ASSERT_GL_NO_ERROR();
4247 }
4248
4249 class MultisampledRenderToTextureWithAdvancedBlendTest : public MultisampledRenderToTextureES3Test
4250 {
4251 protected:
4252 enum class InitMethod
4253 {
4254 Clear,
4255 Load,
4256 };
4257
4258 void drawTestCommon(bool useRenderbuffer, InitMethod initMethod);
4259 };
4260
drawTestCommon(bool useRenderbuffer,InitMethod initMethod)4261 void MultisampledRenderToTextureWithAdvancedBlendTest::drawTestCommon(bool useRenderbuffer,
4262 InitMethod initMethod)
4263 {
4264 constexpr char kFS[] = R"(#version 300 es
4265 #extension GL_KHR_blend_equation_advanced : require
4266 precision mediump float;
4267 uniform vec4 color;
4268 layout (blend_support_multiply) out;
4269 layout (location = 0) out vec4 outColor;
4270 void main() {
4271 outColor = color;
4272 })";
4273
4274 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4275 glUseProgram(program);
4276
4277 GLint colorLoc = glGetUniformLocation(program, "color");
4278 ASSERT_NE(colorLoc, -1);
4279
4280 GLFramebuffer FBO;
4281 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
4282
4283 // Set up color attachment and bind to FBO
4284 constexpr GLsizei kSize = 1;
4285 GLTexture texture;
4286 GLRenderbuffer renderbuffer;
4287 createAndAttachColorAttachment(useRenderbuffer, kSize, GL_COLOR_ATTACHMENT0, nullptr,
4288 mTestSampleCount, &texture, &renderbuffer);
4289 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4290
4291 constexpr float kDst[4] = {1.0f, 0.25f, 0.5f, 1.0f};
4292 constexpr float kSrc[4] = {0.5f, 1.0f, 1.0f, 1.0f};
4293
4294 glClearColor(kDst[0], kDst[1], kDst[2], kDst[3]);
4295 glUniform4f(colorLoc, kSrc[0], kSrc[1], kSrc[2], kSrc[3]);
4296
4297 glEnable(GL_BLEND);
4298 glBlendEquation(GL_MULTIPLY_KHR);
4299
4300 if (initMethod == InitMethod::Load)
4301 {
4302 const GLColor kInitColor(0xFF, 0x3F, 0x7F, 0xFF);
4303 if (useRenderbuffer)
4304 {
4305 glClear(GL_COLOR_BUFFER_BIT);
4306 EXPECT_PIXEL_COLOR_NEAR(0, 0, kInitColor, 1);
4307 }
4308 else
4309 {
4310 std::vector<GLColor> initData(kSize * kSize, kInitColor);
4311 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4312 initData.data());
4313 }
4314 }
4315 else
4316 {
4317 glClear(GL_COLOR_BUFFER_BIT);
4318 }
4319 drawQuad(program, essl3_shaders::PositionAttrib(), 0);
4320
4321 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0x7F, 0x3F, 0x7F, 0xFF), 1);
4322 ASSERT_GL_NO_ERROR();
4323 }
4324
4325 // Interaction between GL_EXT_multisampled_render_to_texture and advanced blend.
TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest,LoadThenDraw)4326 TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest, LoadThenDraw)
4327 {
4328 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4329 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
4330
4331 drawTestCommon(false, InitMethod::Load);
4332 }
4333
4334 // Same as Draw, but with renderbuffers.
TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest,RenderbufferLoadThenDraw)4335 TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest, RenderbufferLoadThenDraw)
4336 {
4337 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4338 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
4339
4340 drawTestCommon(true, InitMethod::Load);
4341 }
4342
4343 // Interaction between GL_EXT_multisampled_render_to_texture and advanced blend.
TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest,ClearThenDraw)4344 TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest, ClearThenDraw)
4345 {
4346 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4347 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
4348
4349 drawTestCommon(false, InitMethod::Clear);
4350 }
4351
4352 // Same as Draw, but with renderbuffers.
TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest,RenderbufferClearThenDraw)4353 TEST_P(MultisampledRenderToTextureWithAdvancedBlendTest, RenderbufferClearThenDraw)
4354 {
4355 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4356 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
4357
4358 drawTestCommon(true, InitMethod::Clear);
4359 }
4360
4361 ANGLE_INSTANTIATE_TEST_COMBINE_1(
4362 MultisampledRenderToTextureTest,
4363 PrintToStringParamName,
4364 testing::Bool(),
4365 ANGLE_ALL_TEST_PLATFORMS_ES2,
4366 ANGLE_ALL_TEST_PLATFORMS_ES3,
4367 ANGLE_ALL_TEST_PLATFORMS_ES31,
4368 ES3_VULKAN()
4369 .disable(Feature::SupportsExtendedDynamicState)
4370 .disable(Feature::SupportsExtendedDynamicState2),
4371 ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
4372 ES3_VULKAN().disable(Feature::SupportsSPIRV14),
4373 ES3_VULKAN_SWIFTSHADER().enable(Feature::EnableMultisampledRenderToTexture),
4374 ES3_VULKAN_SWIFTSHADER()
4375 .enable(Feature::EnableMultisampledRenderToTexture)
4376 .enable(Feature::AsyncCommandQueue));
4377
4378 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampledRenderToTextureES3Test);
4379 ANGLE_INSTANTIATE_TEST_COMBINE_1(
4380 MultisampledRenderToTextureES3Test,
4381 PrintToStringParamName,
4382 testing::Bool(),
4383 ANGLE_ALL_TEST_PLATFORMS_ES3,
4384 ANGLE_ALL_TEST_PLATFORMS_ES31,
4385 ES3_VULKAN()
4386 .disable(Feature::SupportsExtendedDynamicState)
4387 .disable(Feature::SupportsExtendedDynamicState2),
4388 ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
4389 ES3_VULKAN().disable(Feature::SupportsSPIRV14),
4390 ES3_VULKAN_SWIFTSHADER().enable(Feature::EnableMultisampledRenderToTexture),
4391 ES3_VULKAN_SWIFTSHADER()
4392 .enable(Feature::EnableMultisampledRenderToTexture)
4393 .enable(Feature::AsyncCommandQueue));
4394
4395 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampledRenderToTextureES31Test);
4396 ANGLE_INSTANTIATE_TEST_COMBINE_1(
4397 MultisampledRenderToTextureES31Test,
4398 PrintToStringParamName,
4399 testing::Bool(),
4400 ANGLE_ALL_TEST_PLATFORMS_ES31,
4401 ES31_VULKAN()
4402 .disable(Feature::SupportsExtendedDynamicState)
4403 .disable(Feature::SupportsExtendedDynamicState2),
4404 ES31_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
4405 ES31_VULKAN().disable(Feature::SupportsSPIRV14),
4406 ES31_VULKAN_SWIFTSHADER().enable(Feature::EnableMultisampledRenderToTexture),
4407 ES31_VULKAN_SWIFTSHADER()
4408 .enable(Feature::EnableMultisampledRenderToTexture)
4409 .enable(Feature::AsyncCommandQueue));
4410
4411 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampledRenderToTextureWithAdvancedBlendTest);
4412 ANGLE_INSTANTIATE_TEST_COMBINE_1(
4413 MultisampledRenderToTextureWithAdvancedBlendTest,
4414 PrintToStringParamName,
4415 testing::Bool(),
4416 ANGLE_ALL_TEST_PLATFORMS_ES3,
4417 ANGLE_ALL_TEST_PLATFORMS_ES31,
4418 ES3_VULKAN().disable(Feature::SupportsSPIRV14),
4419 ES3_VULKAN_SWIFTSHADER().enable(Feature::EnableMultisampledRenderToTexture),
4420 ES3_VULKAN_SWIFTSHADER()
4421 .enable(Feature::EnableMultisampledRenderToTexture)
4422 .enable(Feature::AsyncCommandQueue));
4423 } // namespace
4424