aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2016-04-05 07:23:38 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-05 07:23:38 -0700
commit17b892551465e5a44560a06e4b34dc3592b49622 (patch)
treef0ab8ea24215d74e25cd670570768ec4e1be7dfa /src
parent74cb44dee50b5db94c1374cbcf0b0a1babd09d89 (diff)
Implement blit image for copySurface in Vulkan
Also allows CopyImage to handle GrRenderTargets which are not textures. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1852413002 Review URL: https://codereview.chromium.org/1852413002
Diffstat (limited to 'src')
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.cpp22
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.h9
-rw-r--r--src/gpu/vk/GrVkGpu.cpp187
-rw-r--r--src/gpu/vk/GrVkGpu.h9
4 files changed, 199 insertions, 28 deletions
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp
index cd97337956..2868d8e1fd 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -253,6 +253,28 @@ void GrVkCommandBuffer::copyImage(const GrVkGpu* gpu,
copyRegions));
}
+void GrVkCommandBuffer::blitImage(const GrVkGpu* gpu,
+ GrVkImage* srcImage,
+ VkImageLayout srcLayout,
+ GrVkImage* dstImage,
+ VkImageLayout dstLayout,
+ uint32_t blitRegionCount,
+ const VkImageBlit* blitRegions,
+ VkFilter filter) {
+ SkASSERT(fIsActive);
+ SkASSERT(!fActiveRenderPass);
+ this->addResource(srcImage->resource());
+ this->addResource(dstImage->resource());
+ GR_VK_CALL(gpu->vkInterface(), CmdBlitImage(fCmdBuffer,
+ srcImage->textureImage(),
+ srcLayout,
+ dstImage->textureImage(),
+ dstLayout,
+ blitRegionCount,
+ blitRegions,
+ filter));
+}
+
void GrVkCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu,
GrVkImage* srcImage,
VkImageLayout srcLayout,
diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h
index 99a3563e8b..e9e3d767a9 100644
--- a/src/gpu/vk/GrVkCommandBuffer.h
+++ b/src/gpu/vk/GrVkCommandBuffer.h
@@ -124,6 +124,15 @@ public:
uint32_t copyRegionCount,
const VkImageCopy* copyRegions);
+ void blitImage(const GrVkGpu* gpu,
+ GrVkImage* srcImage,
+ VkImageLayout srcLayout,
+ GrVkImage* dstImage,
+ VkImageLayout dstLayout,
+ uint32_t blitRegionCount,
+ const VkImageBlit* blitRegions,
+ VkFilter filter);
+
void copyImageToBuffer(const GrVkGpu* gpu,
GrVkImage* srcImage,
VkImageLayout srcLayout,
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 55f1eae997..e1e99ed020 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,
&copyRegion);
}
+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;
}
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 001e12c870..87fea90e32 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -174,9 +174,18 @@ private:
void copySurfaceAsCopyImage(GrSurface* dst,
GrSurface* src,
+ GrVkImage* dstImage,
+ GrVkImage* srcImage,
const SkIRect& srcRect,
const SkIPoint& dstPoint);
+ void copySurfaceAsBlit(GrSurface* dst,
+ GrSurface* src,
+ GrVkImage* dstImage,
+ GrVkImage* srcImage,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint);
+
void copySurfaceAsDraw(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,