From 7ac5da853457b032781cf865ba018de78508edb7 Mon Sep 17 00:00:00 2001 From: egdaniel Date: Fri, 15 Jul 2016 13:41:42 -0700 Subject: Dont allocate a new image which already has mip levels, when regenerating vulkan mipmaps BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2146063008 Review-Url: https://codereview.chromium.org/2146063008 --- src/gpu/vk/GrVkGpu.cpp | 91 ++++++++++++++++++++++++++------------------------ src/gpu/vk/GrVkImage.h | 1 + 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 76d50b0959..e779bac99b 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -777,8 +777,8 @@ void GrVkGpu::generateMipmap(GrVkTexture* tex) { return; } - // We cannot generate mipmaps for images that are multisampled. - // TODO: does it even make sense for rendertargets in general? + // We currently don't support generating mipmaps for images that are multisampled. + // TODO: Add support for mipmapping the resolve target of a multisampled image if (tex->asRenderTarget() && tex->asRenderTarget()->numColorSamples() > 1) { return; } @@ -791,49 +791,56 @@ void GrVkGpu::generateMipmap(GrVkTexture* tex) { return; } - // change the original image's layout - tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); - - // grab handle to the original image resource - const GrVkResource* oldResource = tex->resource(); - oldResource->ref(); - VkImage oldImage = tex->image(); + int width = tex->width(); + int height = tex->height(); + VkImageBlit blitRegion; + memset(&blitRegion, 0, sizeof(VkImageBlit)); // SkMipMap doesn't include the base level in the level count so we have to add 1 uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1; - if (!tex->reallocForMipmap(this, levelCount)) { - oldResource->unref(this); - return; - } - - // change the new image's layout - tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); + if (levelCount != tex->mipLevels()) { + const GrVkResource* oldResource = tex->resource(); + oldResource->ref(); + // grab handle to the original image resource + VkImage oldImage = tex->image(); + + // change the original image's layout so we can copy from it + tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); + + if (!tex->reallocForMipmap(this, levelCount)) { + oldResource->unref(this); + return; + } + // change the new image's layout so we can blit to it + tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); - // Blit original image - int width = tex->width(); - int height = tex->height(); + // Blit original image to top level of new image + blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + blitRegion.srcOffsets[0] = { 0, 0, 0 }; + blitRegion.srcOffsets[1] = { width, height, 1 }; + blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + blitRegion.dstOffsets[0] = { 0, 0, 0 }; + blitRegion.dstOffsets[1] = { width, height, 1 }; - VkImageBlit blitRegion; - memset(&blitRegion, 0, sizeof(VkImageBlit)); - blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - blitRegion.srcOffsets[0] = { 0, 0, 0 }; - blitRegion.srcOffsets[1] = { width, height, 1 }; - blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - blitRegion.dstOffsets[0] = { 0, 0, 0 }; - blitRegion.dstOffsets[1] = { width, height, 1 }; + fCurrentCmdBuffer->blitImage(this, + oldResource, + oldImage, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + tex->resource(), + tex->image(), + VK_IMAGE_LAYOUT_GENERAL, + 1, + &blitRegion, + VK_FILTER_LINEAR); - fCurrentCmdBuffer->blitImage(this, - oldResource, - oldImage, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - tex->resource(), - tex->image(), - VK_IMAGE_LAYOUT_GENERAL, - 1, - &blitRegion, - VK_FILTER_LINEAR); + oldResource->unref(this); + } else { + // change layout of the layers so we can write to them. + tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); + } // setup memory barrier SkASSERT(GrVkFormatToPixelConfig(tex->imageFormat(), nullptr)); @@ -841,8 +848,8 @@ void GrVkGpu::generateMipmap(GrVkTexture* tex) { VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType NULL, // pNext - VK_ACCESS_TRANSFER_WRITE_BIT, // outputMask - VK_ACCESS_TRANSFER_READ_BIT, // inputMask + VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask + VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask VK_IMAGE_LAYOUT_GENERAL, // oldLayout VK_IMAGE_LAYOUT_GENERAL, // newLayout VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex @@ -877,8 +884,6 @@ void GrVkGpu::generateMipmap(GrVkTexture* tex) { VK_FILTER_LINEAR); ++mipLevel; } - - oldResource->unref(this); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/vk/GrVkImage.h b/src/gpu/vk/GrVkImage.h index 2bfc08d150..921d98e6ac 100644 --- a/src/gpu/vk/GrVkImage.h +++ b/src/gpu/vk/GrVkImage.h @@ -43,6 +43,7 @@ public: VkImage image() const { return fInfo.fImage; } const GrVkAlloc& alloc() const { return fInfo.fAlloc; } VkFormat imageFormat() const { return fInfo.fFormat; } + uint32_t mipLevels() const { return fInfo.fLevelCount; } const Resource* resource() const { return fResource; } bool isLinearTiled() const { return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling); -- cgit v1.2.3