Vulkan: Framebuffer blit support for depth/stencil cases
Bug: angleproject:2643
Change-Id: Ib50e4051f5b3965c2a752cf2cd45d3470312cdcf
Reviewed-on: https://chromium-review.googlesource.com/1115370
Commit-Queue: Luc Ferron <lucferron@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index ba969ca..7f24ff5 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -342,6 +342,74 @@
return mRenderTargetCache.getDepthStencil();
}
+gl::Error FramebufferVk::blitUsingCopy(RendererVk *renderer,
+ vk::CommandBuffer *commandBuffer,
+ const gl::Rectangle &readArea,
+ const gl::Rectangle &destArea,
+ RenderTargetVk *readRenderTarget,
+ RenderTargetVk *drawRenderTarget,
+ const gl::Rectangle *scissor,
+ bool blitDepthBuffer,
+ bool blitStencilBuffer)
+{
+ gl::Rectangle scissoredDrawRect = destArea;
+ gl::Rectangle scissoredReadRect = readArea;
+
+ if (scissor)
+ {
+ if (!ClipRectangle(destArea, *scissor, &scissoredDrawRect))
+ {
+ return gl::NoError();
+ }
+
+ if (!ClipRectangle(readArea, *scissor, &scissoredReadRect))
+ {
+ return gl::NoError();
+ }
+ }
+
+ const gl::Extents sourceFrameBufferExtents = readRenderTarget->getImageExtents();
+ const gl::Extents drawFrameBufferExtents = drawRenderTarget->getImageExtents();
+
+ // After cropping for the scissor, we also want to crop for the size of the buffers.
+ gl::Rectangle readFrameBufferBounds(0, 0, sourceFrameBufferExtents.width,
+ sourceFrameBufferExtents.height);
+ gl::Rectangle drawFrameBufferBounds(0, 0, drawFrameBufferExtents.width,
+ drawFrameBufferExtents.height);
+ if (!ClipRectangle(scissoredReadRect, readFrameBufferBounds, &scissoredReadRect))
+ {
+ return gl::NoError();
+ }
+
+ if (!ClipRectangle(scissoredDrawRect, drawFrameBufferBounds, &scissoredDrawRect))
+ {
+ return gl::NoError();
+ }
+
+ ASSERT(readFrameBufferBounds == drawFrameBufferBounds);
+ ASSERT(scissoredReadRect == readFrameBufferBounds);
+ ASSERT(scissoredDrawRect == drawFrameBufferBounds);
+
+ VkFlags aspectFlags =
+ vk::GetDepthStencilAspectFlags(readRenderTarget->getImageFormat().textureFormat());
+ vk::ImageHelper *readImage = readRenderTarget->getImageForRead(
+ this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, aspectFlags, commandBuffer);
+ vk::ImageHelper *writeImage = drawRenderTarget->getImageForWrite(this);
+ // Requirement of the copyImageToBuffer, the dst image must be in
+ // VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout.
+ writeImage->changeLayoutWithStages(aspectFlags, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
+ VkImageAspectFlags depthBit = blitDepthBuffer ? VK_IMAGE_ASPECT_DEPTH_BIT : 0;
+ VkImageAspectFlags stencilBit = blitStencilBuffer ? VK_IMAGE_ASPECT_STENCIL_BIT : 0;
+ VkImageAspectFlags aspectMask = depthBit | stencilBit;
+ vk::ImageHelper::Copy(readImage, writeImage, gl::Offset(), gl::Offset(),
+ gl::Extents(scissoredDrawRect.width, scissoredDrawRect.height, 1),
+ aspectMask, commandBuffer);
+
+ return gl::NoError();
+}
+
RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
{
RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
@@ -368,7 +436,6 @@
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
FramebufferVk *sourceFramebufferVk = vk::GetImpl(sourceFramebuffer);
-
if (blitColorBuffer)
{
RenderTargetVk *readRenderTarget = sourceFramebufferVk->getColorReadRenderTarget();
@@ -400,10 +467,9 @@
}
else
{
- // TODO(lucferron): Support framebuffer blit with a slower path.
- // http://anglebug.com/2643
- UNIMPLEMENTED();
- return gl::InternalError();
+ ASSERT(filter == GL_NEAREST);
+ ANGLE_TRY(blitUsingCopy(renderer, commandBuffer, sourceArea, destArea, readRenderTarget,
+ drawRenderTarget, scissor, blitDepthBuffer, blitStencilBuffer));
}
}