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 // MultisampleTest: Tests of multisampled default framebuffer
8
9 #include "test_utils/ANGLETest.h"
10
11 #include "test_utils/gl_raii.h"
12 #include "util/OSWindow.h"
13 #include "util/shader_utils.h"
14 #include "util/test_utils.h"
15
16 using namespace angle;
17
18 namespace
19 {
20
21 class MultisampleTest : public ANGLETest<>
22 {
23 protected:
MultisampleTest()24 MultisampleTest()
25 {
26 setWindowWidth(kWindowWidth);
27 setWindowHeight(kWindowHeight);
28 setConfigRedBits(8);
29 setConfigGreenBits(8);
30 setConfigBlueBits(8);
31 setConfigAlphaBits(8);
32 setConfigDepthBits(24);
33 setConfigStencilBits(8);
34 setSamples(4);
35 setMultisampleEnabled(true);
36 }
37
prepareVertexBuffer(GLBuffer & vertexBuffer,const Vector3 * vertices,size_t vertexCount,GLint positionLocation)38 void prepareVertexBuffer(GLBuffer &vertexBuffer,
39 const Vector3 *vertices,
40 size_t vertexCount,
41 GLint positionLocation)
42 {
43 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
44 glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * vertexCount, vertices, GL_STATIC_DRAW);
45 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
46 glEnableVertexAttribArray(positionLocation);
47 }
48
49 protected:
50 static constexpr int kWindowWidth = 16;
51 static constexpr int kWindowHeight = 8;
52 };
53
54 class MultisampleTestES3 : public MultisampleTest
55 {};
56
57 class MultisampleTestES32 : public MultisampleTest
58 {};
59
60 // Test point rendering on a multisampled surface. GLES2 section 3.3.1.
TEST_P(MultisampleTest,Point)61 TEST_P(MultisampleTest, Point)
62 {
63 // http://anglebug.com/42262135
64 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
65 // http://anglebug.com/42264264
66 ANGLE_SKIP_TEST_IF(IsOzone());
67
68 constexpr char kPointsVS[] = R"(precision highp float;
69 attribute vec4 a_position;
70
71 void main()
72 {
73 gl_PointSize = 3.0;
74 gl_Position = a_position;
75 })";
76
77 ANGLE_GL_PROGRAM(program, kPointsVS, essl1_shaders::fs::Red());
78 glUseProgram(program);
79 const GLint positionLocation = glGetAttribLocation(program, "a_position");
80
81 GLBuffer vertexBuffer;
82 const Vector3 vertices[1] = {{0.0f, 0.0f, 0.0f}};
83 prepareVertexBuffer(vertexBuffer, vertices, 1, positionLocation);
84
85 glClear(GL_COLOR_BUFFER_BIT);
86 glDrawArrays(GL_POINTS, 0, 1);
87
88 ASSERT_GL_NO_ERROR();
89
90 // The center pixels should be all red.
91 EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2, kWindowHeight / 2, GLColor::red);
92 EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2 - 1, kWindowHeight / 2, GLColor::red);
93 EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2, kWindowHeight / 2 - 1, GLColor::red);
94 EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2 - 1, kWindowHeight / 2 - 1, GLColor::red);
95
96 // Border pixels should be between red and black, and not exactly either; corners are darker and
97 // sides are brighter.
98 const GLColor kSideColor = {128, 0, 0, 128};
99 const GLColor kCornerColor = {64, 0, 0, 64};
100 constexpr int kErrorMargin = 16;
101 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2 - 2, kCornerColor,
102 kErrorMargin);
103 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2 + 1, kCornerColor,
104 kErrorMargin);
105 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2 - 2, kCornerColor,
106 kErrorMargin);
107 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2 + 1, kCornerColor,
108 kErrorMargin);
109
110 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2 - 1, kSideColor, kErrorMargin);
111 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2, kSideColor, kErrorMargin);
112 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 1, kWindowHeight / 2 - 2, kSideColor, kErrorMargin);
113 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 1, kWindowHeight / 2 + 1, kSideColor, kErrorMargin);
114 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2, kWindowHeight / 2 - 2, kSideColor, kErrorMargin);
115 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2, kWindowHeight / 2 + 1, kSideColor, kErrorMargin);
116 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2 - 1, kSideColor, kErrorMargin);
117 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2, kSideColor, kErrorMargin);
118 }
119
120 // Test line rendering on a multisampled surface. GLES2 section 3.4.4.
TEST_P(MultisampleTest,Line)121 TEST_P(MultisampleTest, Line)
122 {
123 ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
124 // http://anglebug.com/42264264
125 ANGLE_SKIP_TEST_IF(IsOzone());
126
127 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
128 glUseProgram(program);
129 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
130
131 GLBuffer vertexBuffer;
132 const Vector3 vertices[2] = {{-1.0f, -0.3f, 0.0f}, {1.0f, 0.3f, 0.0f}};
133 prepareVertexBuffer(vertexBuffer, vertices, 2, positionLocation);
134
135 glClear(GL_COLOR_BUFFER_BIT);
136 glDrawArrays(GL_LINES, 0, 2);
137
138 ASSERT_GL_NO_ERROR();
139
140 // The line goes from left to right at about -17 degrees slope. It renders as such (captured
141 // with renderdoc):
142 //
143 // D D = Dark Red (0.25) or (0.5)
144 // BRA R = Red (1.0)
145 // ARB M = Middle Red (0.75)
146 // D B = Bright Red (1.0 or 0.75)
147 // A = Any red (0.5, 0.75 or 1.0)
148 //
149 // Verify that rendering is done as above.
150
151 const GLColor kDarkRed = {128, 0, 0, 128};
152 const GLColor kMidRed = {192, 0, 0, 192};
153 constexpr int kErrorMargin = 16;
154 constexpr int kLargeMargin = 80;
155
156 static_assert(kWindowWidth == 16, "Verification code written for 16x8 window");
157 EXPECT_PIXEL_COLOR_NEAR(0, 2, kDarkRed, kLargeMargin);
158 EXPECT_PIXEL_COLOR_NEAR(3, 3, GLColor::red, kLargeMargin);
159 EXPECT_PIXEL_COLOR_NEAR(4, 3, GLColor::red, kErrorMargin);
160 EXPECT_PIXEL_COLOR_NEAR(6, 3, kMidRed, kLargeMargin);
161 EXPECT_PIXEL_COLOR_NEAR(8, 4, kMidRed, kLargeMargin);
162 EXPECT_PIXEL_COLOR_NEAR(11, 4, GLColor::red, kErrorMargin);
163 EXPECT_PIXEL_COLOR_NEAR(12, 4, GLColor::red, kLargeMargin);
164 EXPECT_PIXEL_COLOR_NEAR(15, 5, kDarkRed, kLargeMargin);
165 }
166
167 // Test polygon rendering on a multisampled surface. GLES2 section 3.5.3.
TEST_P(MultisampleTest,Triangle)168 TEST_P(MultisampleTest, Triangle)
169 {
170 // http://anglebug.com/42262135
171 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
172 // http://anglebug.com/42264264
173 ANGLE_SKIP_TEST_IF(IsOzone());
174
175 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
176 glUseProgram(program);
177 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
178
179 GLBuffer vertexBuffer;
180 const Vector3 vertices[3] = {{-1.0f, -1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
181 prepareVertexBuffer(vertexBuffer, vertices, 3, positionLocation);
182
183 glClear(GL_COLOR_BUFFER_BIT);
184 glDrawArrays(GL_TRIANGLES, 0, 3);
185
186 ASSERT_GL_NO_ERROR();
187
188 // Top-left pixels should be all red.
189 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
190 EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 4, kWindowHeight / 4, GLColor::red);
191
192 // Diagonal pixels from bottom-left to top-right are between red and black. Pixels above the
193 // diagonal are red and pixels below it are black.
194 const GLColor kMidRed = {128, 0, 0, 128};
195 // D3D11 is off by 63 for red (191 instead of 128), where other back-ends get 128
196 constexpr int kErrorMargin = 64;
197
198 for (int i = 2; i + 2 < kWindowWidth; i += 2)
199 {
200 int j = kWindowHeight - 1 - (i / 2);
201 EXPECT_PIXEL_COLOR_NEAR(i, j, kMidRed, kErrorMargin);
202 EXPECT_PIXEL_COLOR_EQ(i, j - 1, GLColor::red);
203 EXPECT_PIXEL_COLOR_EQ(i, j + 1, GLColor::transparentBlack);
204 }
205 }
206
207 // Test polygon rendering on a multisampled surface. And rendering is interrupted by a compute pass
208 // that converts the index buffer. Make sure the rendering's multisample result is preserved after
209 // interruption.
TEST_P(MultisampleTest,ContentPresevedAfterInterruption)210 TEST_P(MultisampleTest, ContentPresevedAfterInterruption)
211 {
212 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_rgb8_rgba8"));
213 // http://anglebug.com/42262135
214 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
215 // http://anglebug.com/42263216
216 ANGLE_SKIP_TEST_IF(IsD3D11());
217 // http://anglebug.com/42264264
218 ANGLE_SKIP_TEST_IF(IsOzone());
219
220 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
221 glUseProgram(program);
222 const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
223
224 if (IsGLExtensionEnabled("GL_EXT_discard_framebuffer"))
225 {
226 GLenum attachments[] = {GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT};
227 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments);
228 }
229 // Draw triangle
230 GLBuffer vertexBuffer;
231 const Vector3 vertices[3] = {{-1.0f, -1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
232 prepareVertexBuffer(vertexBuffer, vertices, 3, positionLocation);
233
234 glClear(GL_COLOR_BUFFER_BIT);
235 glDrawArrays(GL_TRIANGLES, 0, 3);
236
237 ASSERT_GL_NO_ERROR();
238
239 // Draw a line
240 GLBuffer vertexBuffer2;
241 GLBuffer indexBuffer2;
242 const Vector3 vertices2[2] = {{-1.0f, -0.3f, 0.0f}, {1.0f, 0.3f, 0.0f}};
243 const GLubyte indices2[] = {0, 1};
244 prepareVertexBuffer(vertexBuffer2, vertices2, 2, positionLocation);
245 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2);
246 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
247
248 glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, 0);
249
250 ASSERT_GL_NO_ERROR();
251
252 // Top-left pixels should be all red.
253 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
254 EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 4, kWindowHeight / 4, GLColor::red);
255
256 // Triangle edge:
257 // Diagonal pixels from bottom-left to top-right are between red and black. Pixels above the
258 // diagonal are red and pixels below it are black.
259 {
260 const GLColor kMidRed = {128, 0, 0, 128};
261 constexpr int kErrorMargin = 16;
262
263 for (int i = 2; i + 2 < kWindowWidth; i += 2)
264 {
265 // Exclude the middle pixel where the triangle and line cross each other.
266 if (abs(kWindowHeight / 2 - (i / 2)) <= 1)
267 {
268 continue;
269 }
270 int j = kWindowHeight - 1 - (i / 2);
271 EXPECT_PIXEL_COLOR_NEAR(i, j, kMidRed, kErrorMargin);
272 EXPECT_PIXEL_COLOR_EQ(i, j - 1, GLColor::red);
273 EXPECT_PIXEL_COLOR_EQ(i, j + 1, GLColor::transparentBlack);
274 }
275 }
276
277 // Line edge:
278 {
279 const GLColor kDarkRed = {128, 0, 0, 128};
280 constexpr int kErrorMargin = 16;
281 constexpr int kLargeMargin = 80;
282
283 static_assert(kWindowWidth == 16, "Verification code written for 16x8 window");
284 // Exclude the triangle region.
285 EXPECT_PIXEL_COLOR_NEAR(11, 4, GLColor::red, kErrorMargin);
286 EXPECT_PIXEL_COLOR_NEAR(12, 4, GLColor::red, kLargeMargin);
287 EXPECT_PIXEL_COLOR_NEAR(15, 5, kDarkRed, kLargeMargin);
288 }
289 }
290
291 // Test that alpha to coverage is enabled works properly along with early fragment test.
TEST_P(MultisampleTest,AlphaToSampleCoverage)292 TEST_P(MultisampleTest, AlphaToSampleCoverage)
293 {
294 // http://anglebug.com/42264264
295 ANGLE_SKIP_TEST_IF(IsOzone());
296
297 constexpr char kFS[] =
298 "precision highp float;\n"
299 "void main()\n"
300 "{\n"
301 " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0);\n"
302 "}\n";
303 ANGLE_GL_PROGRAM(transparentRedProgram, essl1_shaders::vs::Simple(), kFS);
304 glUseProgram(transparentRedProgram);
305 glEnable(GL_DEPTH_TEST);
306 glDepthFunc(GL_LESS);
307 glClearDepthf(1.0f);
308 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // clear to green
309 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
310 // This should pass depth test, but because of the alpha to coverage enabled, and alpha is 0,
311 // the fragment should be discarded. If early fragment test is disabled, no depth will be
312 // written. depth buffer should be 1.0.
313 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
314 // There was a bug in ANGLE that we are checking sampler coverage enabled or not instead of
315 // alpha to sample coverage enabled or not. This is specically try to trick ANGLE so that it
316 // will enable early fragment test. When early fragment test is accidentally enabled, then the
317 // depth test will occur before fragment shader, and depth buffer maybe written with value
318 // (0.0+1.0)/2.0=0.5.
319 glEnable(GL_SAMPLE_COVERAGE);
320 drawQuad(transparentRedProgram, essl1_shaders::PositionAttrib(), 0.0f);
321
322 // Now draw with blue color but to test against 0.0f. This should fail depth test
323 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
324 glDisable(GL_SAMPLE_COVERAGE);
325 glDepthFunc(GL_GREATER);
326 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
327 // Zd = 0.5f means (0.5+1.0)/2.0=0.75. Depends on early fragment on or off this will pass or
328 // fail depth test.
329 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
330 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
331
332 ASSERT_GL_NO_ERROR();
333 }
334
335 // Test that resolve from multisample default framebuffer works.
TEST_P(MultisampleTestES3,ResolveToFBO)336 TEST_P(MultisampleTestES3, ResolveToFBO)
337 {
338 GLTexture resolveTexture;
339 glBindTexture(GL_TEXTURE_2D, resolveTexture);
340 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWindowWidth, kWindowHeight, 0, GL_RGBA,
341 GL_UNSIGNED_BYTE, nullptr);
342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
343 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
344
345 GLFramebuffer resolveFBO;
346 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
347 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
348
349 // Clear the default framebuffer
350 glBindFramebuffer(GL_FRAMEBUFFER, 0);
351 glClearColor(0.25, 0.5, 0.75, 0.25);
352 glClear(GL_COLOR_BUFFER_BIT);
353
354 // Resolve into FBO
355 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
356 glClearColor(1, 0, 0, 1);
357 glClear(GL_COLOR_BUFFER_BIT);
358 glBlitFramebuffer(0, 0, kWindowWidth, kWindowHeight, 0, 0, kWindowWidth, kWindowHeight,
359 GL_COLOR_BUFFER_BIT, GL_NEAREST);
360 ASSERT_GL_NO_ERROR();
361
362 const GLColor kResult = GLColor(63, 127, 191, 63);
363 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
364 EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
365 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth - 1, 0, kResult, 1);
366 EXPECT_PIXEL_COLOR_NEAR(0, kWindowHeight - 1, kResult, 1);
367 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth - 1, kWindowHeight - 1, kResult, 1);
368 EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2, kWindowHeight / 2, kResult, 1);
369 }
370
371 // Test that resolve from multisample default framebuffer after an open render pass works when the
372 // framebuffer is also immediately implicitly resolved due to swap afterwards.
TEST_P(MultisampleTestES3,RenderPassResolveToFBOThenSwap)373 TEST_P(MultisampleTestES3, RenderPassResolveToFBOThenSwap)
374 {
375 GLTexture resolveTexture;
376 glBindTexture(GL_TEXTURE_2D, resolveTexture);
377 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWindowWidth, kWindowHeight, 0, GL_RGBA,
378 GL_UNSIGNED_BYTE, nullptr);
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
381
382 GLFramebuffer resolveFBO;
383 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
384 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
385
386 auto runTest = [&](bool flipY) {
387 // Open a render pass by drawing to the default framebuffer
388 glBindFramebuffer(GL_FRAMEBUFFER, 0);
389 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
390 drawQuad(red, essl1_shaders::PositionAttrib(), 0.5f);
391
392 // Resolve into FBO
393 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
394 if (flipY)
395 {
396 glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
397 }
398 glBlitFramebuffer(0, 0, kWindowWidth, kWindowHeight, 0, 0, kWindowWidth, kWindowHeight,
399 GL_COLOR_BUFFER_BIT, GL_NEAREST);
400 ASSERT_GL_NO_ERROR();
401
402 // Immediately swap so that an implicit resolve to the backbuffer happens right away.
403 swapBuffers();
404
405 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
406 EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth, kWindowHeight, GLColor::red);
407 };
408
409 runTest(false);
410 if (IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"))
411 {
412 // With multiple backends, the default framebuffer is flipped w.r.t GL's coordinates. As a
413 // result, the glBlitFramebuffer may need to take a different path from a direct multisample
414 // resolve. This test ensures a direct resolve is also tested where possible.
415 runTest(true);
416 }
417 }
418
419 // Test that CopyTexImage2D from an MSAA default fbo works
TEST_P(MultisampleTestES3,CopyTexImage2DFromMsaaDefaultFbo)420 TEST_P(MultisampleTestES3, CopyTexImage2DFromMsaaDefaultFbo)
421 {
422 constexpr char kFS[] = R"(#version 300 es
423 #extension GL_OES_sample_variables : require
424 precision highp float;
425 out vec4 my_FragColor;
426
427 void main()
428 {
429 switch (uint(gl_SampleID))
430 {
431 case 0u:
432 my_FragColor = vec4(1.0, 0.9, 0.8, 0.7);
433 break;
434 case 1u:
435 my_FragColor = vec4(0.0, 0.1, 0.2, 0.3);
436 break;
437 case 2u:
438 my_FragColor = vec4(0.5, 0.25, 0.75, 1.0);
439 break;
440 case 3u:
441 my_FragColor = vec4(0.4, 0.6, 0.2, 0.8);
442 break;
443 default:
444 my_FragColor = vec4(0.0);
445 break;
446 }
447 }
448 )";
449
450 ANGLE_GL_PROGRAM(programMs, essl3_shaders::vs::Simple(), kFS);
451 glUseProgram(programMs);
452
453 // Clear the default framebuffer and draw
454 glBindFramebuffer(GL_FRAMEBUFFER, 0);
455 glClearColor(0.25, 0.5, 0.75, 0.25);
456 glClear(GL_COLOR_BUFFER_BIT);
457 drawQuad(programMs, essl3_shaders::PositionAttrib(), 0.0);
458
459 // Create a texture for copy
460 GLTexture copyTexture;
461 glBindTexture(GL_TEXTURE_2D, copyTexture);
462 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWindowWidth, kWindowHeight, 0, GL_RGBA,
463 GL_UNSIGNED_BYTE, nullptr);
464 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
465 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
466
467 constexpr int kCopyWidth = 10;
468 constexpr int kCopyHeight = 5;
469 // Copy MSAA default framebuffer into the texture
470 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kCopyWidth, kCopyHeight, 0);
471 ASSERT_GL_NO_ERROR();
472
473 GLFramebuffer readFbo;
474 glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
475 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTexture, 0);
476
477 const GLColor kResult = GLColor(121, 118, 124, 178);
478 EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
479 EXPECT_PIXEL_COLOR_NEAR(kCopyWidth - 1, 0, kResult, 1);
480 EXPECT_PIXEL_COLOR_NEAR(0, kCopyHeight - 1, kResult, 1);
481 EXPECT_PIXEL_COLOR_NEAR(kCopyWidth - 1, kCopyHeight - 1, kResult, 1);
482 EXPECT_PIXEL_COLOR_NEAR(kCopyWidth / 2, kCopyHeight / 2, kResult, 1);
483 }
484
485 class MultisampleResolveTest : public ANGLETest<>
486 {
487 protected:
488 static const GLColor kEXPECTED_R8;
489 static const GLColor kEXPECTED_RG8;
490 static const GLColor kEXPECTED_RGB8;
491 static const GLColor kEXPECTED_RGBA8;
492 static const GLColor32F kEXPECTED_RF;
493 static const GLColor32F kEXPECTED_RGF;
494 static const GLColor32F kEXPECTED_RGBF;
495 static const GLColor32F kEXPECTED_RGBAF;
496 static constexpr GLint kWidth = 13;
497 static constexpr GLint kHeight = 11;
498
MultisampleResolveTest()499 MultisampleResolveTest() {}
500
501 struct GLResources
502 {
503 GLFramebuffer fb;
504 GLRenderbuffer rb;
505 };
506
resolveToFBO(GLenum format,GLint samples,GLint width,GLint height,GLResources & resources)507 void resolveToFBO(GLenum format,
508 GLint samples,
509 GLint width,
510 GLint height,
511 GLResources &resources)
512 {
513 constexpr char kVS[] = R"(#version 300 es
514 layout(location = 0) in vec4 position;
515 void main() {
516 gl_Position = position;
517 }
518 )";
519
520 constexpr char kFS[] = R"(#version 300 es
521 precision highp float;
522 out vec4 color;
523 void main() {
524 color = vec4(0.5, 0.6, 0.7, 0.8);
525 }
526 )";
527
528 ANGLE_GL_PROGRAM(program, kVS, kFS);
529
530 // Make samples = 4 multi-sample framebuffer.
531 GLFramebuffer fb0;
532 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
533
534 GLRenderbuffer rb0;
535 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
536 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
537 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
538 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
539
540 // Make samples = 0 multi-sample framebuffer.
541 glBindFramebuffer(GL_FRAMEBUFFER, resources.fb);
542
543 glBindRenderbuffer(GL_RENDERBUFFER, resources.rb);
544 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, width, height);
545 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
546 resources.rb);
547 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
548
549 // Draw quad to fb0.
550 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
551 glViewport(0, 0, width, height);
552 glUseProgram(program);
553 GLBuffer buf;
554 glBindBuffer(GL_ARRAY_BUFFER, buf);
555
556 constexpr float vertices[] = {
557 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
558 };
559 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
560 glEnableVertexAttribArray(0);
561 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
562 glDrawArrays(GL_TRIANGLES, 0, 6);
563
564 // Blit fb0 to fb1.
565 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
566 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resources.fb);
567 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
568 GL_NEAREST);
569 ASSERT_GL_NO_ERROR();
570
571 // Prep for read pixels.
572 glBindFramebuffer(GL_READ_FRAMEBUFFER, resources.fb);
573 }
574
testResolveToUNormFBO(GLenum format,const GLColor & expected_color,GLint samples,GLint width,GLint height)575 void testResolveToUNormFBO(GLenum format,
576 const GLColor &expected_color,
577 GLint samples,
578 GLint width,
579 GLint height)
580 {
581 GLResources resources;
582 resolveToFBO(format, samples, width, height, resources);
583
584 // Check the results
585 for (GLint y = 0; y < kHeight; ++y)
586 {
587 for (GLint x = 0; x < kWidth; ++x)
588 {
589 EXPECT_PIXEL_COLOR_NEAR(x, y, expected_color, 2);
590 }
591 }
592 ASSERT_GL_NO_ERROR();
593 }
594
testResolveToHalfFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)595 void testResolveToHalfFBO(GLenum format,
596 const GLColor32F &expected_color,
597 GLint samples,
598 GLint width,
599 GLint height)
600 {
601 if (!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"))
602 {
603 return;
604 }
605
606 GLResources resources;
607 resolveToFBO(format, samples, width, height, resources);
608
609 // Check the results
610 for (GLint y = 0; y < kHeight; ++y)
611 {
612 for (GLint x = 0; x < kWidth; ++x)
613 {
614 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
615 }
616 }
617 ASSERT_GL_NO_ERROR();
618 }
619
testResolveToFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)620 void testResolveToFloatFBO(GLenum format,
621 const GLColor32F &expected_color,
622 GLint samples,
623 GLint width,
624 GLint height)
625 {
626 if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"))
627 {
628 return;
629 }
630
631 GLResources resources;
632 resolveToFBO(format, samples, width, height, resources);
633
634 // Check the results
635 for (GLint y = 0; y < kHeight; ++y)
636 {
637 for (GLint x = 0; x < kWidth; ++x)
638 {
639 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
640 }
641 }
642 ASSERT_GL_NO_ERROR();
643 }
644
testResolveToRGBFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)645 void testResolveToRGBFloatFBO(GLenum format,
646 const GLColor32F &expected_color,
647 GLint samples,
648 GLint width,
649 GLint height)
650 {
651 if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
652 {
653 return;
654 }
655
656 GLResources resources;
657 resolveToFBO(format, samples, width, height, resources);
658
659 // Check the results
660 for (GLint y = 0; y < kHeight; ++y)
661 {
662 for (GLint x = 0; x < kWidth; ++x)
663 {
664 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
665 }
666 }
667 ASSERT_GL_NO_ERROR();
668 }
669
peelDepth(GLint colorLoc)670 void peelDepth(GLint colorLoc)
671 {
672 // Draw full quads from front to back and increasing depths
673 // with depth test = less.
674 glDepthMask(GL_FALSE);
675 constexpr int steps = 64;
676 for (int i = 0; i < steps; ++i)
677 {
678 float l = float(i) / float(steps);
679 float c = l;
680 float z = c * 2.0f - 1.0f;
681 glVertexAttrib4f(1, 0, 0, z, 0);
682 glUniform4f(colorLoc, c, c, c, c);
683 glDrawArrays(GL_TRIANGLES, 0, 6);
684 }
685 glDepthMask(GL_TRUE);
686 }
687
testResolveDepthToFBO(GLenum format,GLenum attachment,GLint samples,GLint width,GLint height)688 void testResolveDepthToFBO(GLenum format,
689 GLenum attachment,
690 GLint samples,
691 GLint width,
692 GLint height)
693 {
694 constexpr char kVS[] = R"(#version 300 es
695 layout(location = 0) in vec4 position;
696 void main() {
697 gl_Position = position;
698 }
699 )";
700
701 constexpr char kFS[] = R"(#version 300 es
702 precision highp float;
703 out vec4 color;
704 void main() {
705 color = vec4(0.5, 0.6, 0.7, 0.8);
706 }
707 )";
708
709 constexpr char kDepthVS[] = R"(#version 300 es
710 layout(location = 0) in vec4 position;
711 layout(location = 1) in vec4 offset;
712 void main() {
713 gl_Position = position + offset;
714 }
715 )";
716
717 constexpr char kDepthFS[] = R"(#version 300 es
718 precision highp float;
719 uniform vec4 color;
720 out vec4 outColor;
721 void main() {
722 outColor = color;
723 }
724 )";
725
726 ANGLE_GL_PROGRAM(program, kVS, kFS);
727 ANGLE_GL_PROGRAM(depthProgram, kDepthVS, kDepthFS);
728
729 // Make samples = 4 multi-sample framebuffer.
730 GLFramebuffer fb0;
731 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
732
733 GLRenderbuffer rb0;
734 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
735 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
736 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
737
738 GLRenderbuffer db0;
739 glBindRenderbuffer(GL_RENDERBUFFER, db0);
740 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
741 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db0);
742
743 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
744
745 // Make samples = 0 multi-sample framebuffer.
746 GLFramebuffer fb1;
747 glBindFramebuffer(GL_FRAMEBUFFER, fb1);
748
749 GLRenderbuffer rb1;
750 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
751 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
752 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb1);
753 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
754
755 GLRenderbuffer db1;
756 glBindRenderbuffer(GL_RENDERBUFFER, db1);
757 glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
758 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db1);
759
760 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
761
762 // Draw quad to fb0.
763 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
764 glViewport(0, 0, width, height);
765 glClearColor(1, 1, 1, 1);
766 glUseProgram(program);
767
768 GLVertexArray va0;
769 glBindVertexArray(va0);
770
771 GLBuffer buf0;
772 glBindBuffer(GL_ARRAY_BUFFER, buf0);
773
774 // clang-format off
775 constexpr float vertices[] = {
776 -1.0f, -1.0f, -1.0,
777 1.0f, -1.0f, 0.0,
778 -1.0f, 1.0f, 0.0,
779 -1.0f, 1.0f, 0.0,
780 1.0f, -1.0f, 0.0,
781 1.0f, 1.0f, 1.0,
782 };
783 // clang-format on
784
785 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
786 glEnableVertexAttribArray(0);
787 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
788 glEnable(GL_DEPTH_TEST);
789 glDepthFunc(GL_ALWAYS);
790 glDrawArrays(GL_TRIANGLES, 0, 6);
791
792 // Blit fb0 to fb1.
793 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
794 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb1);
795 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT,
796 GL_NEAREST);
797 ASSERT_GL_NO_ERROR();
798
799 GLVertexArray va1;
800 glBindVertexArray(va1);
801
802 // clang-format off
803 constexpr float depthVertices[] = {
804 -1.0f, -1.0f,
805 1.0f, -1.0f,
806 -1.0f, 1.0f,
807 -1.0f, 1.0f,
808 1.0f, -1.0f,
809 1.0f, 1.0f,
810 };
811 // clang-format on
812
813 GLBuffer buf1;
814 glBindBuffer(GL_ARRAY_BUFFER, buf1);
815 glBufferData(GL_ARRAY_BUFFER, sizeof(depthVertices), depthVertices, GL_STATIC_DRAW);
816 glEnableVertexAttribArray(0);
817 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
818
819 glUseProgram(depthProgram);
820 GLint colorLoc = glGetUniformLocation(depthProgram, "color");
821
822 // Extract the depth results.
823 glBindFramebuffer(GL_FRAMEBUFFER, fb1);
824 glClear(GL_COLOR_BUFFER_BIT);
825 glDepthFunc(GL_LESS);
826 peelDepth(colorLoc);
827 std::vector<GLColor> actual(width * height);
828 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
829
830 // Render what should be a similar result to the non-multi-sampled fb
831 glBindVertexArray(va0);
832 glDepthFunc(GL_ALWAYS);
833 glUseProgram(program);
834 glDrawArrays(GL_TRIANGLES, 0, 6);
835
836 // Extract the expected depth results.
837 glBindVertexArray(va1);
838 glUseProgram(depthProgram);
839 glClear(GL_COLOR_BUFFER_BIT);
840 glDepthFunc(GL_LESS);
841 peelDepth(colorLoc);
842 std::vector<GLColor> expected(width * height);
843 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
844
845 for (size_t i = 0; i < expected.size(); ++i)
846 {
847 EXPECT_NEAR(expected[i].R, actual[i].R, 8)
848 << "at " << (i % width) << "," << (i / width);
849 }
850
851 // Verify we read the depth buffer.
852 const GLint minDimension = std::min(width, height);
853 for (GLint i = 1; i < minDimension; ++i)
854 {
855 const GLColor &c1 = expected[i - 1];
856 const GLColor &c2 = expected[i * width + i];
857 EXPECT_LT(c1.R, c2.R);
858 }
859 ASSERT_GL_NO_ERROR();
860 }
861 };
862
863 // Test the multisampled optimized resolve subpass
TEST_P(MultisampleResolveTest,DISABLED_ResolveSubpassMSImage)864 TEST_P(MultisampleResolveTest, DISABLED_ResolveSubpassMSImage)
865 {
866 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
867
868 // Draw green.
869 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
870 swapBuffers();
871
872 // Wait for visual verification.
873 angle::Sleep(2000);
874 }
875
876 // This is a test that must be verified visually.
877 //
878 // Tests that clear of the default framebuffer with multisample applies to the window.
TEST_P(MultisampleTestES3,DISABLED_ClearMSAAReachesWindow)879 TEST_P(MultisampleTestES3, DISABLED_ClearMSAAReachesWindow)
880 {
881 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
882
883 // Draw blue.
884 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
885 swapBuffers();
886
887 // Use glClear to clear to red. Regression test for the Vulkan backend where this clear
888 // remained "deferred" and didn't make it to the window on swap.
889 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
890 glClear(GL_COLOR_BUFFER_BIT);
891 swapBuffers();
892
893 // Wait for visual verification.
894 angle::Sleep(2000);
895 }
896
897 // According to the spec, the minimum value for the multisample line width range limits is one.
TEST_P(MultisampleTestES32,MultisampleLineWidthRangeCheck)898 TEST_P(MultisampleTestES32, MultisampleLineWidthRangeCheck)
899 {
900 GLfloat range[2] = {0, 0};
901 glGetFloatv(GL_MULTISAMPLE_LINE_WIDTH_RANGE, range);
902 EXPECT_GL_NO_ERROR();
903 EXPECT_GE(range[0], 1.0f);
904 EXPECT_GE(range[1], 1.0f);
905 }
906
907 // The multisample line width granularity should not be negative.
TEST_P(MultisampleTestES32,MultisampleLineWidthGranularityCheck)908 TEST_P(MultisampleTestES32, MultisampleLineWidthGranularityCheck)
909 {
910 GLfloat granularity = -1.0f;
911 glGetFloatv(GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY, &granularity);
912 EXPECT_GL_NO_ERROR();
913 EXPECT_GE(granularity, 0.0f);
914 }
915
916 // These colors match the shader in resolveToFBO which returns (0.5, 0.6, 0.7, 0.8).
917 const GLColor MultisampleResolveTest::kEXPECTED_R8(128, 0, 0, 255);
918 const GLColor MultisampleResolveTest::kEXPECTED_RG8(128, 153, 0, 255);
919 const GLColor MultisampleResolveTest::kEXPECTED_RGB8(128, 153, 178, 255);
920 const GLColor MultisampleResolveTest::kEXPECTED_RGBA8(128, 153, 178, 204);
921 const GLColor32F MultisampleResolveTest::kEXPECTED_RF(0.5f, 0.0f, 0.0f, 1.0f);
922 const GLColor32F MultisampleResolveTest::kEXPECTED_RGF(0.5f, 0.6f, 0.0f, 1.0f);
923 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBF(0.5f, 0.6f, 0.7f, 1.0f);
924 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBAF(0.5f, 0.6f, 0.7f, 0.8f);
925
926 // Test we can render to and resolve an RGBA8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA8ToFBO4Samples)927 TEST_P(MultisampleResolveTest, ResolveRGBA8ToFBO4Samples)
928 {
929 testResolveToUNormFBO(GL_RGBA8, kEXPECTED_RGBA8, 4, kWidth, kHeight);
930 }
931
932 // Test we can render to and resolve an RGB8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB8ToFBO4Samples)933 TEST_P(MultisampleResolveTest, ResolveRGB8ToFBO4Samples)
934 {
935 testResolveToUNormFBO(GL_RGB8, kEXPECTED_RGB8, 4, kWidth, kHeight);
936 }
937
938 // Test we can render to and resolve an RG8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG8ToFBO4Samples)939 TEST_P(MultisampleResolveTest, ResolveRG8ToFBO4Samples)
940 {
941 testResolveToUNormFBO(GL_RG8, kEXPECTED_RG8, 4, kWidth, kHeight);
942 }
943
944 // Test we can render to and resolve an R8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveR8ToFBO4Samples)945 TEST_P(MultisampleResolveTest, ResolveR8ToFBO4Samples)
946 {
947 testResolveToUNormFBO(GL_R8, kEXPECTED_R8, 4, kWidth, kHeight);
948 }
949
950 // Test we can render to and resolve an R16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR16FToFBO4Samples)951 TEST_P(MultisampleResolveTest, ResolveR16FToFBO4Samples)
952 {
953 testResolveToHalfFBO(GL_R16F, kEXPECTED_RF, 4, kWidth, kHeight);
954 }
955
956 // Test we can render to and resolve an RG16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG16FToFBO4Samples)957 TEST_P(MultisampleResolveTest, ResolveRG16FToFBO4Samples)
958 {
959 testResolveToHalfFBO(GL_RG16F, kEXPECTED_RGF, 4, kWidth, kHeight);
960 }
961
962 // Test we can render to and resolve an RGB16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB16FToFBO4Samples)963 TEST_P(MultisampleResolveTest, ResolveRGB16FToFBO4Samples)
964 {
965 testResolveToHalfFBO(GL_RGB16F, kEXPECTED_RGBF, 4, kWidth, kHeight);
966 }
967
968 // Test we can render to and resolve an RGBA16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA16FToFBO4Samples)969 TEST_P(MultisampleResolveTest, ResolveRGBA16FToFBO4Samples)
970 {
971 testResolveToHalfFBO(GL_RGBA16F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
972 }
973
974 // Test we can render to and resolve an R32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR32FToFBO4Samples)975 TEST_P(MultisampleResolveTest, ResolveR32FToFBO4Samples)
976 {
977 testResolveToFloatFBO(GL_R32F, kEXPECTED_RF, 4, kWidth, kHeight);
978 }
979
980 // Test we can render to and resolve an RG32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG32FToFBO4Samples)981 TEST_P(MultisampleResolveTest, ResolveRG32FToFBO4Samples)
982 {
983 testResolveToFloatFBO(GL_RG32F, kEXPECTED_RGF, 4, kWidth, kHeight);
984 }
985
986 // Test we can render to and resolve an RGB32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB32FToFBO4Samples)987 TEST_P(MultisampleResolveTest, ResolveRGB32FToFBO4Samples)
988 {
989 testResolveToRGBFloatFBO(GL_RGB32F, kEXPECTED_RGBF, 4, kWidth, kHeight);
990 }
991
992 // Test we can render to and resolve an RGBA32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA32FToFBO4Samples)993 TEST_P(MultisampleResolveTest, ResolveRGBA32FToFBO4Samples)
994 {
995 testResolveToFloatFBO(GL_RGBA32F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
996 }
997
TEST_P(MultisampleResolveTest,ResolveD32FS8F4Samples)998 TEST_P(MultisampleResolveTest, ResolveD32FS8F4Samples)
999 {
1000 testResolveDepthToFBO(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
1001 }
1002
TEST_P(MultisampleResolveTest,ResolveD24S8Samples)1003 TEST_P(MultisampleResolveTest, ResolveD24S8Samples)
1004 {
1005 testResolveDepthToFBO(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
1006 }
1007
TEST_P(MultisampleResolveTest,ResolveD32FSamples)1008 TEST_P(MultisampleResolveTest, ResolveD32FSamples)
1009 {
1010 testResolveDepthToFBO(GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
1011 }
1012
TEST_P(MultisampleResolveTest,ResolveD24Samples)1013 TEST_P(MultisampleResolveTest, ResolveD24Samples)
1014 {
1015 testResolveDepthToFBO(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
1016 }
1017
TEST_P(MultisampleResolveTest,ResolveD16Samples)1018 TEST_P(MultisampleResolveTest, ResolveD16Samples)
1019 {
1020 testResolveDepthToFBO(GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
1021 }
1022
drawRectAndBlit(GLuint msFramebuffer,GLuint resolveFramebuffer,GLint width,GLint height,GLint matLoc,GLint colorLoc,float x,float y,float w,float h,const GLColor & color)1023 void drawRectAndBlit(GLuint msFramebuffer,
1024 GLuint resolveFramebuffer,
1025 GLint width,
1026 GLint height,
1027 GLint matLoc,
1028 GLint colorLoc,
1029 float x,
1030 float y,
1031 float w,
1032 float h,
1033 const GLColor &color)
1034 {
1035 glBindFramebuffer(GL_FRAMEBUFFER, msFramebuffer);
1036 float matrix[16] = {
1037 w, 0, 0, 0, 0, h, 0, 0, 0, 0, 1, 0, x, y, 0, 1,
1038 };
1039 glUniformMatrix4fv(matLoc, 1, false, matrix);
1040 angle::Vector4 c(color.toNormalizedVector());
1041 glUniform4f(colorLoc, c[0], c[1], c[2], c[3]);
1042 glDrawArrays(GL_TRIANGLES, 0, 6);
1043
1044 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
1045 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1046 }
1047
1048 // Tests if we resolve(blit) a multisample renderbuffer that it
1049 // does not lose its contents.
TEST_P(MultisampleResolveTest,DrawAndResolveMultipleTimes)1050 TEST_P(MultisampleResolveTest, DrawAndResolveMultipleTimes)
1051 {
1052 constexpr GLint samples = 4;
1053 constexpr GLenum format = GL_RGBA8;
1054 constexpr GLint width = 16;
1055 constexpr GLint height = 16;
1056
1057 constexpr char kVS[] = R"(#version 300 es
1058 layout(location = 0) in vec4 position;
1059 uniform mat4 mat;
1060 void main() {
1061 gl_Position = mat * position;
1062 }
1063 )";
1064
1065 constexpr char kFS[] = R"(#version 300 es
1066 precision highp float;
1067 uniform vec4 color;
1068 out vec4 outColor;
1069 void main() {
1070 outColor = color;
1071 }
1072 )";
1073
1074 glViewport(0, 0, width, height);
1075
1076 ANGLE_GL_PROGRAM(program, kVS, kFS);
1077 GLint matLoc = glGetUniformLocation(program, "mat");
1078 GLint colorLoc = glGetUniformLocation(program, "color");
1079 glUseProgram(program);
1080
1081 GLBuffer buf;
1082 glBindBuffer(GL_ARRAY_BUFFER, buf);
1083
1084 constexpr float vertices[] = {
1085 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1086 };
1087 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
1088 glEnableVertexAttribArray(0);
1089 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1090
1091 // Make samples = 4 multi-sample framebuffer.
1092 GLFramebuffer msFB;
1093 glBindFramebuffer(GL_FRAMEBUFFER, msFB);
1094
1095 GLRenderbuffer msRB;
1096 glBindRenderbuffer(GL_RENDERBUFFER, msRB);
1097 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
1098 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msRB);
1099 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1100
1101 // Make non-multi-sample framebuffer.
1102 GLFramebuffer drawFB;
1103 glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1104
1105 GLRenderbuffer drawRB;
1106 glBindRenderbuffer(GL_RENDERBUFFER, drawRB);
1107 glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
1108 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, drawRB);
1109 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1110
1111 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, -1, 2, 2, GLColor::red);
1112 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, -1, 1, 1, GLColor::green);
1113 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, 0, 1, 1, GLColor::blue);
1114 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, 0, 1, 1, GLColor::yellow);
1115 glEnable(GL_BLEND);
1116 glBlendFunc(GL_ONE, GL_ONE);
1117 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -0.5, -0.5, 1, 1,
1118 GLColor(0x80, 0x80, 0x80, 0x80));
1119 glDisable(GL_BLEND);
1120 ASSERT_GL_NO_ERROR();
1121
1122 /*
1123 expected
1124 +-------------+--------------+
1125 | blue | yellow |
1126 | +---------+----------+ |
1127 | |.5,.5,1,1| 1,1,.5,1 | |
1128 +---+---------+----------+---+
1129 | |1,.5,.5,1| .5,1,.5,1| |
1130 | +---------+----------+ |
1131 | red | green |
1132 +-------------+--------------+
1133 0,0
1134 */
1135
1136 glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1137 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 4, GLColor::red);
1138 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2, height / 4, GLColor::green);
1139 EXPECT_PIXEL_RECT_EQ(0, height * 3 / 4, width / 2, height / 4, GLColor::blue);
1140 EXPECT_PIXEL_RECT_EQ(width / 2, height * 3 / 4, width / 2, height / 4, GLColor::yellow);
1141
1142 EXPECT_PIXEL_RECT_EQ(width / 4, height / 4, width / 4, height / 4, GLColor(255, 128, 128, 255));
1143 EXPECT_PIXEL_RECT_EQ(width / 2, height / 4, width / 4, height / 4, GLColor(128, 255, 128, 255));
1144 EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 4, height / 4, GLColor(128, 128, 255, 255));
1145 EXPECT_PIXEL_RECT_EQ(width / 2, height / 2, width / 4, height / 4, GLColor(255, 255, 128, 255));
1146 }
1147
1148 // Tests resolve after the read framebuffer's attachment has been swapped out.
TEST_P(MultisampleResolveTest,SwitchAttachmentsBeforeResolve)1149 TEST_P(MultisampleResolveTest, SwitchAttachmentsBeforeResolve)
1150 {
1151 constexpr GLuint kWidth = 16;
1152 constexpr GLuint kHeight = 24;
1153
1154 GLRenderbuffer msaaColor0, msaaColor1;
1155 glBindRenderbuffer(GL_RENDERBUFFER, msaaColor0);
1156 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, kWidth, kHeight);
1157 glBindRenderbuffer(GL_RENDERBUFFER, msaaColor1);
1158 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, kWidth, kHeight);
1159
1160 {
1161 // First, make one of the MSAA color buffers green.
1162 GLFramebuffer clearFbo;
1163 glBindFramebuffer(GL_FRAMEBUFFER, clearFbo);
1164 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1165 msaaColor1);
1166 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1167
1168 glClearColor(0, 1, 0, 1);
1169 glClear(GL_COLOR_BUFFER_BIT);
1170
1171 // Make sure clear is performed.
1172 GLTexture resolveTexture;
1173 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1174 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1175 nullptr);
1176
1177 GLFramebuffer verifyFBO;
1178 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, verifyFBO);
1179 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1180 resolveTexture, 0);
1181
1182 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1183 GL_NEAREST);
1184
1185 glBindFramebuffer(GL_READ_FRAMEBUFFER, verifyFBO);
1186 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1187 }
1188
1189 // Set up the msaa framebuffer with the other MSAA color buffer.
1190 GLFramebuffer msaaFBO;
1191 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1192 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColor0);
1193 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1194
1195 // Draw into it to start a render pass
1196 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1197 drawQuad(red, essl1_shaders::PositionAttrib(), 0.5f);
1198
1199 // Set up the resolve framebuffer
1200 GLRenderbuffer resolveColor;
1201 glBindRenderbuffer(GL_RENDERBUFFER, resolveColor);
1202 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
1203
1204 GLFramebuffer resolveFBO;
1205 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1206 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1207 resolveColor);
1208 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1209
1210 // Before resolve the MSAA framebuffer, switch its attachment. Regression test for a bug where
1211 // the resolve used the previous attachment.
1212 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1213 msaaColor1);
1214
1215 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1216 GL_NEAREST);
1217
1218 // Verify that the resolve happened on the pre-cleared attachment, not the rendered one.
1219 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1220 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1221 }
1222
1223 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND(
1224 MultisampleTest,
1225 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1226 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1227 ES3_VULKAN().enable(Feature::EmulatedPrerotation270),
1228 // Simulate missing msaa auto resolve feature in Metal.
1229 ES2_METAL().disable(Feature::AllowMultisampleStoreAndResolve));
1230
1231 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES3);
1232 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(MultisampleTestES3,
1233 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1234 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1235 ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
1236
1237 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES32);
1238 ANGLE_INSTANTIATE_TEST_ES32_AND(MultisampleTestES32,
1239 ES32_VULKAN().enable(Feature::EmulatedPrerotation90),
1240 ES32_VULKAN().enable(Feature::EmulatedPrerotation180),
1241 ES32_VULKAN().enable(Feature::EmulatedPrerotation270));
1242
1243 ANGLE_INSTANTIATE_TEST_ES3_AND(
1244 MultisampleResolveTest,
1245 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1246 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1247 ES3_VULKAN().enable(Feature::EmulatedPrerotation270),
1248 ES3_VULKAN().enable(Feature::PreferDrawClearOverVkCmdClearAttachments));
1249
1250 } // anonymous namespace
1251