Commit 5c8113d3 by Luc Ferron Committed by Commit Bot

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/1132125Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Luc Ferron <lucferron@chromium.org>
parent a6a7842f
...@@ -330,21 +330,37 @@ gl::Error Framebuffer11::blitImpl(const gl::Context *context, ...@@ -330,21 +330,37 @@ gl::Error Framebuffer11::blitImpl(const gl::Context *context,
{ {
const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
ASSERT(readBuffer); ASSERT(readBuffer);
RenderTargetD3D *readRenderTarget = nullptr; RenderTargetD3D *readRenderTarget = nullptr;
ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget)); ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget));
ASSERT(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(); const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
ASSERT(drawBuffer); ASSERT(drawBuffer);
RenderTargetD3D *drawRenderTarget = nullptr; RenderTargetD3D *drawRenderTarget = nullptr;
ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget)); ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget));
ASSERT(drawRenderTarget); ASSERT(drawRenderTarget);
ANGLE_TRY(mRenderer->blitRenderbufferRect(context, sourceArea, destArea, readRenderTarget, bool invertDest = UsePresentPathFast(mRenderer, drawBuffer);
drawRenderTarget, filter, scissor, false, gl::Rectangle actualDestArea = destArea;
blitDepth, blitStencil)); 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)); ANGLE_TRY(markAttachmentsDirty(context));
......
...@@ -485,6 +485,7 @@ gl::Error FramebufferVk::blit(const gl::Context *context, ...@@ -485,6 +485,7 @@ gl::Error FramebufferVk::blit(const gl::Context *context,
{ {
if (flipSource || contextVk->isViewportFlipEnabledForReadFBO()) if (flipSource || contextVk->isViewportFlipEnabledForReadFBO())
{ {
// TODO(lucferron): Implement this http://anglebug.com/2673
// The tests in BlitFramebufferANGLETest are passing, but they are wrong since they // 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, // 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 // but if it was a gradient or a checked board, you would realize the flip isn't
......
...@@ -25,6 +25,7 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -25,6 +25,7 @@ class BlitFramebufferANGLETest : public ANGLETest
mCheckerProgram = 0; mCheckerProgram = 0;
mBlueProgram = 0; mBlueProgram = 0;
mRedProgram = 0;
mOriginalFBO = 0; mOriginalFBO = 0;
...@@ -67,7 +68,8 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -67,7 +68,8 @@ class BlitFramebufferANGLETest : public ANGLETest
mCheckerProgram = mCheckerProgram =
CompileProgram(essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Checkered()); CompileProgram(essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Checkered());
mBlueProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); 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."; FAIL() << "shader compilation failed.";
} }
...@@ -236,6 +238,7 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -236,6 +238,7 @@ class BlitFramebufferANGLETest : public ANGLETest
{ {
glDeleteProgram(mCheckerProgram); glDeleteProgram(mCheckerProgram);
glDeleteProgram(mBlueProgram); glDeleteProgram(mBlueProgram);
glDeleteProgram(mRedProgram);
glDeleteFramebuffers(1, &mUserFBO); glDeleteFramebuffers(1, &mUserFBO);
glDeleteTextures(1, &mUserColorBuffer); glDeleteTextures(1, &mUserColorBuffer);
...@@ -337,6 +340,7 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -337,6 +340,7 @@ class BlitFramebufferANGLETest : public ANGLETest
GLuint mCheckerProgram; GLuint mCheckerProgram;
GLuint mBlueProgram; GLuint mBlueProgram;
GLuint mRedProgram;
GLuint mOriginalFBO; GLuint mOriginalFBO;
...@@ -568,12 +572,8 @@ TEST_P(BlitFramebufferANGLETest, ReverseOversizedBlit) ...@@ -568,12 +572,8 @@ TEST_P(BlitFramebufferANGLETest, ReverseOversizedBlit)
} }
// blit from user-created FBO to system framebuffer, with depth buffer. // 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")); ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_ANGLE_framebuffer_blit"));
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO); glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
...@@ -583,74 +583,96 @@ TEST_P(BlitFramebufferANGLETest, BlitWithDepth) ...@@ -583,74 +583,96 @@ TEST_P(BlitFramebufferANGLETest, BlitWithDepth)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
EXPECT_GL_NO_ERROR(); 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_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO); 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(), glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO); glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
// if blit is happening correctly, this quad will not draw, because it is behind the blitted one // if blit is happening correctly, this quad will draw only on the bottom half since it will be
drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.8f); // behind on the first half and in front on the second half.
drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.5f);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255); 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, getWindowHeight() / 4, 255, 0, 0, 255);
EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * 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, 255, 0, 255); EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
} }
// blit from system FBO to user-created framebuffer, with depth buffer. // 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")); ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_ANGLE_framebuffer_blit"));
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO); glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.3f);
EXPECT_GL_NO_ERROR(); 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_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO); 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(), glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO); glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
// if blit is happening correctly, this quad will not draw, because it is behind the blitted one // 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.8f); drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), 0.5f);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255); 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, getWindowHeight() / 4, 255, 0, 0, 255);
EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * 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, 255, 0, 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. // blit from one region of the system fbo to another-- this should fail.
...@@ -789,10 +811,6 @@ TEST_P(BlitFramebufferANGLETest, BlitWithMissingAttachments) ...@@ -789,10 +811,6 @@ TEST_P(BlitFramebufferANGLETest, BlitWithMissingAttachments)
TEST_P(BlitFramebufferANGLETest, BlitStencil) 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")); ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_ANGLE_framebuffer_blit"));
// TODO(jmadill): Figure out if we can fix this on D3D9. // TODO(jmadill): Figure out if we can fix this on D3D9.
...@@ -804,16 +822,27 @@ TEST_P(BlitFramebufferANGLETest, BlitStencil) ...@@ -804,16 +822,27 @@ TEST_P(BlitFramebufferANGLETest, BlitStencil)
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO); 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 // fill the stencil buffer with 0x1
glStencilFunc(GL_ALWAYS, 0x1, 0xFF); glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glEnable(GL_STENCIL_TEST); 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_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO); 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); glClearColor(1.0, 1.0, 1.0, 1.0);
glClearStencil(0x0); glClearStencil(0x0);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
...@@ -827,19 +856,21 @@ TEST_P(BlitFramebufferANGLETest, BlitStencil) ...@@ -827,19 +856,21 @@ TEST_P(BlitFramebufferANGLETest, BlitStencil)
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO); glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255); 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, getWindowHeight() / 4, 255, 0, 0, 255);
EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * 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); 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 glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(), drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(),
0.8f); // blue quad will draw if stencil buffer was copied 0.8f); // blue quad will draw if stencil buffer was copied
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
EXPECT_PIXEL_EQ( getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255); 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, getWindowHeight() / 4, 0, 0, 255, 255);
EXPECT_PIXEL_EQ(3 * 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, 0, 255, 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 // make sure that attempting to blit a partial depth buffer issues an error
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment