Apply setImageLayout() to all of a VkImage's subresources.

This also adds fLevelCount to GrVkImage::Resource, which allows
clients to wrap mipmapped textures.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1943933002
TBR=bsalomon@google.com

Review-Url: https://codereview.chromium.org/1943933002
diff --git a/include/gpu/vk/GrVkTypes.h b/include/gpu/vk/GrVkTypes.h
index ac33bf8..2e6a255 100755
--- a/include/gpu/vk/GrVkTypes.h
+++ b/include/gpu/vk/GrVkTypes.h
@@ -36,6 +36,7 @@
     VkImageTiling  fImageTiling;
     VkImageLayout  fImageLayout;
     VkFormat       fFormat;
+    uint32_t       fLevelCount;
 };
 
 GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrVkTextureInfo*));
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 7da587c..7c101a7 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -494,7 +494,6 @@
     VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
     VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
     VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
-    // TODO: change layout of all the subresources
     tex->setImageLayout(this,
                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                         srcAccessMask,
@@ -728,7 +727,6 @@
     VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
     VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
 
-    // TODO: change layout of all the subresources
     tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                         srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, false);
 
@@ -751,13 +749,8 @@
     srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
     dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 
-    tex->setImageLayout(this,
-                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                        srcAccessMask,
-                        dstAccessMask,
-                        srcStageMask,
-                        dstStageMask,
-                        false);
+    tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                        srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, false);
 
     // Blit original image
     int width = tex->width();
@@ -791,6 +784,7 @@
         blitRegion.dstOffsets[1] = { width/2, height/2, 0 };
 
         // TODO: insert image barrier to wait on previous blit
+        // TODO: change layout of src subresource to TRANSFER_SRC_OPTIMAL
 
         fCurrentCmdBuffer->blitImage(this,
                                      tex->resource(),
@@ -969,6 +963,7 @@
     info->fImageTiling = imageTiling;
     info->fImageLayout = initialLayout;
     info->fFormat = pixelFormat;
+    info->fLevelCount = 1;
 
     return (GrBackendObject)info;
 }
diff --git a/src/gpu/vk/GrVkImage.cpp b/src/gpu/vk/GrVkImage.cpp
index 5102124..53fb2f2 100644
--- a/src/gpu/vk/GrVkImage.cpp
+++ b/src/gpu/vk/GrVkImage.cpp
@@ -31,7 +31,8 @@
                                VkPipelineStageFlags srcStageMask,
                                VkPipelineStageFlags dstStageMask,
                                bool byRegion) {
-    SkASSERT(VK_IMAGE_LAYOUT_GENERAL != newLayout || VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout);
+    SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
+             VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout);
     // Is this reasonable? Could someone want to keep the same layout but use the masks to force
     // a barrier on certain things?
     if (newLayout == fCurrentLayout) {
@@ -39,16 +40,16 @@
     }
     VkImageAspectFlags aspectFlags = vk_format_to_aspect_flags(fResource->fFormat);
     VkImageMemoryBarrier imageMemoryBarrier = {
-        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // sType
-        NULL,                                     // pNext
-        srcAccessMask,                            // outputMask
-        dstAccessMask,                            // inputMask
-        fCurrentLayout,                           // oldLayout
-        newLayout,                                // newLayout
-        VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex
-        VK_QUEUE_FAMILY_IGNORED,                  // dstQueueFamilyIndex
-        fResource->fImage,                        // image
-        { aspectFlags, 0, 1, 0, 1 }               // subresourceRange
+        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
+        NULL,                                            // pNext
+        srcAccessMask,                                   // outputMask
+        dstAccessMask,                                   // inputMask
+        fCurrentLayout,                                  // oldLayout
+        newLayout,                                       // newLayout
+        VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
+        VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
+        fResource->fImage,                               // image
+        { aspectFlags, 0, fResource->fLevelCount, 0, 1 } // subresourceRange
     };
 
     // TODO: restrict to area of image we're interested in
@@ -104,7 +105,7 @@
         (VK_IMAGE_TILING_LINEAR == imageDesc.fImageTiling) ? Resource::kLinearTiling_Flag
                                                            : Resource::kNo_Flags;
 
-    return (new GrVkImage::Resource(image, alloc, flags, imageDesc.fFormat));
+    return (new GrVkImage::Resource(image, alloc, imageDesc.fFormat, imageDesc.fLevels, flags));
 }
 
 GrVkImage::~GrVkImage() {
diff --git a/src/gpu/vk/GrVkImage.h b/src/gpu/vk/GrVkImage.h
index f040c10..6f848d5 100644
--- a/src/gpu/vk/GrVkImage.h
+++ b/src/gpu/vk/GrVkImage.h
@@ -31,6 +31,7 @@
         VkImage                  fImage;
         VkDeviceMemory           fAlloc;
         VkFormat                 fFormat;
+        uint32_t                 fLevelCount;
         uint32_t                 fFlags;
 
         Resource()
@@ -38,10 +39,13 @@
             , fImage(VK_NULL_HANDLE)
             , fAlloc(VK_NULL_HANDLE)
             , fFormat(VK_FORMAT_UNDEFINED)
+            , fLevelCount(0)
             , fFlags(kNo_Flags) {}
 
-        Resource(VkImage image, VkDeviceMemory alloc, uint32_t flags, VkFormat format)
-            : fImage(image), fAlloc(alloc), fFormat(format), fFlags(flags) {}
+        Resource(VkImage image, VkDeviceMemory alloc, VkFormat format, uint32_t levelCount,
+                 uint32_t flags)
+            : fImage(image), fAlloc(alloc), fFormat(format), fLevelCount(levelCount)
+            , fFlags(flags) {}
 
         ~Resource() override {}
 
@@ -54,8 +58,9 @@
     // for wrapped textures
     class BorrowedResource : public Resource {
     public:
-        BorrowedResource(VkImage image, VkDeviceMemory alloc, uint32_t flags, VkFormat format)
-            : Resource(image, alloc, (flags | kBorrowed_Flag), format) {
+        BorrowedResource(VkImage image, VkDeviceMemory alloc, VkFormat format, uint32_t levelCount,
+                         uint32_t flags)
+            : Resource(image, alloc, format, levelCount, (flags | kBorrowed_Flag)) {
         }
     private:
         void freeGPUData(const GrVkGpu* gpu) const override;
@@ -122,7 +127,6 @@
     const Resource* fResource;
 
     VkImageLayout   fCurrentLayout;
-
 };
 
 #endif
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 46099f2..70b73a7 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -214,10 +214,12 @@
     if (kBorrow_GrWrapOwnership == ownership) {
         imageResource = new GrVkImage::BorrowedResource(info->fImage,
                                                         info->fAlloc,
-                                                        flags,
-                                                        info->fFormat);
+                                                        info->fFormat,
+                                                        info->fLevelCount,
+                                                        flags);
     } else {
-        imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, flags, info->fFormat);
+        imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, info->fFormat,
+                                                info->fLevelCount, flags);
     }
     if (!imageResource) {
         return nullptr;
diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp
index 91852da..1e1e1b2 100644
--- a/src/gpu/vk/GrVkTexture.cpp
+++ b/src/gpu/vk/GrVkTexture.cpp
@@ -55,13 +55,13 @@
 GrVkTexture* GrVkTexture::Create(GrVkGpu* gpu,
                                  ResourceType type,
                                  const GrSurfaceDesc& desc,
-                                 VkFormat format, uint32_t levels, 
+                                 VkFormat format,
                                  const GrVkImage::Resource* imageResource) {
     VkImage image = imageResource->fImage;
 
     const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, format,
                                                            GrVkImageView::kColor_Type, 
-                                                           levels);
+                                                           imageResource->fLevelCount);
     if (!imageView) {
         return nullptr;
     }
@@ -79,8 +79,7 @@
         return nullptr;
     }
 
-    GrVkTexture* texture = Create(gpu, budgeted, desc, imageDesc.fFormat, imageDesc.fLevels,
-                                  imageResource);
+    GrVkTexture* texture = Create(gpu, budgeted, desc, imageDesc.fFormat, imageResource);
     // Create() will increment the refCount of the image resource if it succeeds
     imageResource->unref(gpu);
 
@@ -103,17 +102,18 @@
     if (kBorrow_GrWrapOwnership == ownership) {
         imageResource = new GrVkImage::BorrowedResource(info->fImage,
                                                         info->fAlloc,
-                                                        flags,
-                                                        info->fFormat);
+                                                        info->fFormat,
+                                                        info->fLevelCount,
+                                                        flags);
     } else {
-        imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, flags, info->fFormat);
+        imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, info->fFormat, 
+                                                info->fLevelCount, flags);
     }
     if (!imageResource) {
         return nullptr;
     }
 
-    // We have no other information so we have to assume that wrapped textures have only one level
-    GrVkTexture* texture = Create(gpu, kWrapped, desc, format, 1, imageResource);
+    GrVkTexture* texture = Create(gpu, kWrapped, desc, format, imageResource);
     if (texture) {
         texture->fCurrentLayout = info->fImageLayout;
     }
diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h
index be52c17..c8fb917 100644
--- a/src/gpu/vk/GrVkTexture.h
+++ b/src/gpu/vk/GrVkTexture.h
@@ -41,7 +41,7 @@
 
     template<typename ResourceType>
     static GrVkTexture* Create(GrVkGpu*, ResourceType, const GrSurfaceDesc&, VkFormat,
-                               uint32_t levels, const GrVkImage::Resource* texImpl);
+                               const GrVkImage::Resource* texImpl);
 
     GrVkGpu* getVkGpu() const;
 
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp
index e44e85a..2a89817 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -159,10 +159,12 @@
     if (kBorrow_GrWrapOwnership == ownership) {
         imageResource = new GrVkImage::BorrowedResource(info->fImage,
                                                         info->fAlloc,
-                                                        flags,
-                                                        info->fFormat);
+                                                        info->fFormat,
+                                                        info->fLevelCount,
+                                                        flags);
     } else {
-        imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, flags, info->fFormat);
+        imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, info->fFormat, 
+                                                info->fLevelCount, flags);
     }
     if (!imageResource) {
         return nullptr;