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/3470
64 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
65 // http://anglebug.com/5727
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/5727
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/3470
171 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
172 // http://anglebug.com/5727
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/3470
214 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
215 // http://anglebug.com/4609
216 ANGLE_SKIP_TEST_IF(IsD3D11());
217 // http://anglebug.com/5727
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/5727
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 class MultisampleResolveTest : public ANGLETest<>
420 {
421 protected:
422 static const GLColor kEXPECTED_R8;
423 static const GLColor kEXPECTED_RG8;
424 static const GLColor kEXPECTED_RGB8;
425 static const GLColor kEXPECTED_RGBA8;
426 static const GLColor32F kEXPECTED_RF;
427 static const GLColor32F kEXPECTED_RGF;
428 static const GLColor32F kEXPECTED_RGBF;
429 static const GLColor32F kEXPECTED_RGBAF;
430 static constexpr GLint kWidth = 13;
431 static constexpr GLint kHeight = 11;
432
MultisampleResolveTest()433 MultisampleResolveTest() {}
434
435 struct GLResources
436 {
437 GLFramebuffer fb;
438 GLRenderbuffer rb;
439 };
440
resolveToFBO(GLenum format,GLint samples,GLint width,GLint height,GLResources & resources)441 void resolveToFBO(GLenum format,
442 GLint samples,
443 GLint width,
444 GLint height,
445 GLResources &resources)
446 {
447 constexpr char kVS[] = R"(#version 300 es
448 layout(location = 0) in vec4 position;
449 void main() {
450 gl_Position = position;
451 }
452 )";
453
454 constexpr char kFS[] = R"(#version 300 es
455 precision highp float;
456 out vec4 color;
457 void main() {
458 color = vec4(0.5, 0.6, 0.7, 0.8);
459 }
460 )";
461
462 ANGLE_GL_PROGRAM(program, kVS, kFS);
463
464 // Make samples = 4 multi-sample framebuffer.
465 GLFramebuffer fb0;
466 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
467
468 GLRenderbuffer rb0;
469 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
470 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
471 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
472 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
473
474 // Make samples = 0 multi-sample framebuffer.
475 glBindFramebuffer(GL_FRAMEBUFFER, resources.fb);
476
477 glBindRenderbuffer(GL_RENDERBUFFER, resources.rb);
478 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, width, height);
479 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
480 resources.rb);
481 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
482
483 // Draw quad to fb0.
484 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
485 glViewport(0, 0, width, height);
486 glUseProgram(program);
487 GLBuffer buf;
488 glBindBuffer(GL_ARRAY_BUFFER, buf);
489
490 constexpr float vertices[] = {
491 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
492 };
493 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
494 glEnableVertexAttribArray(0);
495 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
496 glDrawArrays(GL_TRIANGLES, 0, 6);
497
498 // Blit fb0 to fb1.
499 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
500 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resources.fb);
501 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
502 GL_NEAREST);
503 ASSERT_GL_NO_ERROR();
504
505 // Prep for read pixels.
506 glBindFramebuffer(GL_READ_FRAMEBUFFER, resources.fb);
507 }
508
testResolveToUNormFBO(GLenum format,const GLColor & expected_color,GLint samples,GLint width,GLint height)509 void testResolveToUNormFBO(GLenum format,
510 const GLColor &expected_color,
511 GLint samples,
512 GLint width,
513 GLint height)
514 {
515 GLResources resources;
516 resolveToFBO(format, samples, width, height, resources);
517
518 // Check the results
519 for (GLint y = 0; y < kHeight; ++y)
520 {
521 for (GLint x = 0; x < kWidth; ++x)
522 {
523 EXPECT_PIXEL_COLOR_NEAR(x, y, expected_color, 2);
524 }
525 }
526 ASSERT_GL_NO_ERROR();
527 }
528
testResolveToHalfFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)529 void testResolveToHalfFBO(GLenum format,
530 const GLColor32F &expected_color,
531 GLint samples,
532 GLint width,
533 GLint height)
534 {
535 if (!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"))
536 {
537 return;
538 }
539
540 GLResources resources;
541 resolveToFBO(format, samples, width, height, resources);
542
543 // Check the results
544 for (GLint y = 0; y < kHeight; ++y)
545 {
546 for (GLint x = 0; x < kWidth; ++x)
547 {
548 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
549 }
550 }
551 ASSERT_GL_NO_ERROR();
552 }
553
testResolveToFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)554 void testResolveToFloatFBO(GLenum format,
555 const GLColor32F &expected_color,
556 GLint samples,
557 GLint width,
558 GLint height)
559 {
560 if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"))
561 {
562 return;
563 }
564
565 GLResources resources;
566 resolveToFBO(format, samples, width, height, resources);
567
568 // Check the results
569 for (GLint y = 0; y < kHeight; ++y)
570 {
571 for (GLint x = 0; x < kWidth; ++x)
572 {
573 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
574 }
575 }
576 ASSERT_GL_NO_ERROR();
577 }
578
testResolveToRGBFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)579 void testResolveToRGBFloatFBO(GLenum format,
580 const GLColor32F &expected_color,
581 GLint samples,
582 GLint width,
583 GLint height)
584 {
585 if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
586 {
587 return;
588 }
589
590 GLResources resources;
591 resolveToFBO(format, samples, width, height, resources);
592
593 // Check the results
594 for (GLint y = 0; y < kHeight; ++y)
595 {
596 for (GLint x = 0; x < kWidth; ++x)
597 {
598 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
599 }
600 }
601 ASSERT_GL_NO_ERROR();
602 }
603
peelDepth(GLint colorLoc)604 void peelDepth(GLint colorLoc)
605 {
606 // Draw full quads from front to back and increasing depths
607 // with depth test = less.
608 glDepthMask(GL_FALSE);
609 constexpr int steps = 64;
610 for (int i = 0; i < steps; ++i)
611 {
612 float l = float(i) / float(steps);
613 float c = l;
614 float z = c * 2.0f - 1.0f;
615 glVertexAttrib4f(1, 0, 0, z, 0);
616 glUniform4f(colorLoc, c, c, c, c);
617 glDrawArrays(GL_TRIANGLES, 0, 6);
618 }
619 glDepthMask(GL_TRUE);
620 }
621
testResolveDepthToFBO(GLenum format,GLenum attachment,GLint samples,GLint width,GLint height)622 void testResolveDepthToFBO(GLenum format,
623 GLenum attachment,
624 GLint samples,
625 GLint width,
626 GLint height)
627 {
628 constexpr char kVS[] = R"(#version 300 es
629 layout(location = 0) in vec4 position;
630 void main() {
631 gl_Position = position;
632 }
633 )";
634
635 constexpr char kFS[] = R"(#version 300 es
636 precision highp float;
637 out vec4 color;
638 void main() {
639 color = vec4(0.5, 0.6, 0.7, 0.8);
640 }
641 )";
642
643 constexpr char kDepthVS[] = R"(#version 300 es
644 layout(location = 0) in vec4 position;
645 layout(location = 1) in vec4 offset;
646 void main() {
647 gl_Position = position + offset;
648 }
649 )";
650
651 constexpr char kDepthFS[] = R"(#version 300 es
652 precision highp float;
653 uniform vec4 color;
654 out vec4 outColor;
655 void main() {
656 outColor = color;
657 }
658 )";
659
660 ANGLE_GL_PROGRAM(program, kVS, kFS);
661 ANGLE_GL_PROGRAM(depthProgram, kDepthVS, kDepthFS);
662
663 // Make samples = 4 multi-sample framebuffer.
664 GLFramebuffer fb0;
665 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
666
667 GLRenderbuffer rb0;
668 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
669 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
670 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
671
672 GLRenderbuffer db0;
673 glBindRenderbuffer(GL_RENDERBUFFER, db0);
674 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
675 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db0);
676
677 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
678
679 // Make samples = 0 multi-sample framebuffer.
680 GLFramebuffer fb1;
681 glBindFramebuffer(GL_FRAMEBUFFER, fb1);
682
683 GLRenderbuffer rb1;
684 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
685 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
686 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb1);
687 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
688
689 GLRenderbuffer db1;
690 glBindRenderbuffer(GL_RENDERBUFFER, db1);
691 glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
692 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db1);
693
694 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
695
696 // Draw quad to fb0.
697 glBindFramebuffer(GL_FRAMEBUFFER, fb0);
698 glViewport(0, 0, width, height);
699 glClearColor(1, 1, 1, 1);
700 glUseProgram(program);
701
702 GLVertexArray va0;
703 glBindVertexArray(va0);
704
705 GLBuffer buf0;
706 glBindBuffer(GL_ARRAY_BUFFER, buf0);
707
708 // clang-format off
709 constexpr float vertices[] = {
710 -1.0f, -1.0f, -1.0,
711 1.0f, -1.0f, 0.0,
712 -1.0f, 1.0f, 0.0,
713 -1.0f, 1.0f, 0.0,
714 1.0f, -1.0f, 0.0,
715 1.0f, 1.0f, 1.0,
716 };
717 // clang-format on
718
719 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
720 glEnableVertexAttribArray(0);
721 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
722 glEnable(GL_DEPTH_TEST);
723 glDepthFunc(GL_ALWAYS);
724 glDrawArrays(GL_TRIANGLES, 0, 6);
725
726 // Blit fb0 to fb1.
727 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
728 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb1);
729 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT,
730 GL_NEAREST);
731 ASSERT_GL_NO_ERROR();
732
733 GLVertexArray va1;
734 glBindVertexArray(va1);
735
736 // clang-format off
737 constexpr float depthVertices[] = {
738 -1.0f, -1.0f,
739 1.0f, -1.0f,
740 -1.0f, 1.0f,
741 -1.0f, 1.0f,
742 1.0f, -1.0f,
743 1.0f, 1.0f,
744 };
745 // clang-format on
746
747 GLBuffer buf1;
748 glBindBuffer(GL_ARRAY_BUFFER, buf1);
749 glBufferData(GL_ARRAY_BUFFER, sizeof(depthVertices), depthVertices, GL_STATIC_DRAW);
750 glEnableVertexAttribArray(0);
751 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
752
753 glUseProgram(depthProgram);
754 GLint colorLoc = glGetUniformLocation(depthProgram, "color");
755
756 // Extract the depth results.
757 glBindFramebuffer(GL_FRAMEBUFFER, fb1);
758 glClear(GL_COLOR_BUFFER_BIT);
759 glDepthFunc(GL_LESS);
760 peelDepth(colorLoc);
761 std::vector<GLColor> actual(width * height);
762 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
763
764 // Render what should be a similar result to the non-multi-sampled fb
765 glBindVertexArray(va0);
766 glDepthFunc(GL_ALWAYS);
767 glUseProgram(program);
768 glDrawArrays(GL_TRIANGLES, 0, 6);
769
770 // Extract the expected depth results.
771 glBindVertexArray(va1);
772 glUseProgram(depthProgram);
773 glClear(GL_COLOR_BUFFER_BIT);
774 glDepthFunc(GL_LESS);
775 peelDepth(colorLoc);
776 std::vector<GLColor> expected(width * height);
777 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
778
779 for (size_t i = 0; i < expected.size(); ++i)
780 {
781 EXPECT_NEAR(expected[i].R, actual[i].R, 8)
782 << "at " << (i % width) << "," << (i / width);
783 }
784
785 // Verify we read the depth buffer.
786 const GLint minDimension = std::min(width, height);
787 for (GLint i = 1; i < minDimension; ++i)
788 {
789 const GLColor &c1 = expected[i - 1];
790 const GLColor &c2 = expected[i * width + i];
791 EXPECT_LT(c1.R, c2.R);
792 }
793 ASSERT_GL_NO_ERROR();
794 }
795 };
796
797 // Test the multisampled optimized resolve subpass
TEST_P(MultisampleResolveTest,DISABLED_ResolveSubpassMSImage)798 TEST_P(MultisampleResolveTest, DISABLED_ResolveSubpassMSImage)
799 {
800 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
801
802 // Draw green.
803 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
804 swapBuffers();
805
806 // Wait for visual verification.
807 angle::Sleep(2000);
808 }
809
810 // This is a test that must be verified visually.
811 //
812 // Tests that clear of the default framebuffer with multisample applies to the window.
TEST_P(MultisampleTestES3,DISABLED_ClearMSAAReachesWindow)813 TEST_P(MultisampleTestES3, DISABLED_ClearMSAAReachesWindow)
814 {
815 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
816
817 // Draw blue.
818 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
819 swapBuffers();
820
821 // Use glClear to clear to red. Regression test for the Vulkan backend where this clear
822 // remained "deferred" and didn't make it to the window on swap.
823 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
824 glClear(GL_COLOR_BUFFER_BIT);
825 swapBuffers();
826
827 // Wait for visual verification.
828 angle::Sleep(2000);
829 }
830
831 // According to the spec, the minimum value for the multisample line width range limits is one.
TEST_P(MultisampleTestES32,MultisampleLineWidthRangeCheck)832 TEST_P(MultisampleTestES32, MultisampleLineWidthRangeCheck)
833 {
834 GLfloat range[2] = {0, 0};
835 glGetFloatv(GL_MULTISAMPLE_LINE_WIDTH_RANGE, range);
836 EXPECT_GL_NO_ERROR();
837 EXPECT_GE(range[0], 1.0f);
838 EXPECT_GE(range[1], 1.0f);
839 }
840
841 // The multisample line width granularity should not be negative.
TEST_P(MultisampleTestES32,MultisampleLineWidthGranularityCheck)842 TEST_P(MultisampleTestES32, MultisampleLineWidthGranularityCheck)
843 {
844 GLfloat granularity = -1.0f;
845 glGetFloatv(GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY, &granularity);
846 EXPECT_GL_NO_ERROR();
847 EXPECT_GE(granularity, 0.0f);
848 }
849
850 // These colors match the shader in resolveToFBO which returns (0.5, 0.6, 0.7, 0.8).
851 const GLColor MultisampleResolveTest::kEXPECTED_R8(128, 0, 0, 255);
852 const GLColor MultisampleResolveTest::kEXPECTED_RG8(128, 153, 0, 255);
853 const GLColor MultisampleResolveTest::kEXPECTED_RGB8(128, 153, 178, 255);
854 const GLColor MultisampleResolveTest::kEXPECTED_RGBA8(128, 153, 178, 204);
855 const GLColor32F MultisampleResolveTest::kEXPECTED_RF(0.5f, 0.0f, 0.0f, 1.0f);
856 const GLColor32F MultisampleResolveTest::kEXPECTED_RGF(0.5f, 0.6f, 0.0f, 1.0f);
857 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBF(0.5f, 0.6f, 0.7f, 1.0f);
858 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBAF(0.5f, 0.6f, 0.7f, 0.8f);
859
860 // Test we can render to and resolve an RGBA8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA8ToFBO4Samples)861 TEST_P(MultisampleResolveTest, ResolveRGBA8ToFBO4Samples)
862 {
863 testResolveToUNormFBO(GL_RGBA8, kEXPECTED_RGBA8, 4, kWidth, kHeight);
864 }
865
866 // Test we can render to and resolve an RGB8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB8ToFBO4Samples)867 TEST_P(MultisampleResolveTest, ResolveRGB8ToFBO4Samples)
868 {
869 testResolveToUNormFBO(GL_RGB8, kEXPECTED_RGB8, 4, kWidth, kHeight);
870 }
871
872 // Test we can render to and resolve an RG8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG8ToFBO4Samples)873 TEST_P(MultisampleResolveTest, ResolveRG8ToFBO4Samples)
874 {
875 testResolveToUNormFBO(GL_RG8, kEXPECTED_RG8, 4, kWidth, kHeight);
876 }
877
878 // Test we can render to and resolve an R8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveR8ToFBO4Samples)879 TEST_P(MultisampleResolveTest, ResolveR8ToFBO4Samples)
880 {
881 testResolveToUNormFBO(GL_R8, kEXPECTED_R8, 4, kWidth, kHeight);
882 }
883
884 // Test we can render to and resolve an R16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR16FToFBO4Samples)885 TEST_P(MultisampleResolveTest, ResolveR16FToFBO4Samples)
886 {
887 testResolveToHalfFBO(GL_R16F, kEXPECTED_RF, 4, kWidth, kHeight);
888 }
889
890 // Test we can render to and resolve an RG16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG16FToFBO4Samples)891 TEST_P(MultisampleResolveTest, ResolveRG16FToFBO4Samples)
892 {
893 testResolveToHalfFBO(GL_RG16F, kEXPECTED_RGF, 4, kWidth, kHeight);
894 }
895
896 // Test we can render to and resolve an RGB16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB16FToFBO4Samples)897 TEST_P(MultisampleResolveTest, ResolveRGB16FToFBO4Samples)
898 {
899 testResolveToHalfFBO(GL_RGB16F, kEXPECTED_RGBF, 4, kWidth, kHeight);
900 }
901
902 // Test we can render to and resolve an RGBA16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA16FToFBO4Samples)903 TEST_P(MultisampleResolveTest, ResolveRGBA16FToFBO4Samples)
904 {
905 testResolveToHalfFBO(GL_RGBA16F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
906 }
907
908 // Test we can render to and resolve an R32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR32FToFBO4Samples)909 TEST_P(MultisampleResolveTest, ResolveR32FToFBO4Samples)
910 {
911 testResolveToFloatFBO(GL_R32F, kEXPECTED_RF, 4, kWidth, kHeight);
912 }
913
914 // Test we can render to and resolve an RG32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG32FToFBO4Samples)915 TEST_P(MultisampleResolveTest, ResolveRG32FToFBO4Samples)
916 {
917 testResolveToFloatFBO(GL_RG32F, kEXPECTED_RGF, 4, kWidth, kHeight);
918 }
919
920 // Test we can render to and resolve an RGB32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB32FToFBO4Samples)921 TEST_P(MultisampleResolveTest, ResolveRGB32FToFBO4Samples)
922 {
923 testResolveToRGBFloatFBO(GL_RGB32F, kEXPECTED_RGBF, 4, kWidth, kHeight);
924 }
925
926 // Test we can render to and resolve an RGBA32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA32FToFBO4Samples)927 TEST_P(MultisampleResolveTest, ResolveRGBA32FToFBO4Samples)
928 {
929 testResolveToFloatFBO(GL_RGBA32F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
930 }
931
TEST_P(MultisampleResolveTest,ResolveD32FS8F4Samples)932 TEST_P(MultisampleResolveTest, ResolveD32FS8F4Samples)
933 {
934 testResolveDepthToFBO(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
935 }
936
TEST_P(MultisampleResolveTest,ResolveD24S8Samples)937 TEST_P(MultisampleResolveTest, ResolveD24S8Samples)
938 {
939 testResolveDepthToFBO(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
940 }
941
TEST_P(MultisampleResolveTest,ResolveD32FSamples)942 TEST_P(MultisampleResolveTest, ResolveD32FSamples)
943 {
944 testResolveDepthToFBO(GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
945 }
946
TEST_P(MultisampleResolveTest,ResolveD24Samples)947 TEST_P(MultisampleResolveTest, ResolveD24Samples)
948 {
949 testResolveDepthToFBO(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
950 }
951
TEST_P(MultisampleResolveTest,ResolveD16Samples)952 TEST_P(MultisampleResolveTest, ResolveD16Samples)
953 {
954 testResolveDepthToFBO(GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
955 }
956
drawRectAndBlit(GLuint msFramebuffer,GLuint resolveFramebuffer,GLint width,GLint height,GLint matLoc,GLint colorLoc,float x,float y,float w,float h,const GLColor & color)957 void drawRectAndBlit(GLuint msFramebuffer,
958 GLuint resolveFramebuffer,
959 GLint width,
960 GLint height,
961 GLint matLoc,
962 GLint colorLoc,
963 float x,
964 float y,
965 float w,
966 float h,
967 const GLColor &color)
968 {
969 glBindFramebuffer(GL_FRAMEBUFFER, msFramebuffer);
970 float matrix[16] = {
971 w, 0, 0, 0, 0, h, 0, 0, 0, 0, 1, 0, x, y, 0, 1,
972 };
973 glUniformMatrix4fv(matLoc, 1, false, matrix);
974 angle::Vector4 c(color.toNormalizedVector());
975 glUniform4f(colorLoc, c[0], c[1], c[2], c[3]);
976 glDrawArrays(GL_TRIANGLES, 0, 6);
977
978 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
979 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
980 }
981
982 // Tests if we resolve(blit) a multisample renderbuffer that it
983 // does not lose its contents.
TEST_P(MultisampleResolveTest,DrawAndResolveMultipleTimes)984 TEST_P(MultisampleResolveTest, DrawAndResolveMultipleTimes)
985 {
986 constexpr GLint samples = 4;
987 constexpr GLenum format = GL_RGBA8;
988 constexpr GLint width = 16;
989 constexpr GLint height = 16;
990
991 constexpr char kVS[] = R"(#version 300 es
992 layout(location = 0) in vec4 position;
993 uniform mat4 mat;
994 void main() {
995 gl_Position = mat * position;
996 }
997 )";
998
999 constexpr char kFS[] = R"(#version 300 es
1000 precision highp float;
1001 uniform vec4 color;
1002 out vec4 outColor;
1003 void main() {
1004 outColor = color;
1005 }
1006 )";
1007
1008 glViewport(0, 0, width, height);
1009
1010 ANGLE_GL_PROGRAM(program, kVS, kFS);
1011 GLint matLoc = glGetUniformLocation(program, "mat");
1012 GLint colorLoc = glGetUniformLocation(program, "color");
1013 glUseProgram(program);
1014
1015 GLBuffer buf;
1016 glBindBuffer(GL_ARRAY_BUFFER, buf);
1017
1018 constexpr float vertices[] = {
1019 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1020 };
1021 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
1022 glEnableVertexAttribArray(0);
1023 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1024
1025 // Make samples = 4 multi-sample framebuffer.
1026 GLFramebuffer msFB;
1027 glBindFramebuffer(GL_FRAMEBUFFER, msFB);
1028
1029 GLRenderbuffer msRB;
1030 glBindRenderbuffer(GL_RENDERBUFFER, msRB);
1031 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
1032 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msRB);
1033 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1034
1035 // Make non-multi-sample framebuffer.
1036 GLFramebuffer drawFB;
1037 glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1038
1039 GLRenderbuffer drawRB;
1040 glBindRenderbuffer(GL_RENDERBUFFER, drawRB);
1041 glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
1042 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, drawRB);
1043 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1044
1045 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, -1, 2, 2, GLColor::red);
1046 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, -1, 1, 1, GLColor::green);
1047 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, 0, 1, 1, GLColor::blue);
1048 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, 0, 1, 1, GLColor::yellow);
1049 glEnable(GL_BLEND);
1050 glBlendFunc(GL_ONE, GL_ONE);
1051 drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -0.5, -0.5, 1, 1,
1052 GLColor(0x80, 0x80, 0x80, 0x80));
1053 glDisable(GL_BLEND);
1054 ASSERT_GL_NO_ERROR();
1055
1056 /*
1057 expected
1058 +-------------+--------------+
1059 | blue | yellow |
1060 | +---------+----------+ |
1061 | |.5,.5,1,1| 1,1,.5,1 | |
1062 +---+---------+----------+---+
1063 | |1,.5,.5,1| .5,1,.5,1| |
1064 | +---------+----------+ |
1065 | red | green |
1066 +-------------+--------------+
1067 0,0
1068 */
1069
1070 glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1071 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 4, GLColor::red);
1072 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2, height / 4, GLColor::green);
1073 EXPECT_PIXEL_RECT_EQ(0, height * 3 / 4, width / 2, height / 4, GLColor::blue);
1074 EXPECT_PIXEL_RECT_EQ(width / 2, height * 3 / 4, width / 2, height / 4, GLColor::yellow);
1075
1076 EXPECT_PIXEL_RECT_EQ(width / 4, height / 4, width / 4, height / 4, GLColor(255, 128, 128, 255));
1077 EXPECT_PIXEL_RECT_EQ(width / 2, height / 4, width / 4, height / 4, GLColor(128, 255, 128, 255));
1078 EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 4, height / 4, GLColor(128, 128, 255, 255));
1079 EXPECT_PIXEL_RECT_EQ(width / 2, height / 2, width / 4, height / 4, GLColor(255, 255, 128, 255));
1080 }
1081
1082 // Tests resolve after the read framebuffer's attachment has been swapped out.
TEST_P(MultisampleResolveTest,SwitchAttachmentsBeforeResolve)1083 TEST_P(MultisampleResolveTest, SwitchAttachmentsBeforeResolve)
1084 {
1085 constexpr GLuint kWidth = 16;
1086 constexpr GLuint kHeight = 24;
1087
1088 GLRenderbuffer msaaColor0, msaaColor1;
1089 glBindRenderbuffer(GL_RENDERBUFFER, msaaColor0);
1090 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, kWidth, kHeight);
1091 glBindRenderbuffer(GL_RENDERBUFFER, msaaColor1);
1092 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, kWidth, kHeight);
1093
1094 {
1095 // First, make one of the MSAA color buffers green.
1096 GLFramebuffer clearFbo;
1097 glBindFramebuffer(GL_FRAMEBUFFER, clearFbo);
1098 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1099 msaaColor1);
1100 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1101
1102 glClearColor(0, 1, 0, 1);
1103 glClear(GL_COLOR_BUFFER_BIT);
1104
1105 // Make sure clear is performed.
1106 GLTexture resolveTexture;
1107 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1108 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1109 nullptr);
1110
1111 GLFramebuffer verifyFBO;
1112 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, verifyFBO);
1113 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1114 resolveTexture, 0);
1115
1116 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1117 GL_NEAREST);
1118
1119 glBindFramebuffer(GL_READ_FRAMEBUFFER, verifyFBO);
1120 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1121 }
1122
1123 // Set up the msaa framebuffer with the other MSAA color buffer.
1124 GLFramebuffer msaaFBO;
1125 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1126 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColor0);
1127 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1128
1129 // Draw into it to start a render pass
1130 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1131 drawQuad(red, essl1_shaders::PositionAttrib(), 0.5f);
1132
1133 // Set up the resolve framebuffer
1134 GLRenderbuffer resolveColor;
1135 glBindRenderbuffer(GL_RENDERBUFFER, resolveColor);
1136 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
1137
1138 GLFramebuffer resolveFBO;
1139 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1140 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1141 resolveColor);
1142 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1143
1144 // Before resolve the MSAA framebuffer, switch its attachment. Regression test for a bug where
1145 // the resolve used the previous attachment.
1146 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1147 msaaColor1);
1148
1149 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1150 GL_NEAREST);
1151
1152 // Verify that the resolve happened on the pre-cleared attachment, not the rendered one.
1153 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1154 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1155 }
1156
1157 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND(
1158 MultisampleTest,
1159 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1160 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1161 ES3_VULKAN().enable(Feature::EmulatedPrerotation270),
1162 // Simulate missing msaa auto resolve feature in Metal.
1163 ES2_METAL().disable(Feature::AllowMultisampleStoreAndResolve));
1164
1165 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES3);
1166 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(MultisampleTestES3,
1167 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1168 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1169 ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
1170
1171 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES32);
1172 ANGLE_INSTANTIATE_TEST_ES32_AND(MultisampleTestES32,
1173 ES32_VULKAN().enable(Feature::EmulatedPrerotation90),
1174 ES32_VULKAN().enable(Feature::EmulatedPrerotation180),
1175 ES32_VULKAN().enable(Feature::EmulatedPrerotation270));
1176
1177 ANGLE_INSTANTIATE_TEST_ES3_AND(
1178 MultisampleResolveTest,
1179 ES3_METAL().disable(Feature::AlwaysResolveMultisampleRenderBuffers),
1180 ES3_METAL().enable(Feature::AlwaysResolveMultisampleRenderBuffers),
1181 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1182 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1183 ES3_VULKAN().enable(Feature::EmulatedPrerotation270),
1184 ES3_VULKAN().enable(Feature::PreferDrawClearOverVkCmdClearAttachments));
1185
1186 } // anonymous namespace
1187