aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2016-07-15 13:41:42 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-15 13:41:42 -0700
commit7ac5da853457b032781cf865ba018de78508edb7 (patch)
tree833907fdab20d6aa6ec0c7097be73980eecad61f
parenteb92cb3e84f49b5eedb22b36acffd895d6a90e5a (diff)
Dont allocate a new image which already has mip levels, when regenerating vulkan mipmaps
-rw-r--r--src/gpu/vk/GrVkGpu.cpp91
-rw-r--r--src/gpu/vk/GrVkImage.h1
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);