Don't use GENERAL layout during mipmap generation in Vulkan

With the latest validation layers, they now spew an annoying number of
warnings cause we are using GENERAL when making mip maps. Even though
there was technically nothing wrong with our current code, this updates
the generation to use the specific layouts instead.

Bug: skia:
Change-Id: I0ce431e2540fd6fb2a87134768ca3ed488661012
Reviewed-on: https://skia-review.googlesource.com/112061
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 01d1846..a53432c 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1023,7 +1023,7 @@
             return;
         }
         // change the new image's layout so we can blit to it
-        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
+        tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                             VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
 
         // Blit original image to top level of new image
@@ -1040,7 +1040,7 @@
                                      VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                      tex->resource(),
                                      tex->image(),
-                                     VK_IMAGE_LAYOUT_GENERAL,
+                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                      1,
                                      &blitRegion,
                                      VK_FILTER_LINEAR);
@@ -1048,7 +1048,7 @@
         oldResource->unref(this);
     } else {
         // change layout of the layers so we can write to them.
-        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
+        tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                             VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
     }
 
@@ -1060,8 +1060,8 @@
         nullptr,                                         // pNext
         VK_ACCESS_TRANSFER_WRITE_BIT,                    // srcAccessMask
         VK_ACCESS_TRANSFER_READ_BIT,                     // dstAccessMask
-        VK_IMAGE_LAYOUT_GENERAL,                         // oldLayout
-        VK_IMAGE_LAYOUT_GENERAL,                         // newLayout
+        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,            // oldLayout
+        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,            // newLayout
         VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
         VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
         tex->image(),                                    // image
@@ -1087,13 +1087,24 @@
         blitRegion.dstOffsets[0] = { 0, 0, 0 };
         blitRegion.dstOffsets[1] = { width, height, 1 };
         fCurrentCmdBuffer->blitImage(this,
-                                     *tex,
-                                     *tex,
+                                     tex->resource(),
+                                     tex->image(),
+                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                                     tex->resource(),
+                                     tex->image(),
+                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                      1,
                                      &blitRegion,
                                      VK_FILTER_LINEAR);
         ++mipLevel;
     }
+    // This barrier logically is not needed, but it changes the final level to the same layout as
+    // all the others, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL. This makes tracking of the layouts and
+    // future layout changes easier.
+    imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
+    this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                false, &imageMemoryBarrier);
+    tex->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/vk/GrVkImage.h b/src/gpu/vk/GrVkImage.h
index 587c3a8..e43c2f2 100644
--- a/src/gpu/vk/GrVkImage.h
+++ b/src/gpu/vk/GrVkImage.h
@@ -52,6 +52,11 @@
                         VkPipelineStageFlags dstStageMask,
                         bool byRegion);
 
+    // This simply updates our tracking of the image layout and does not actually do any gpu work.
+    // This is only used for mip map generation where we are manually changing the layouts as we
+    // blit each layer, and then at the end need to update our tracking.
+    void updateImageLayout(VkImageLayout newLayout) { fInfo.fImageLayout = newLayout; }
+
     struct ImageDesc {
         VkImageType         fImageType;
         VkFormat            fFormat;