| Index: src/gpu/vk/GrVkGpu.cpp
|
| diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
|
| index 55f1eae99739220f56014aade32cada9fab47598..e1e99ed0209b7be99cba0930fc73cb8d866a64ae 100644
|
| --- a/src/gpu/vk/GrVkGpu.cpp
|
| +++ b/src/gpu/vk/GrVkGpu.cpp
|
| @@ -1057,31 +1057,35 @@ void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color
|
| inline bool can_copy_image(const GrSurface* dst,
|
| const GrSurface* src,
|
| const GrVkGpu* gpu) {
|
| - if (src->asTexture() &&
|
| - dst->asTexture() &&
|
| - src->origin() == dst->origin() &&
|
| - src->config() == dst->config()) {
|
| + // Currently we don't support msaa
|
| + if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
|
| + (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
|
| + return false;
|
| + }
|
| +
|
| + // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
|
| + // as image usage flags.
|
| + if (src->origin() == dst->origin() &&
|
| + GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
|
| return true;
|
| }
|
|
|
| // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled
|
| - // or the resolved image here?
|
| + // or the resolved image here? Im multisampled, Vulkan requires sample counts to be the same.
|
|
|
| return false;
|
| }
|
|
|
| void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
|
| GrSurface* src,
|
| + GrVkImage* dstImage,
|
| + GrVkImage* srcImage,
|
| const SkIRect& srcRect,
|
| const SkIPoint& dstPoint) {
|
| SkASSERT(can_copy_image(dst, src, this));
|
|
|
| - // Insert memory barriers to switch src and dst to transfer_source and transfer_dst layouts
|
| - GrVkTexture* dstTex = static_cast<GrVkTexture*>(dst->asTexture());
|
| - GrVkTexture* srcTex = static_cast<GrVkTexture*>(src->asTexture());
|
| -
|
| - VkImageLayout origDstLayout = dstTex->currentLayout();
|
| - VkImageLayout origSrcLayout = srcTex->currentLayout();
|
| + VkImageLayout origDstLayout = dstImage->currentLayout();
|
| + VkImageLayout origSrcLayout = srcImage->currentLayout();
|
|
|
| VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
|
| VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
| @@ -1091,13 +1095,13 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
|
| VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
|
| VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
|
| - dstTex->setImageLayout(this,
|
| - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
| - srcAccessMask,
|
| - dstAccessMask,
|
| - srcStageMask,
|
| - dstStageMask,
|
| - false);
|
| + dstImage->setImageLayout(this,
|
| + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
| + srcAccessMask,
|
| + dstAccessMask,
|
| + srcStageMask,
|
| + dstStageMask,
|
| + false);
|
|
|
| srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
|
| dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
| @@ -1105,13 +1109,13 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
|
| srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
|
| dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
|
| - srcTex->setImageLayout(this,
|
| - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
| - srcAccessMask,
|
| - dstAccessMask,
|
| - srcStageMask,
|
| - dstStageMask,
|
| - false);
|
| + srcImage->setImageLayout(this,
|
| + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
| + srcAccessMask,
|
| + dstAccessMask,
|
| + srcStageMask,
|
| + dstStageMask,
|
| + false);
|
|
|
| // Flip rect if necessary
|
| SkIRect srcVkRect = srcRect;
|
| @@ -1133,14 +1137,121 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
|
| copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 0 };
|
|
|
| fCurrentCmdBuffer->copyImage(this,
|
| - srcTex,
|
| + srcImage,
|
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
| - dstTex,
|
| + dstImage,
|
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
| 1,
|
| ©Region);
|
| }
|
|
|
| +inline bool can_copy_as_blit(const GrSurface* dst,
|
| + const GrSurface* src,
|
| + const GrVkImage* dstImage,
|
| + const GrVkImage* srcImage,
|
| + const GrVkGpu* gpu) {
|
| + // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
|
| + // as image usage flags.
|
| + const GrVkCaps& caps = gpu->vkCaps();
|
| + if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
|
| + !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
|
| + return false;
|
| + }
|
| +
|
| + // We cannot blit images that are multisampled. Will need to figure out if we can blit the
|
| + // resolved msaa though.
|
| + if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
|
| + (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
|
| + GrSurface* src,
|
| + GrVkImage* dstImage,
|
| + GrVkImage* srcImage,
|
| + const SkIRect& srcRect,
|
| + const SkIPoint& dstPoint) {
|
| + SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
|
| +
|
| + VkImageLayout origDstLayout = dstImage->currentLayout();
|
| + VkImageLayout origSrcLayout = srcImage->currentLayout();
|
| +
|
| + VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
|
| + VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
| +
|
| + VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
|
| + VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
| +
|
| + dstImage->setImageLayout(this,
|
| + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
| + srcAccessMask,
|
| + dstAccessMask,
|
| + srcStageMask,
|
| + dstStageMask,
|
| + false);
|
| +
|
| + srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
|
| + dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
| +
|
| + srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
|
| + dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
| +
|
| + srcImage->setImageLayout(this,
|
| + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
| + srcAccessMask,
|
| + dstAccessMask,
|
| + srcStageMask,
|
| + dstStageMask,
|
| + false);
|
| +
|
| + // Flip rect if necessary
|
| + SkIRect srcVkRect;
|
| + SkIRect dstRect;
|
| + dstRect.fLeft = dstPoint.fX;
|
| + dstRect.fRight = dstPoint.fX + srcVkRect.width();
|
| +
|
| + if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
|
| + srcVkRect.fTop = src->height() - srcRect.fBottom;
|
| + srcVkRect.fBottom = src->height() - srcRect.fTop;
|
| + } else {
|
| + srcVkRect = srcRect;
|
| + }
|
| +
|
| + if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
|
| + dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
|
| + } else {
|
| + dstRect.fTop = dstPoint.fY;
|
| + }
|
| + dstRect.fBottom = dstRect.fTop + srcVkRect.height();
|
| +
|
| + // If we have different origins, we need to flip the top and bottom of the dst rect so that we
|
| + // get the correct origintation of the copied data.
|
| + if (src->origin() != dst->origin()) {
|
| + SkTSwap(dstRect.fTop, dstRect.fBottom);
|
| + }
|
| +
|
| + VkImageBlit blitRegion;
|
| + memset(&blitRegion, 0, sizeof(VkImageBlit));
|
| + blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
| + blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
|
| + blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 0 };
|
| + blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
| + blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
|
| + blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 0 };
|
| +
|
| + fCurrentCmdBuffer->blitImage(this,
|
| + srcImage,
|
| + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
| + dstImage,
|
| + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
| + 1,
|
| + &blitRegion,
|
| + VK_FILTER_NEAREST); // We never scale so any filter works here
|
| +}
|
| +
|
| inline bool can_copy_as_draw(const GrSurface* dst,
|
| const GrSurface* src,
|
| const GrVkGpu* gpu) {
|
| @@ -1158,8 +1269,28 @@ bool GrVkGpu::onCopySurface(GrSurface* dst,
|
| GrSurface* src,
|
| const SkIRect& srcRect,
|
| const SkIPoint& dstPoint) {
|
| + GrVkImage* dstImage;
|
| + GrVkImage* srcImage;
|
| + if (dst->asTexture()) {
|
| + dstImage = static_cast<GrVkTexture*>(dst->asTexture());
|
| + } else {
|
| + SkASSERT(dst->asRenderTarget());
|
| + dstImage = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
|
| + }
|
| + if (src->asTexture()) {
|
| + srcImage = static_cast<GrVkTexture*>(src->asTexture());
|
| + } else {
|
| + SkASSERT(src->asRenderTarget());
|
| + srcImage = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
|
| + }
|
| +
|
| if (can_copy_image(dst, src, this)) {
|
| - this->copySurfaceAsCopyImage(dst, src, srcRect, dstPoint);
|
| + this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
|
| + return true;
|
| + }
|
| +
|
| + if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
|
| + this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
|
| return true;
|
| }
|
|
|
|
|