Vulkan/D3D11: Improve blit framebuffer tests and fix bug in D3D11
- Improving the tests revealed a bug in D3D 11 Fast Path rendering.
- These changes here are preliminary to implementing the blit for
depth/stencil in Vulkan when using the viewport flipping.
Bug: angleproject:2673
Bug: angleproject:2719
Change-Id: I6d55084e559d3110c8eeb0e7acb4e6fb09b6c1b5
Reviewed-on: https://chromium-review.googlesource.com/1132125
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Luc Ferron <lucferron@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index f6c1242..d7f4f6f 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -330,21 +330,37 @@
{
const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
ASSERT(readBuffer);
-
RenderTargetD3D *readRenderTarget = nullptr;
ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget));
ASSERT(readRenderTarget);
+ const bool invertSource = UsePresentPathFast(mRenderer, readBuffer);
+ gl::Rectangle actualSourceArea = sourceArea;
+ if (invertSource)
+ {
+ RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+ actualSourceArea.y = readRenderTarget11->getHeight() - sourceArea.y;
+ actualSourceArea.height = -sourceArea.height;
+ }
+
const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
ASSERT(drawBuffer);
-
RenderTargetD3D *drawRenderTarget = nullptr;
ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget));
ASSERT(drawRenderTarget);
- ANGLE_TRY(mRenderer->blitRenderbufferRect(context, sourceArea, destArea, readRenderTarget,
- drawRenderTarget, filter, scissor, false,
- blitDepth, blitStencil));
+ bool invertDest = UsePresentPathFast(mRenderer, drawBuffer);
+ gl::Rectangle actualDestArea = destArea;
+ if (invertDest)
+ {
+ RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+ actualDestArea.y = drawRenderTarget11->getHeight() - destArea.y;
+ actualDestArea.height = -destArea.height;
+ }
+
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(context, actualSourceArea, actualDestArea,
+ readRenderTarget, drawRenderTarget, filter,
+ scissor, false, blitDepth, blitStencil));
}
ANGLE_TRY(markAttachmentsDirty(context));
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 85ef146..89f22c3 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -485,6 +485,7 @@
{
if (flipSource || contextVk->isViewportFlipEnabledForReadFBO())
{
+ // TODO(lucferron): Implement this http://anglebug.com/2673
// The tests in BlitFramebufferANGLETest are passing, but they are wrong since they
// use a single color for the depth / stencil buffers, it looks like its working,
// but if it was a gradient or a checked board, you would realize the flip isn't
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
index 14a3535..79b8491 100644
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
@@ -25,6 +25,7 @@
mCheckerProgram = 0;
mBlueProgram = 0;
+ mRedProgram = 0;
mOriginalFBO = 0;
@@ -67,7 +68,8 @@
mCheckerProgram =
CompileProgram(essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Checkered());
mBlueProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
- if (mCheckerProgram == 0 || mBlueProgram == 0)
+ mRedProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
+ if (mCheckerProgram == 0 || mBlueProgram == 0 || mRedProgram == 0)
{
FAIL() << "shader compilation failed.";
}
@@ -236,6 +238,7 @@
{
glDeleteProgram(mCheckerProgram);
glDeleteProgram(mBlueProgram);
+ glDeleteProgram(mRedProgram);
glDeleteFramebuffers(1, &mUserFBO);
glDeleteTextures(1, &mUserColorBuffer);
@@ -337,6 +340,7 @@
GLuint mCheckerProgram;
GLuint mBlueProgram;
+ GLuint mRedProgram;
GLuint mOriginalFBO;
@@ -568,12 +572,8 @@
}
// blit from user-created FBO to system framebuffer, with depth buffer.
-TEST_P(BlitFramebufferANGLETest, BlitWithDepth)
+TEST_P(BlitFramebufferANGLETest, BlitWithDepthUserToDefault)
{
- // TODO(lucferron): Fix this test and the implementation.
- // http://anglebug.com/2673
- ANGLE_SKIP_TEST_IF(IsVulkan());
-
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_ANGLE_framebuffer_blit"));
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
@@ -583,74 +583,96 @@
glEnable(GL_DEPTH_TEST);
- drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
-
EXPECT_GL_NO_ERROR();
+ // Clear the first half of the screen
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, getWindowWidth(), getWindowHeight() / 2);
+
+ glClearDepthf(0.1f);
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // Scissor the second half of the screen
+ glScissor(0, getWindowHeight() / 2, getWindowWidth(), getWindowHeight() / 2);
+
+ glClearDepthf(0.9f);
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glDisable(GL_SCISSOR_TEST);
+
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
- // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
- drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.8f);
+ // if blit is happening correctly, this quad will draw only on the bottom half since it will be
+ // behind on the first half and in front on the second half.
+ drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.5f);
glDisable(GL_DEPTH_TEST);
- EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 0, 0, 255);
- EXPECT_PIXEL_EQ( getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
+ EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
+ EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
}
// blit from system FBO to user-created framebuffer, with depth buffer.
-TEST_P(BlitFramebufferANGLETest, ReverseBlitWithDepth)
+TEST_P(BlitFramebufferANGLETest, BlitWithDepthDefaultToUser)
{
- // TODO(lucferron): Fix this test and the implementation.
- // http://anglebug.com/2673
- ANGLE_SKIP_TEST_IF(IsVulkan());
-
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_ANGLE_framebuffer_blit"));
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
+ glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
- drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
-
EXPECT_GL_NO_ERROR();
+ // Clear the first half of the screen
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, getWindowWidth(), getWindowHeight() / 2);
+
+ glClearDepthf(0.1f);
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // Scissor the second half of the screen
+ glScissor(0, getWindowHeight() / 2, getWindowWidth(), getWindowHeight() / 2);
+
+ glClearDepthf(0.9f);
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glDisable(GL_SCISSOR_TEST);
+
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
- glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
- // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
-
- drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.8f);
+ // if blit is happening correctly, this quad will draw only on the bottom half since it will be
+ // behind on the first half and in front on the second half.
+ drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.5f);
glDisable(GL_DEPTH_TEST);
- EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 0, 0, 255);
- EXPECT_PIXEL_EQ( getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
+ EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
+ EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
}
// blit from one region of the system fbo to another-- this should fail.
@@ -789,10 +811,6 @@
TEST_P(BlitFramebufferANGLETest, BlitStencil)
{
- // TODO(lucferron): Fix this test and the implementation.
- // http://anglebug.com/2673
- ANGLE_SKIP_TEST_IF(IsVulkan());
-
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_ANGLE_framebuffer_blit"));
// TODO(jmadill): Figure out if we can fix this on D3D9.
@@ -804,16 +822,27 @@
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
- glClear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glClearStencil(0x0);
+
+ // Scissor half the screen so we fill the stencil only halfway
+ glScissor(0, 0, getWindowWidth(), getWindowHeight() / 2);
+ glEnable(GL_SCISSOR_TEST);
+
// fill the stencil buffer with 0x1
glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glEnable(GL_STENCIL_TEST);
- drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
+ drawQuad(mRedProgram, essl1_shaders::PositionAttrib(), 0.3f);
+
+ glDisable(GL_SCISSOR_TEST);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
+ // These clears are not useful in theory because we're copying over them, but its
+ // helpful in debugging if we see white in any result.
glClearColor(1.0, 1.0, 1.0, 1.0);
glClearStencil(0x0);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -827,19 +856,21 @@
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 0, 0, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
+
drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(),
0.8f); // blue quad will draw if stencil buffer was copied
+
glDisable(GL_STENCIL_TEST);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
- EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
- EXPECT_PIXEL_EQ( getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
+ EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
+ EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
}
// make sure that attempting to blit a partial depth buffer issues an error