Merge GrVkAttachment into GrVkImage.

Bug: skia:12402
Change-Id: I743724f66db8d7666d4d627d6945ce6bc3dc6bc3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448261
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 95d11f2..7636dcc 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -605,8 +605,6 @@
   "$_include/private/GrVkTypesPriv.h",
   "$_src/gpu/vk/GrVkAMDMemoryAllocator.cpp",
   "$_src/gpu/vk/GrVkAMDMemoryAllocator.h",
-  "$_src/gpu/vk/GrVkAttachment.cpp",
-  "$_src/gpu/vk/GrVkAttachment.h",
   "$_src/gpu/vk/GrVkBuffer.cpp",
   "$_src/gpu/vk/GrVkBuffer.h",
   "$_src/gpu/vk/GrVkCaps.cpp",
diff --git a/src/gpu/vk/GrVkAttachment.cpp b/src/gpu/vk/GrVkAttachment.cpp
deleted file mode 100644
index b5e463b..0000000
--- a/src/gpu/vk/GrVkAttachment.cpp
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/gpu/vk/GrVkAttachment.h"
-
-#include "src/gpu/vk/GrVkDescriptorSet.h"
-#include "src/gpu/vk/GrVkGpu.h"
-#include "src/gpu/vk/GrVkImage.h"
-#include "src/gpu/vk/GrVkImageView.h"
-#include "src/gpu/vk/GrVkUtil.h"
-
-#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
-
-GrVkAttachment::GrVkAttachment(GrVkGpu* gpu,
-                               SkISize dimensions,
-                               UsageFlags supportedUsages,
-                               const GrVkImageInfo& info,
-                               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-                               sk_sp<const GrVkImageView> framebufferView,
-                               sk_sp<const GrVkImageView> textureView,
-                               SkBudgeted budgeted)
-        : GrAttachment(gpu, dimensions, supportedUsages, info.fSampleCount,
-                       info.fLevelCount > 1 ? GrMipmapped::kYes : GrMipmapped::kNo,
-                       info.fProtected)
-        , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kOwned)
-        , fFramebufferView(std::move(framebufferView))
-        , fTextureView(std::move(textureView)) {
-    this->registerWithCache(budgeted);
-}
-
-GrVkAttachment::GrVkAttachment(GrVkGpu* gpu,
-                               SkISize dimensions,
-                               UsageFlags supportedUsages,
-                               const GrVkImageInfo& info,
-                               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-                               sk_sp<const GrVkImageView> framebufferView,
-                               sk_sp<const GrVkImageView> textureView,
-                               GrBackendObjectOwnership ownership,
-                               GrWrapCacheable cacheable,
-                               bool forSecondaryCB)
-        : GrAttachment(gpu, dimensions, supportedUsages, info.fSampleCount,
-                       info.fLevelCount > 1 ? GrMipmapped::kYes : GrMipmapped::kNo,
-                       info.fProtected)
-        , GrVkImage(gpu, info, std::move(mutableState), ownership, forSecondaryCB)
-        , fFramebufferView(std::move(framebufferView))
-        , fTextureView(std::move(textureView)) {
-    this->registerWithCacheWrapped(cacheable);
-}
-
-sk_sp<GrVkAttachment> GrVkAttachment::MakeStencil(GrVkGpu* gpu,
-                                                  SkISize dimensions,
-                                                  int sampleCnt,
-                                                  VkFormat format) {
-    VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
-                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-    return GrVkAttachment::Make(gpu, dimensions, UsageFlags::kStencilAttachment, sampleCnt, format,
-                                /*mipLevels=*/1, vkUsageFlags, GrProtected::kNo, SkBudgeted::kYes);
-}
-
-sk_sp<GrVkAttachment> GrVkAttachment::MakeMSAA(GrVkGpu* gpu,
-                                               SkISize dimensions,
-                                               int numSamples,
-                                               VkFormat format,
-                                               GrProtected isProtected) {
-    SkASSERT(numSamples > 1);
-
-    VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
-                                     VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
-                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-    return GrVkAttachment::Make(gpu, dimensions, UsageFlags::kColorAttachment, numSamples, format,
-                                /*mipLevels=*/1, vkUsageFlags, isProtected, SkBudgeted::kYes);
-}
-
-sk_sp<GrVkAttachment> GrVkAttachment::MakeTexture(GrVkGpu* gpu,
-                                                  SkISize dimensions,
-                                                  VkFormat format,
-                                                  uint32_t mipLevels,
-                                                  GrRenderable renderable,
-                                                  int numSamples,
-                                                  SkBudgeted budgeted,
-                                                  GrProtected isProtected) {
-    UsageFlags usageFlags = UsageFlags::kTexture;
-    VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
-                                     VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
-                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-    if (renderable == GrRenderable::kYes) {
-        usageFlags |= UsageFlags::kColorAttachment;
-        vkUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-        // We always make our render targets support being used as input attachments
-        vkUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
-    }
-
-    return GrVkAttachment::Make(gpu, dimensions, usageFlags, numSamples, format, mipLevels,
-                                vkUsageFlags, isProtected, budgeted);
-}
-
-static bool make_views(GrVkGpu* gpu, const GrVkImageInfo& info,
-                       GrAttachment::UsageFlags attachmentUsages,
-                       sk_sp<const GrVkImageView>* framebufferView,
-                       sk_sp<const GrVkImageView>* textureView) {
-    GrVkImageView::Type viewType;
-    if (attachmentUsages & GrAttachment::UsageFlags::kStencilAttachment) {
-        // If we have stencil usage then we shouldn't have any other usages
-        SkASSERT(attachmentUsages == GrAttachment::UsageFlags::kStencilAttachment);
-        viewType = GrVkImageView::kStencil_Type;
-    } else {
-        viewType = GrVkImageView::kColor_Type;
-    }
-
-    if (SkToBool(attachmentUsages & GrAttachment::UsageFlags::kStencilAttachment) ||
-        SkToBool(attachmentUsages & GrAttachment::UsageFlags::kColorAttachment)) {
-        // Attachments can only have a mip level of 1
-        *framebufferView = GrVkImageView::Make(gpu, info.fImage, info.fFormat, viewType, 1,
-                                               info.fYcbcrConversionInfo);
-        if (!*framebufferView) {
-            return false;
-        }
-    }
-
-    if (attachmentUsages & GrAttachment::UsageFlags::kTexture) {
-        *textureView = GrVkImageView::Make(gpu, info.fImage, info.fFormat, viewType,
-                                           info.fLevelCount, info.fYcbcrConversionInfo);
-        if (!*textureView) {
-            return false;
-        }
-    }
-    return true;
-}
-
-sk_sp<GrVkAttachment> GrVkAttachment::Make(GrVkGpu* gpu,
-                                           SkISize dimensions,
-                                           UsageFlags attachmentUsages,
-                                           int sampleCnt,
-                                           VkFormat format,
-                                           uint32_t mipLevels,
-                                           VkImageUsageFlags vkUsageFlags,
-                                           GrProtected isProtected,
-                                           SkBudgeted budgeted) {
-    GrVkImage::ImageDesc imageDesc;
-    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
-    imageDesc.fFormat = format;
-    imageDesc.fWidth = dimensions.width();
-    imageDesc.fHeight = dimensions.height();
-    imageDesc.fLevels = mipLevels;
-    imageDesc.fSamples = sampleCnt;
-    imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
-    imageDesc.fUsageFlags = vkUsageFlags;
-    imageDesc.fIsProtected = isProtected;
-
-    GrVkImageInfo info;
-    if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
-        return nullptr;
-    }
-
-    sk_sp<const GrVkImageView> framebufferView;
-    sk_sp<const GrVkImageView> textureView;
-    if (!make_views(gpu, info, attachmentUsages, &framebufferView, &textureView)) {
-        GrVkImage::DestroyImageInfo(gpu, &info);
-        return nullptr;
-    }
-
-    sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(
-            new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily));
-    return sk_sp<GrVkAttachment>(new GrVkAttachment(gpu, dimensions, attachmentUsages, info,
-                                                    std::move(mutableState),
-                                                    std::move(framebufferView),
-                                                    std::move(textureView),
-                                                    budgeted));
-}
-
-sk_sp<GrVkAttachment> GrVkAttachment::MakeWrapped(
-        GrVkGpu* gpu,
-        SkISize dimensions,
-        const GrVkImageInfo& info,
-        sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-        UsageFlags attachmentUsages,
-        GrWrapOwnership ownership,
-        GrWrapCacheable cacheable,
-        bool forSecondaryCB) {
-    sk_sp<const GrVkImageView> framebufferView;
-    sk_sp<const GrVkImageView> textureView;
-    if (!forSecondaryCB) {
-        if (!make_views(gpu, info, attachmentUsages, &framebufferView, &textureView)) {
-            return nullptr;
-        }
-    }
-
-     GrBackendObjectOwnership backendOwnership = kBorrow_GrWrapOwnership == ownership
-            ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
-
-    return sk_sp<GrVkAttachment>(new GrVkAttachment(gpu, dimensions, attachmentUsages, info,
-                                                    std::move(mutableState),
-                                                    std::move(framebufferView),
-                                                    std::move(textureView),
-                                                    backendOwnership, cacheable, forSecondaryCB));
-}
-
-static void write_input_desc_set(GrVkGpu* gpu, VkImageView view, VkImageLayout layout,
-                                 VkDescriptorSet descSet) {
-    VkDescriptorImageInfo imageInfo;
-    memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
-    imageInfo.sampler = VK_NULL_HANDLE;
-    imageInfo.imageView = view;
-    imageInfo.imageLayout = layout;
-
-    VkWriteDescriptorSet writeInfo;
-    memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
-    writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-    writeInfo.pNext = nullptr;
-    writeInfo.dstSet = descSet;
-    writeInfo.dstBinding = GrVkUniformHandler::kInputBinding;
-    writeInfo.dstArrayElement = 0;
-    writeInfo.descriptorCount = 1;
-    writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
-    writeInfo.pImageInfo = &imageInfo;
-    writeInfo.pBufferInfo = nullptr;
-    writeInfo.pTexelBufferView = nullptr;
-
-    GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
-}
-
-gr_rp < const GrVkDescriptorSet> GrVkAttachment::inputDescSetForBlending(GrVkGpu* gpu) {
-    if (!this->supportsInputAttachmentUsage()) {
-        return nullptr;
-    }
-    if (fCachedBlendingInputDescSet) {
-        return fCachedBlendingInputDescSet;
-    }
-
-    fCachedBlendingInputDescSet.reset(gpu->resourceProvider().getInputDescriptorSet());
-    if (!fCachedBlendingInputDescSet) {
-        return nullptr;
-    }
-
-    write_input_desc_set(gpu,
-                         this->framebufferView()->imageView(),
-                         VK_IMAGE_LAYOUT_GENERAL,
-                         *fCachedBlendingInputDescSet->descriptorSet());
-
-    return fCachedBlendingInputDescSet;
-}
-
-gr_rp<const GrVkDescriptorSet> GrVkAttachment::inputDescSetForMSAALoad(GrVkGpu* gpu) {
-    if (!this->supportsInputAttachmentUsage()) {
-        return nullptr;
-    }
-    if (fCachedMSAALoadInputDescSet) {
-        return fCachedMSAALoadInputDescSet;
-    }
-
-    fCachedMSAALoadInputDescSet.reset(gpu->resourceProvider().getInputDescriptorSet());
-    if (!fCachedMSAALoadInputDescSet) {
-        return nullptr;
-    }
-
-    write_input_desc_set(gpu,
-                         this->framebufferView()->imageView(),
-                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                         *fCachedMSAALoadInputDescSet->descriptorSet());
-
-    return fCachedMSAALoadInputDescSet;
-}
-
-GrVkAttachment::~GrVkAttachment() {
-    // should have been released or abandoned first
-    SkASSERT(!fFramebufferView);
-    SkASSERT(!fTextureView);
-}
-
-void GrVkAttachment::release() {
-    this->releaseImage();
-    fFramebufferView.reset();
-    fTextureView.reset();
-    fCachedBlendingInputDescSet.reset();
-    fCachedMSAALoadInputDescSet.reset();
-}
-
-void GrVkAttachment::onRelease() {
-    this->release();
-    GrAttachment::onRelease();
-}
-
-void GrVkAttachment::onAbandon() {
-    this->release();
-    GrAttachment::onAbandon();
-}
-
-GrVkGpu* GrVkAttachment::getVkGpu() const {
-    SkASSERT(!this->wasDestroyed());
-    return static_cast<GrVkGpu*>(this->getGpu());
-}
diff --git a/src/gpu/vk/GrVkAttachment.h b/src/gpu/vk/GrVkAttachment.h
deleted file mode 100644
index 6b22a87..0000000
--- a/src/gpu/vk/GrVkAttachment.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrVkAttachment_DEFINED
-#define GrVkAttachment_DEFINED
-
-#include "include/gpu/vk/GrVkTypes.h"
-#include "src/gpu/GrAttachment.h"
-#include "src/gpu/GrRefCnt.h"
-#include "src/gpu/vk/GrVkDescriptorSet.h"
-#include "src/gpu/vk/GrVkImage.h"
-
-class GrVkImageView;
-class GrVkGpu;
-
-class GrVkAttachment : public GrAttachment, public GrVkImage {
-public:
-    static sk_sp<GrVkAttachment> MakeStencil(GrVkGpu* gpu,
-                                             SkISize dimensions,
-                                             int sampleCnt,
-                                             VkFormat format);
-
-    static sk_sp<GrVkAttachment> MakeMSAA(GrVkGpu* gpu,
-                                          SkISize dimensions,
-                                          int numSamples,
-                                          VkFormat format,
-                                          GrProtected isProtected);
-
-    static sk_sp<GrVkAttachment> MakeTexture(GrVkGpu* gpu,
-                                             SkISize dimensions,
-                                             VkFormat format,
-                                             uint32_t mipLevels,
-                                             GrRenderable renderable,
-                                             int numSamples,
-                                             SkBudgeted budgeted,
-                                             GrProtected isProtected);
-
-    static sk_sp<GrVkAttachment> MakeWrapped(GrVkGpu* gpu,
-                                             SkISize dimensions,
-                                             const GrVkImageInfo&,
-                                             sk_sp<GrBackendSurfaceMutableStateImpl>,
-                                             UsageFlags attachmentUsages,
-                                             GrWrapOwnership,
-                                             GrWrapCacheable,
-                                             bool forSecondaryCB = false);
-
-    ~GrVkAttachment() override;
-
-    GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
-
-    const GrManagedResource* imageResource() const { return this->resource(); }
-    const GrVkImageView* framebufferView() const { return fFramebufferView.get(); }
-    const GrVkImageView* textureView() const { return fTextureView.get(); }
-
-    // So that we don't need to rewrite descriptor sets each time, we keep cached input descriptor
-    // sets on the attachment and simply reuse those descriptor sets for this attachment only. These
-    // calls will fail if the attachment does not support being used as an input attachment. These
-    // calls do not ref the GrVkDescriptorSet so they called will need to manually ref them if they
-    // need to be kept alive.
-    gr_rp<const GrVkDescriptorSet> inputDescSetForBlending(GrVkGpu* gpu);
-    // Input descripotr set used when needing to read a resolve attachment to load data into a
-    // discardable msaa attachment.
-    gr_rp<const GrVkDescriptorSet> inputDescSetForMSAALoad(GrVkGpu* gpu);
-
-protected:
-    void onRelease() override;
-    void onAbandon() override;
-
-private:
-    static sk_sp<GrVkAttachment> Make(GrVkGpu* gpu,
-                                      SkISize dimensions,
-                                      UsageFlags attachmentUsages,
-                                      int sampleCnt,
-                                      VkFormat format,
-                                      uint32_t mipLevels,
-                                      VkImageUsageFlags vkUsageFlags,
-                                      GrProtected isProtected,
-                                      SkBudgeted);
-
-    GrVkAttachment(GrVkGpu* gpu,
-                   SkISize dimensions,
-                   UsageFlags supportedUsages,
-                   const GrVkImageInfo&,
-                   sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-                   sk_sp<const GrVkImageView> framebufferView,
-                   sk_sp<const GrVkImageView> textureView,
-                   SkBudgeted);
-
-    GrVkAttachment(GrVkGpu* gpu,
-                   SkISize dimensions,
-                   UsageFlags supportedUsages,
-                   const GrVkImageInfo&,
-                   sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-                   sk_sp<const GrVkImageView> framebufferView,
-                   sk_sp<const GrVkImageView> textureView,
-                   GrBackendObjectOwnership,
-                   GrWrapCacheable,
-                   bool forSecondaryCB);
-
-    GrVkGpu* getVkGpu() const;
-
-    void release();
-
-    sk_sp<const GrVkImageView> fFramebufferView;
-    sk_sp<const GrVkImageView> fTextureView;
-
-    // Descriptor set used when this is used as an input attachment for reading the dst in blending.
-    gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet;
-    // Descriptor set used when this is used as an input attachment for loading an msaa attachment.
-    gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet;
-};
-
-#endif
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 1fb973a..9215dde 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -22,6 +22,7 @@
 #include "src/gpu/GrUtil.h"
 #include "src/gpu/SkGr.h"
 #include "src/gpu/vk/GrVkGpu.h"
+#include "src/gpu/vk/GrVkImage.h"
 #include "src/gpu/vk/GrVkInterface.h"
 #include "src/gpu/vk/GrVkRenderTarget.h"
 #include "src/gpu/vk/GrVkTexture.h"
@@ -1543,16 +1544,16 @@
         return SurfaceReadPixelsSupport::kUnsupported;
     }
     if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
-        auto texAttachment = tex->textureAttachment();
-        if (!texAttachment) {
+        auto texImage = tex->textureImage();
+        if (!texImage) {
             return SurfaceReadPixelsSupport::kUnsupported;
         }
         // We can't directly read from a VkImage that has a ycbcr sampler.
-        if (texAttachment->ycbcrConversionInfo().isValid()) {
+        if (texImage->ycbcrConversionInfo().isValid()) {
             return SurfaceReadPixelsSupport::kCopyToTexture2D;
         }
         // We can't directly read from a compressed format
-        if (GrVkFormatIsCompressed(texAttachment->imageFormat())) {
+        if (GrVkFormatIsCompressed(texImage->imageFormat())) {
             return SurfaceReadPixelsSupport::kCopyToTexture2D;
         }
         return SurfaceReadPixelsSupport::kSupported;
@@ -1581,12 +1582,12 @@
     }
     // We can't write to a texture that has a ycbcr sampler.
     if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
-        auto texAttachment = tex->textureAttachment();
-        if (!texAttachment) {
+        auto texImage = tex->textureImage();
+        if (!texImage) {
             return false;
         }
         // We can't directly read from a VkImage that has a ycbcr sampler.
-        if (texAttachment->ycbcrConversionInfo().isValid()) {
+        if (texImage->ycbcrConversionInfo().isValid()) {
             return false;
         }
     }
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 981e465..8391d6a 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -10,7 +10,6 @@
 
 #include "include/gpu/vk/GrVkTypes.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/vk/GrVkAttachment.h"
 
 class GrShaderCaps;
 class GrVkExtensions;
diff --git a/src/gpu/vk/GrVkFramebuffer.cpp b/src/gpu/vk/GrVkFramebuffer.cpp
index dfbe9d2..79c31a3 100644
--- a/src/gpu/vk/GrVkFramebuffer.cpp
+++ b/src/gpu/vk/GrVkFramebuffer.cpp
@@ -7,9 +7,9 @@
 
 #include "src/gpu/vk/GrVkFramebuffer.h"
 
-#include "src/gpu/vk/GrVkAttachment.h"
 #include "src/gpu/vk/GrVkCommandBuffer.h"
 #include "src/gpu/vk/GrVkGpu.h"
+#include "src/gpu/vk/GrVkImage.h"
 #include "src/gpu/vk/GrVkImageView.h"
 #include "src/gpu/vk/GrVkRenderPass.h"
 
@@ -17,9 +17,9 @@
         GrVkGpu* gpu,
         SkISize dimensions,
         sk_sp<const GrVkRenderPass> compatibleRenderPass,
-        GrVkAttachment* colorAttachment,
-        GrVkAttachment* resolveAttachment,
-        GrVkAttachment* stencilAttachment,
+        GrVkImage* colorAttachment,
+        GrVkImage* resolveAttachment,
+        GrVkImage* stencilAttachment,
         GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle) {
     // At the very least we need a renderPass and a colorAttachment
     SkASSERT(compatibleRenderPass);
@@ -63,9 +63,9 @@
 
 GrVkFramebuffer::GrVkFramebuffer(const GrVkGpu* gpu,
                                  VkFramebuffer framebuffer,
-                                 sk_sp<GrVkAttachment> colorAttachment,
-                                 sk_sp<GrVkAttachment> resolveAttachment,
-                                 sk_sp<GrVkAttachment> stencilAttachment,
+                                 sk_sp<GrVkImage> colorAttachment,
+                                 sk_sp<GrVkImage> resolveAttachment,
+                                 sk_sp<GrVkImage> stencilAttachment,
                                  sk_sp<const GrVkRenderPass> compatibleRenderPass,
                                  GrVkResourceProvider::CompatibleRPHandle compatibleRPHandle)
         : GrVkManagedResource(gpu)
@@ -79,7 +79,7 @@
 }
 
 GrVkFramebuffer::GrVkFramebuffer(const GrVkGpu* gpu,
-                                 sk_sp<GrVkAttachment> colorAttachment,
+                                 sk_sp<GrVkImage> colorAttachment,
                                  sk_sp<const GrVkRenderPass> renderPass,
                                  std::unique_ptr<GrVkSecondaryCommandBuffer> externalCommandBuffer)
         : GrVkManagedResource(gpu)
diff --git a/src/gpu/vk/GrVkFramebuffer.h b/src/gpu/vk/GrVkFramebuffer.h
index cf774cb..623fe78 100644
--- a/src/gpu/vk/GrVkFramebuffer.h
+++ b/src/gpu/vk/GrVkFramebuffer.h
@@ -15,8 +15,8 @@
 
 #include <cinttypes>
 
-class GrVkAttachment;
 class GrVkGpu;
+class GrVkImage;
 class GrVkImageView;
 class GrVkRenderPass;
 
@@ -25,14 +25,14 @@
     static sk_sp<const GrVkFramebuffer> Make(GrVkGpu* gpu,
                                              SkISize dimensions,
                                              sk_sp<const GrVkRenderPass> compatibleRenderPass,
-                                             GrVkAttachment* colorAttachment,
-                                             GrVkAttachment* resolveAttachment,
-                                             GrVkAttachment* stencilAttachment,
+                                             GrVkImage* colorAttachment,
+                                             GrVkImage* resolveAttachment,
+                                             GrVkImage* stencilAttachment,
                                              GrVkResourceProvider::CompatibleRPHandle);
 
     // Used for wrapped external secondary command buffers
     GrVkFramebuffer(const GrVkGpu* gpu,
-                    sk_sp<GrVkAttachment> colorAttachment,
+                    sk_sp<GrVkImage> colorAttachment,
                     sk_sp<const GrVkRenderPass> renderPass,
                     std::unique_ptr<GrVkSecondaryCommandBuffer>);
 
@@ -70,16 +70,16 @@
         return fCompatibleRenderPassHandle;
     }
 
-    GrVkAttachment* colorAttachment() { return fColorAttachment.get(); }
-    GrVkAttachment* resolveAttachment() { return fResolveAttachment.get(); }
-    GrVkAttachment* stencilAttachment() { return fStencilAttachment.get(); }
+    GrVkImage* colorAttachment() { return fColorAttachment.get(); }
+    GrVkImage* resolveAttachment() { return fResolveAttachment.get(); }
+    GrVkImage* stencilAttachment() { return fStencilAttachment.get(); }
 
 private:
     GrVkFramebuffer(const GrVkGpu* gpu,
                     VkFramebuffer framebuffer,
-                    sk_sp<GrVkAttachment> colorAttachment,
-                    sk_sp<GrVkAttachment> resolveAttachment,
-                    sk_sp<GrVkAttachment> stencilAttachment,
+                    sk_sp<GrVkImage> colorAttachment,
+                    sk_sp<GrVkImage> resolveAttachment,
+                    sk_sp<GrVkImage> stencilAttachment,
                     sk_sp<const GrVkRenderPass> compatibleRenderPass,
                     GrVkResourceProvider::CompatibleRPHandle);
 
@@ -90,9 +90,9 @@
 
     VkFramebuffer  fFramebuffer = VK_NULL_HANDLE;
 
-    sk_sp<GrVkAttachment> fColorAttachment;
-    sk_sp<GrVkAttachment> fResolveAttachment;
-    sk_sp<GrVkAttachment> fStencilAttachment;
+    sk_sp<GrVkImage> fColorAttachment;
+    sk_sp<GrVkImage> fResolveAttachment;
+    sk_sp<GrVkImage> fStencilAttachment;
 
     sk_sp<const GrVkRenderPass> fCompatibleRenderPass;
     GrVkResourceProvider::CompatibleRPHandle fCompatibleRenderPassHandle;
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 509dcdf..9dcc553 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -486,40 +486,40 @@
     if (!texture) {
         return false;
     }
-    GrVkAttachment* texAttachment = texture->textureAttachment();
+    GrVkImage* texImage = texture->textureImage();
 
     // Make sure we have at least the base level
     if (!mipLevelCount || !texels[0].fPixels) {
         return false;
     }
 
-    SkASSERT(!GrVkFormatIsCompressed(texAttachment->imageFormat()));
+    SkASSERT(!GrVkFormatIsCompressed(texImage->imageFormat()));
     bool success = false;
-    bool linearTiling = texAttachment->isLinearTiled();
+    bool linearTiling = texImage->isLinearTiled();
     if (linearTiling) {
         if (mipLevelCount > 1) {
             SkDebugf("Can't upload mipmap data to linear tiled texture");
             return false;
         }
-        if (VK_IMAGE_LAYOUT_PREINITIALIZED != texAttachment->currentLayout()) {
+        if (VK_IMAGE_LAYOUT_PREINITIALIZED != texImage->currentLayout()) {
             // Need to change the layout to general in order to perform a host write
-            texAttachment->setImageLayout(this,
-                                          VK_IMAGE_LAYOUT_GENERAL,
-                                          VK_ACCESS_HOST_WRITE_BIT,
-                                          VK_PIPELINE_STAGE_HOST_BIT,
-                                          false);
+            texImage->setImageLayout(this,
+                                     VK_IMAGE_LAYOUT_GENERAL,
+                                     VK_ACCESS_HOST_WRITE_BIT,
+                                     VK_PIPELINE_STAGE_HOST_BIT,
+                                     false);
             if (!this->submitCommandBuffer(kForce_SyncQueue)) {
                 return false;
             }
         }
-        success = this->uploadTexDataLinear(texAttachment,
+        success = this->uploadTexDataLinear(texImage,
                                             rect,
                                             srcColorType,
                                             texels[0].fPixels,
                                             texels[0].fRowBytes);
     } else {
-        SkASSERT(mipLevelCount <= (int)texAttachment->mipLevels());
-        success = this->uploadTexDataOptimal(texAttachment,
+        SkASSERT(mipLevelCount <= (int)texImage->mipLevels());
+        success = this->uploadTexDataOptimal(texImage,
                                              rect,
                                              srcColorType,
                                              texels,
@@ -530,7 +530,7 @@
     }
 
     if (prepForTexSampling) {
-        texAttachment->setImageLayout(this,
+        texImage->setImageLayout(this,
                                       VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                                       VK_ACCESS_SHADER_READ_BIT,
                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
@@ -564,8 +564,8 @@
     if (!tex) {
         return false;
     }
-    GrVkAttachment* vkTex = tex->textureAttachment();
-    VkFormat format = vkTex->imageFormat();
+    GrVkImage* vkImage = tex->textureImage();
+    VkFormat format = vkImage->imageFormat();
 
     // Can't transfer compressed data
     SkASSERT(!GrVkFormatIsCompressed(format));
@@ -592,18 +592,18 @@
     region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 };
 
     // Change layout of our target so it can be copied to
-    vkTex->setImageLayout(this,
-                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                          VK_ACCESS_TRANSFER_WRITE_BIT,
-                          VK_PIPELINE_STAGE_TRANSFER_BIT,
-                          false);
+    vkImage->setImageLayout(this,
+                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                            VK_ACCESS_TRANSFER_WRITE_BIT,
+                            VK_PIPELINE_STAGE_TRANSFER_BIT,
+                            false);
 
     const GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get());
 
     // Copy the buffer to the image.
     this->currentCommandBuffer()->copyBufferToImage(this,
                                                     vkBuffer->vkBuffer(),
-                                                    vkTex,
+                                                    vkImage,
                                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                     1,
                                                     &region);
@@ -642,7 +642,7 @@
         srcImage = rt->nonMSAAAttachment();
     } else {
         SkASSERT(surface->asTexture());
-        srcImage = static_cast<GrVkTexture*>(surface->asTexture())->textureAttachment();
+        srcImage = static_cast<GrVkTexture*>(surface->asTexture())->textureImage();
     }
 
     VkFormat format = srcImage->imageFormat();
@@ -701,7 +701,7 @@
     GrRenderTarget* dstRT = dst->asRenderTarget();
     GrTexture* dstTex = dst->asTexture();
     if (dstTex) {
-        dstImage = static_cast<GrVkTexture*>(dstTex)->textureAttachment();
+        dstImage = static_cast<GrVkTexture*>(dstTex)->textureImage();
     } else {
         SkASSERT(dst->asRenderTarget());
         dstImage = static_cast<GrVkRenderTarget*>(dstRT)->nonMSAAAttachment();
@@ -739,21 +739,21 @@
                        SkIPoint::Make(resolveRect.x(), resolveRect.y()));
 }
 
-bool GrVkGpu::uploadTexDataLinear(GrVkAttachment* texAttachment,
+bool GrVkGpu::uploadTexDataLinear(GrVkImage* texImage,
                                   SkIRect rect,
                                   GrColorType dataColorType,
                                   const void* data,
                                   size_t rowBytes) {
     SkASSERT(data);
-    SkASSERT(texAttachment->isLinearTiled());
+    SkASSERT(texImage->isLinearTiled());
 
-    SkASSERT(SkIRect::MakeSize(texAttachment->dimensions()).contains(rect));
+    SkASSERT(SkIRect::MakeSize(texImage->dimensions()).contains(rect));
 
     size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
     size_t trimRowBytes = rect.width() * bpp;
 
-    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == texAttachment->currentLayout() ||
-             VK_IMAGE_LAYOUT_GENERAL == texAttachment->currentLayout());
+    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == texImage->currentLayout() ||
+             VK_IMAGE_LAYOUT_GENERAL == texImage->currentLayout());
     const VkImageSubresource subres = {
         VK_IMAGE_ASPECT_COLOR_BIT,
         0,  // mipLevel
@@ -764,11 +764,11 @@
     const GrVkInterface* interface = this->vkInterface();
 
     GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
-                                                    texAttachment->image(),
+                                                    texImage->image(),
                                                     &subres,
                                                     &layout));
 
-    const GrVkAlloc& alloc = texAttachment->alloc();
+    const GrVkAlloc& alloc = texImage->alloc();
     if (VK_NULL_HANDLE == alloc.fMemory) {
         return false;
     }
@@ -853,7 +853,7 @@
     return bufferSize;
 }
 
-bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment,
+bool GrVkGpu::uploadTexDataOptimal(GrVkImage* texImage,
                                    SkIRect rect,
                                    GrColorType dataColorType,
                                    const GrMipLevel texels[],
@@ -862,19 +862,19 @@
         return false;
     }
 
-    SkASSERT(!texAttachment->isLinearTiled());
+    SkASSERT(!texImage->isLinearTiled());
     // The assumption is either that we have no mipmaps, or that our rect is the entire texture
-    SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(texAttachment->dimensions()));
+    SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(texImage->dimensions()));
 
     // We assume that if the texture has mip levels, we either upload to all the levels or just the
     // first.
-    SkASSERT(mipLevelCount == 1 || mipLevelCount == (int)texAttachment->mipLevels());
+    SkASSERT(mipLevelCount == 1 || mipLevelCount == (int)texImage->mipLevels());
 
     SkASSERT(!rect.isEmpty());
 
-    SkASSERT(this->vkCaps().surfaceSupportsWritePixels(texAttachment));
+    SkASSERT(this->vkCaps().surfaceSupportsWritePixels(texImage));
 
-    SkASSERT(this->vkCaps().isVkFormatTexturable(texAttachment->imageFormat()));
+    SkASSERT(this->vkCaps().isVkFormatTexturable(texImage->imageFormat()));
     size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
 
     // texels is const.
@@ -944,11 +944,11 @@
     }
 
     // Change layout of our target so it can be copied to
-    texAttachment->setImageLayout(this,
-                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                  VK_ACCESS_TRANSFER_WRITE_BIT,
-                                  VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                  false);
+    texImage->setImageLayout(this,
+                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                             VK_ACCESS_TRANSFER_WRITE_BIT,
+                             VK_PIPELINE_STAGE_TRANSFER_BIT,
+                             false);
 
     // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer
     // because we don't need the command buffer to ref the buffer here. The reason being is that
@@ -958,7 +958,7 @@
     GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(slice.fBuffer);
     this->currentCommandBuffer()->copyBufferToImage(this,
                                                     vkBuffer->vkBuffer(),
-                                                    texAttachment,
+                                                    texImage,
                                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                     regions.count(),
                                                     regions.begin());
@@ -967,7 +967,7 @@
 
 // It's probably possible to roll this into uploadTexDataOptimal,
 // but for now it's easier to maintain as a separate entity.
-bool GrVkGpu::uploadTexDataCompressed(GrVkAttachment* uploadTexture,
+bool GrVkGpu::uploadTexDataCompressed(GrVkImage* uploadTexture,
                                       SkImage::CompressionType compression, VkFormat vkFormat,
                                       SkISize dimensions, GrMipmapped mipMapped,
                                       const void* data, size_t dataSize) {
@@ -1071,7 +1071,7 @@
         }
         SkSTArray<1, VkImageSubresourceRange> ranges;
         bool inRange = false;
-        GrVkImage* texImage = tex->textureAttachment();
+        GrVkImage* texImage = tex->textureImage();
         for (uint32_t i = 0; i < texImage->mipLevels(); ++i) {
             if (levelClearMask & (1U << i)) {
                 if (inRange) {
@@ -1124,7 +1124,7 @@
     }
 
     SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
-    if (!this->uploadTexDataCompressed(tex->textureAttachment(), compression, pixelFormat,
+    if (!this->uploadTexDataCompressed(tex->textureImage(), compression, pixelFormat,
                                        dimensions, mipMapped, data, dataSize)) {
         return nullptr;
     }
@@ -1377,7 +1377,7 @@
 bool GrVkGpu::loadMSAAFromResolve(GrVkCommandBuffer* commandBuffer,
                                   const GrVkRenderPass& renderPass,
                                   GrAttachment* dst,
-                                  GrVkAttachment* src,
+                                  GrVkImage* src,
                                   const SkIRect& srcRect) {
     return fMSAALoadManager.loadMSAAFromResolve(this, commandBuffer, renderPass, dst, src, srcRect);
 }
@@ -1386,7 +1386,7 @@
     if (!this->currentCommandBuffer()) {
         return false;
     }
-    auto* vkTex = static_cast<GrVkTexture*>(tex)->textureAttachment();
+    auto* vkTex = static_cast<GrVkTexture*>(tex)->textureImage();
     // don't do anything for linearly tiled textures (can't have mipmaps)
     if (vkTex->isLinearTiled()) {
         SkDebugf("Trying to create mipmap for linear tiled texture");
@@ -1480,7 +1480,7 @@
     VkFormat sFmt = this->vkCaps().preferredStencilFormat();
 
     fStats.incStencilAttachmentCreates();
-    return GrVkAttachment::MakeStencil(this, dimensions, numStencilSamples, sFmt);
+    return GrVkImage::MakeStencil(this, dimensions, numStencilSamples, sFmt);
 }
 
 sk_sp<GrAttachment> GrVkGpu::makeMSAAAttachment(SkISize dimensions,
@@ -1493,7 +1493,7 @@
     SkASSERT(this->vkCaps().isFormatRenderable(pixelFormat, numSamples));
 
     fStats.incMSAAAttachmentCreates();
-    return GrVkAttachment::MakeMSAA(this, dimensions, numSamples, pixelFormat, isProtected);
+    return GrVkImage::MakeMSAA(this, dimensions, numSamples, pixelFormat, isProtected);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1602,16 +1602,18 @@
     if (!texture) {
         return false;
     }
-    GrVkAttachment* texAttachment = texture->textureAttachment();
+    GrVkImage* texImage = texture->textureImage();
 
     GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer();
     if (!cmdBuffer) {
         return false;
     }
 
-    texAttachment->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                  VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                  false);
+    texImage->setImageLayout(this,
+                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                             VK_ACCESS_TRANSFER_WRITE_BIT,
+                             VK_PIPELINE_STAGE_TRANSFER_BIT,
+                             false);
 
     // CmdClearColorImage doesn't work for compressed formats
     SkASSERT(!GrVkFormatIsCompressed(info.fFormat));
@@ -1629,11 +1631,11 @@
     range.baseMipLevel = 0;
     range.layerCount = 1;
     range.levelCount = info.fLevelCount;
-    cmdBuffer->clearColorImage(this, texAttachment, &vkColor, 1, &range);
+    cmdBuffer->clearColorImage(this, texImage, &vkColor, 1, &range);
 
     // Change image layout to shader read since if we use this texture as a borrowed
     // texture within Ganesh we require that its layout be set to that
-    texAttachment->setImageLayout(this, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+    texImage->setImageLayout(this, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                                   VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
                                   false);
 
@@ -1708,12 +1710,12 @@
     if (!cmdBuffer) {
         return false;
     }
-    GrVkAttachment* attachment = texture->textureAttachment();
-    attachment->setImageLayout(this,
-                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                               VK_ACCESS_TRANSFER_WRITE_BIT,
-                               VK_PIPELINE_STAGE_TRANSFER_BIT,
-                               false);
+    GrVkImage* image = texture->textureImage();
+    image->setImageLayout(this,
+                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                          VK_ACCESS_TRANSFER_WRITE_BIT,
+                          VK_PIPELINE_STAGE_TRANSFER_BIT,
+                          false);
 
     SkImage::CompressionType compression =
             GrBackendFormatToCompressionType(backendTexture.getBackendFormat());
@@ -1745,18 +1747,18 @@
     // every upload in the frame.
     cmdBuffer->copyBufferToImage(this,
                                  static_cast<GrVkBuffer*>(slice.fBuffer)->vkBuffer(),
-                                 attachment,
-                                 attachment->currentLayout(),
+                                 image,
+                                 image->currentLayout(),
                                  regions.count(),
                                  regions.begin());
 
     // Change image layout to shader read since if we use this texture as a borrowed
     // texture within Ganesh we require that its layout be set to that
-    attachment->setImageLayout(this,
-                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                               VK_ACCESS_SHADER_READ_BIT,
-                               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
-                               false);
+    image->setImageLayout(this,
+                          VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                          VK_ACCESS_SHADER_READ_BIT,
+                          VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+                          false);
 
     if (finishedCallback) {
         this->addFinishedCallback(std::move(finishedCallback));
@@ -1798,10 +1800,14 @@
                                      const GrVkSharedImageInfo& newInfo,
                                      GrBackendSurfaceMutableState* previousState,
                                      sk_sp<GrRefCntedCallback> finishedCallback) {
-    sk_sp<GrVkAttachment> texture = GrVkAttachment::MakeWrapped(
-            this, dimensions, info, std::move(currentState),
-           GrVkAttachment::UsageFlags::kColorAttachment, kBorrow_GrWrapOwnership,
-           GrWrapCacheable::kNo, /*forSecondaryCB=*/false);
+    sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(this,
+                                                      dimensions,
+                                                      info,
+                                                      std::move(currentState),
+                                                      GrVkImage::UsageFlags::kColorAttachment,
+                                                      kBorrow_GrWrapOwnership,
+                                                      GrWrapCacheable::kNo,
+                                                      /*forSecondaryCB=*/false);
     SkASSERT(texture);
     if (!texture) {
         return false;
@@ -1857,19 +1863,19 @@
         dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
         dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
     }
-    GrVkAttachment* colorAttachment = vkRT->colorAttachment();
+    GrVkImage* image = vkRT->colorAttachment();
     VkImageMemoryBarrier barrier;
     barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
     barrier.pNext = nullptr;
     barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
     barrier.dstAccessMask = dstAccess;
-    barrier.oldLayout = colorAttachment->currentLayout();
+    barrier.oldLayout = image->currentLayout();
     barrier.newLayout = barrier.oldLayout;
     barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-    barrier.image = colorAttachment->image();
-    barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, colorAttachment->mipLevels(), 0, 1};
-    this->addImageMemoryBarrier(colorAttachment->resource(),
+    barrier.image = image->image();
+    barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, image->mipLevels(), 0, 1};
+    this->addImageMemoryBarrier(image->resource(),
                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
                                 dstStage, true, &barrier);
 }
@@ -2055,7 +2061,7 @@
         for (GrSurfaceProxy* proxy : proxies) {
             SkASSERT(proxy->isInstantiated());
             if (GrTexture* tex = proxy->peekTexture()) {
-                image = static_cast<GrVkTexture*>(tex)->textureAttachment();
+                image = static_cast<GrVkTexture*>(tex)->textureImage();
             } else {
                 GrRenderTarget* rt = proxy->peekRenderTarget();
                 SkASSERT(rt);
@@ -2121,8 +2127,8 @@
 
 void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
                                      GrSurface* src,
-                                     GrVkAttachment* dstAttachment,
-                                     GrVkAttachment* srcAttachment,
+                                     GrVkImage* dstImage,
+                                     GrVkImage* srcImage,
                                      const SkIRect& srcRect,
                                      const SkIPoint& dstPoint) {
     if (!this->currentCommandBuffer()) {
@@ -2130,11 +2136,11 @@
     }
 
 #ifdef SK_DEBUG
-    int dstSampleCnt = dstAttachment->numSamples();
-    int srcSampleCnt = srcAttachment->numSamples();
-    bool dstHasYcbcr = dstAttachment->ycbcrConversionInfo().isValid();
-    bool srcHasYcbcr = srcAttachment->ycbcrConversionInfo().isValid();
-    VkFormat dstFormat = dstAttachment->imageFormat();
+    int dstSampleCnt = dstImage->numSamples();
+    int srcSampleCnt = srcImage->numSamples();
+    bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
+    bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
+    VkFormat dstFormat = dstImage->imageFormat();
     VkFormat srcFormat;
     SkAssertResult(dst->backendFormat().asVkFormat(&srcFormat));
     SkASSERT(this->vkCaps().canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr,
@@ -2147,17 +2153,17 @@
 
     // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
     // the cache is flushed since it is only being written to.
-    dstAttachment->setImageLayout(this,
-                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                  VK_ACCESS_TRANSFER_WRITE_BIT,
-                                  VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                  false);
+    dstImage->setImageLayout(this,
+                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                             VK_ACCESS_TRANSFER_WRITE_BIT,
+                             VK_PIPELINE_STAGE_TRANSFER_BIT,
+                             false);
 
-    srcAttachment->setImageLayout(this,
-                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                                  VK_ACCESS_TRANSFER_READ_BIT,
-                                  VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                  false);
+    srcImage->setImageLayout(this,
+                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                             VK_ACCESS_TRANSFER_READ_BIT,
+                             VK_PIPELINE_STAGE_TRANSFER_BIT,
+                             false);
 
     VkImageCopy copyRegion;
     memset(&copyRegion, 0, sizeof(VkImageCopy));
@@ -2170,9 +2176,9 @@
     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src));
     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst));
     this->currentCommandBuffer()->copyImage(this,
-                                            srcAttachment,
+                                            srcImage,
                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                                            dstAttachment,
+                                            dstImage,
                                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                             1,
                                             &copyRegion);
@@ -2185,8 +2191,8 @@
 
 void GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
                                 GrSurface* src,
-                                GrVkAttachment* dstAttachment,
-                                GrVkAttachment* srcAttachment,
+                                GrVkImage* dstImage,
+                                GrVkImage* srcImage,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) {
     if (!this->currentCommandBuffer()) {
@@ -2194,20 +2200,20 @@
     }
 
 #ifdef SK_DEBUG
-    int dstSampleCnt = dstAttachment->numSamples();
-    int srcSampleCnt = srcAttachment->numSamples();
-    bool dstHasYcbcr = dstAttachment->ycbcrConversionInfo().isValid();
-    bool srcHasYcbcr = srcAttachment->ycbcrConversionInfo().isValid();
-    VkFormat dstFormat = dstAttachment->imageFormat();
+    int dstSampleCnt = dstImage->numSamples();
+    int srcSampleCnt = srcImage->numSamples();
+    bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
+    bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
+    VkFormat dstFormat = dstImage->imageFormat();
     VkFormat srcFormat;
     SkAssertResult(dst->backendFormat().asVkFormat(&srcFormat));
     SkASSERT(this->vkCaps().canCopyAsBlit(dstFormat,
                                           dstSampleCnt,
-                                          dstAttachment->isLinearTiled(),
+                                          dstImage->isLinearTiled(),
                                           dstHasYcbcr,
                                           srcFormat,
                                           srcSampleCnt,
-                                          srcAttachment->isLinearTiled(),
+                                          srcImage->isLinearTiled(),
                                           srcHasYcbcr));
 
 #endif
@@ -2216,17 +2222,17 @@
         return;
     }
 
-    dstAttachment->setImageLayout(this,
-                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                  VK_ACCESS_TRANSFER_WRITE_BIT,
-                                  VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                  false);
+    dstImage->setImageLayout(this,
+                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                             VK_ACCESS_TRANSFER_WRITE_BIT,
+                             VK_PIPELINE_STAGE_TRANSFER_BIT,
+                             false);
 
-    srcAttachment->setImageLayout(this,
-                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                                  VK_ACCESS_TRANSFER_READ_BIT,
-                                  VK_PIPELINE_STAGE_TRANSFER_BIT,
-                                  false);
+    srcImage->setImageLayout(this,
+                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                             VK_ACCESS_TRANSFER_READ_BIT,
+                             VK_PIPELINE_STAGE_TRANSFER_BIT,
+                             false);
 
     // Flip rect if necessary
     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, srcRect.width(),
@@ -2244,8 +2250,8 @@
     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src));
     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst));
     this->currentCommandBuffer()->blitImage(this,
-                                            *srcAttachment,
-                                            *dstAttachment,
+                                            *srcImage,
+                                            *dstImage,
                                             1,
                                             &blitRegion,
                                             VK_FILTER_NEAREST); // We never scale so any filter works here
@@ -2283,8 +2289,8 @@
         return false;
     }
 
-    GrVkAttachment* dstAttachment;
-    GrVkAttachment* srcAttachment;
+    GrVkImage* dstImage;
+    GrVkImage* srcImage;
     GrRenderTarget* dstRT = dst->asRenderTarget();
     if (dstRT) {
         GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
@@ -2295,15 +2301,15 @@
         // don't have to pick the resolve attachment. But in that case the resolve and color
         // attachments will be the same anyways.
         if (this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) {
-            dstAttachment = vkRT->resolveAttachment();
+            dstImage = vkRT->resolveAttachment();
         } else {
-            dstAttachment = vkRT->colorAttachment();
+            dstImage = vkRT->colorAttachment();
         }
     } else if (dst->asTexture()) {
-        dstAttachment = static_cast<GrVkTexture*>(dst->asTexture())->textureAttachment();
+        dstImage = static_cast<GrVkTexture*>(dst->asTexture())->textureImage();
     } else {
         // The surface in a GrAttachment already
-        dstAttachment = static_cast<GrVkAttachment*>(dst);
+        dstImage = static_cast<GrVkImage*>(dst);
     }
     GrRenderTarget* srcRT = src->asRenderTarget();
     if (srcRT) {
@@ -2312,26 +2318,26 @@
         // don't have to pick the resolve attachment. But in that case the resolve and color
         // attachments will be the same anyways.
         if (this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) {
-            srcAttachment = vkRT->resolveAttachment();
+            srcImage = vkRT->resolveAttachment();
         } else {
-            srcAttachment = vkRT->colorAttachment();
+            srcImage = vkRT->colorAttachment();
         }
     } else if (src->asTexture()) {
         SkASSERT(src->asTexture());
-        srcAttachment = static_cast<GrVkTexture*>(src->asTexture())->textureAttachment();
+        srcImage = static_cast<GrVkTexture*>(src->asTexture())->textureImage();
     } else {
         // The surface in a GrAttachment already
-        srcAttachment = static_cast<GrVkAttachment*>(src);
+        srcImage = static_cast<GrVkImage*>(src);
     }
 
-    VkFormat dstFormat = dstAttachment->imageFormat();
-    VkFormat srcFormat = srcAttachment->imageFormat();
+    VkFormat dstFormat = dstImage->imageFormat();
+    VkFormat srcFormat = srcImage->imageFormat();
 
-    int dstSampleCnt = dstAttachment->numSamples();
-    int srcSampleCnt = srcAttachment->numSamples();
+    int dstSampleCnt = dstImage->numSamples();
+    int srcSampleCnt = srcImage->numSamples();
 
-    bool dstHasYcbcr = dstAttachment->ycbcrConversionInfo().isValid();
-    bool srcHasYcbcr = srcAttachment->ycbcrConversionInfo().isValid();
+    bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
+    bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
 
     if (this->vkCaps().canCopyAsResolve(dstFormat, dstSampleCnt, dstHasYcbcr,
                                         srcFormat, srcSampleCnt, srcHasYcbcr)) {
@@ -2341,19 +2347,19 @@
 
     if (this->vkCaps().canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr,
                                     srcFormat, srcSampleCnt, srcHasYcbcr)) {
-        this->copySurfaceAsCopyImage(dst, src, dstAttachment, srcAttachment, srcRect, dstPoint);
+        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
         return true;
     }
 
     if (this->vkCaps().canCopyAsBlit(dstFormat,
                                      dstSampleCnt,
-                                     dstAttachment->isLinearTiled(),
+                                     dstImage->isLinearTiled(),
                                      dstHasYcbcr,
                                      srcFormat,
                                      srcSampleCnt,
-                                     srcAttachment->isLinearTiled(),
+                                     srcImage->isLinearTiled(),
                                      srcHasYcbcr)) {
-        this->copySurfaceAsBlit(dst, src, dstAttachment, srcAttachment, srcRect, dstPoint);
+        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
         return true;
     }
 
@@ -2385,7 +2391,7 @@
         }
         image = rt->nonMSAAAttachment();
     } else {
-        image = static_cast<GrVkTexture*>(surface->asTexture())->textureAttachment();
+        image = static_cast<GrVkTexture*>(surface->asTexture())->textureImage();
     }
 
     if (!image) {
@@ -2601,7 +2607,7 @@
 
 std::unique_ptr<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
     SkASSERT(texture);
-    GrVkAttachment* vkTexture = static_cast<GrVkTexture*>(texture)->textureAttachment();
+    GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage();
     vkTexture->setImageLayout(this,
                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                               VK_ACCESS_SHADER_READ_BIT,
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index c3b3f09..18439d5 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -138,7 +138,7 @@
     bool loadMSAAFromResolve(GrVkCommandBuffer* commandBuffer,
                              const GrVkRenderPass& renderPass,
                              GrAttachment* dst,
-                             GrVkAttachment* src,
+                             GrVkImage* src,
                              const SkIRect& srcRect);
 
     bool onRegenerateMipMapLevels(GrTexture* tex) override;
@@ -310,7 +310,7 @@
 
     GrOpsRenderPass* onGetOpsRenderPass(GrRenderTarget*,
                                         bool useMSAASurface,
-                                        GrAttachment*,
+                                        GrAttachment* stencil,
                                         GrSurfaceOrigin,
                                         const SkIRect&,
                                         const GrOpsRenderPass::LoadAndStoreInfo&,
@@ -337,15 +337,15 @@
 
     void copySurfaceAsCopyImage(GrSurface* dst,
                                 GrSurface* src,
-                                GrVkAttachment* dstAttachment,
-                                GrVkAttachment* srcAttachment,
+                                GrVkImage* dstImage,
+                                GrVkImage* srcImage,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint);
 
     void copySurfaceAsBlit(GrSurface* dst,
                            GrSurface* src,
-                           GrVkAttachment* dstAttachment,
-                           GrVkAttachment* srcAttachment,
+                           GrVkImage* dstImage,
+                           GrVkImage* srcImage,
                            const SkIRect& srcRect,
                            const SkIPoint& dstPoint);
 
@@ -353,17 +353,17 @@
                               const SkIPoint& dstPoint);
 
     // helpers for onCreateTexture and writeTexturePixels
-    bool uploadTexDataLinear(GrVkAttachment* tex,
+    bool uploadTexDataLinear(GrVkImage* tex,
                              SkIRect rect,
                              GrColorType colorType,
                              const void* data,
                              size_t rowBytes);
-    bool uploadTexDataOptimal(GrVkAttachment* tex,
+    bool uploadTexDataOptimal(GrVkImage* tex,
                               SkIRect rect,
                               GrColorType colorType,
                               const GrMipLevel texels[],
                               int mipLevelCount);
-    bool uploadTexDataCompressed(GrVkAttachment* tex, SkImage::CompressionType compression,
+    bool uploadTexDataCompressed(GrVkImage* tex, SkImage::CompressionType compression,
                                  VkFormat vkFormat, SkISize dimensions, GrMipmapped mipMapped,
                                  const void* data, size_t dataSize);
     void resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
diff --git a/src/gpu/vk/GrVkImage.cpp b/src/gpu/vk/GrVkImage.cpp
index 4fb1e8b..6a26410 100644
--- a/src/gpu/vk/GrVkImage.cpp
+++ b/src/gpu/vk/GrVkImage.cpp
@@ -5,40 +5,265 @@
  * found in the LICENSE file.
  */
 
-#include "src/gpu/vk/GrVkGpu.h"
 #include "src/gpu/vk/GrVkImage.h"
+
+#include "src/gpu/vk/GrVkGpu.h"
+#include "src/gpu/vk/GrVkImageView.h"
 #include "src/gpu/vk/GrVkMemory.h"
 #include "src/gpu/vk/GrVkTexture.h"
 #include "src/gpu/vk/GrVkUtil.h"
 
 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
 
-GrVkImage::GrVkImage(const GrVkGpu* gpu,
+sk_sp<GrVkImage> GrVkImage::MakeStencil(GrVkGpu* gpu,
+                                        SkISize dimensions,
+                                        int sampleCnt,
+                                        VkFormat format) {
+    VkImageUsageFlags vkUsageFlags =
+            VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    return GrVkImage::Make(gpu,
+                           dimensions,
+                           UsageFlags::kStencilAttachment,
+                           sampleCnt,
+                           format,
+                           /*mipLevels=*/1,
+                           vkUsageFlags,
+                           GrProtected::kNo,
+                           SkBudgeted::kYes);
+}
+
+sk_sp<GrVkImage> GrVkImage::MakeMSAA(GrVkGpu* gpu,
+                                     SkISize dimensions,
+                                     int numSamples,
+                                     VkFormat format,
+                                     GrProtected isProtected) {
+    SkASSERT(numSamples > 1);
+
+    VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+                                     VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    return GrVkImage::Make(gpu,
+                           dimensions,
+                           UsageFlags::kColorAttachment,
+                           numSamples,
+                           format,
+                           /*mipLevels=*/1,
+                           vkUsageFlags,
+                           isProtected,
+                           SkBudgeted::kYes);
+}
+
+sk_sp<GrVkImage> GrVkImage::MakeTexture(GrVkGpu* gpu,
+                                        SkISize dimensions,
+                                        VkFormat format,
+                                        uint32_t mipLevels,
+                                        GrRenderable renderable,
+                                        int numSamples,
+                                        SkBudgeted budgeted,
+                                        GrProtected isProtected) {
+    UsageFlags usageFlags = UsageFlags::kTexture;
+    VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    if (renderable == GrRenderable::kYes) {
+        usageFlags |= UsageFlags::kColorAttachment;
+        vkUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+        // We always make our render targets support being used as input attachments
+        vkUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+    }
+
+    return GrVkImage::Make(gpu,
+                           dimensions,
+                           usageFlags,
+                           numSamples,
+                           format,
+                           mipLevels,
+                           vkUsageFlags,
+                           isProtected,
+                           budgeted);
+}
+
+static bool make_views(GrVkGpu* gpu,
+                       const GrVkImageInfo& info,
+                       GrAttachment::UsageFlags attachmentUsages,
+                       sk_sp<const GrVkImageView>* framebufferView,
+                       sk_sp<const GrVkImageView>* textureView) {
+    GrVkImageView::Type viewType;
+    if (attachmentUsages & GrAttachment::UsageFlags::kStencilAttachment) {
+        // If we have stencil usage then we shouldn't have any other usages
+        SkASSERT(attachmentUsages == GrAttachment::UsageFlags::kStencilAttachment);
+        viewType = GrVkImageView::kStencil_Type;
+    } else {
+        viewType = GrVkImageView::kColor_Type;
+    }
+
+    if (SkToBool(attachmentUsages & GrAttachment::UsageFlags::kStencilAttachment) ||
+        SkToBool(attachmentUsages & GrAttachment::UsageFlags::kColorAttachment)) {
+        // Attachments can only have a mip level of 1
+        *framebufferView = GrVkImageView::Make(
+                gpu, info.fImage, info.fFormat, viewType, 1, info.fYcbcrConversionInfo);
+        if (!*framebufferView) {
+            return false;
+        }
+    }
+
+    if (attachmentUsages & GrAttachment::UsageFlags::kTexture) {
+        *textureView = GrVkImageView::Make(gpu,
+                                           info.fImage,
+                                           info.fFormat,
+                                           viewType,
+                                           info.fLevelCount,
+                                           info.fYcbcrConversionInfo);
+        if (!*textureView) {
+            return false;
+        }
+    }
+    return true;
+}
+
+sk_sp<GrVkImage> GrVkImage::Make(GrVkGpu* gpu,
+                                 SkISize dimensions,
+                                 UsageFlags attachmentUsages,
+                                 int sampleCnt,
+                                 VkFormat format,
+                                 uint32_t mipLevels,
+                                 VkImageUsageFlags vkUsageFlags,
+                                 GrProtected isProtected,
+                                 SkBudgeted budgeted) {
+    GrVkImage::ImageDesc imageDesc;
+    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
+    imageDesc.fFormat = format;
+    imageDesc.fWidth = dimensions.width();
+    imageDesc.fHeight = dimensions.height();
+    imageDesc.fLevels = mipLevels;
+    imageDesc.fSamples = sampleCnt;
+    imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
+    imageDesc.fUsageFlags = vkUsageFlags;
+    imageDesc.fIsProtected = isProtected;
+
+    GrVkImageInfo info;
+    if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
+        return nullptr;
+    }
+
+    sk_sp<const GrVkImageView> framebufferView;
+    sk_sp<const GrVkImageView> textureView;
+    if (!make_views(gpu, info, attachmentUsages, &framebufferView, &textureView)) {
+        GrVkImage::DestroyImageInfo(gpu, &info);
+        return nullptr;
+    }
+
+    sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(
+            new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily));
+    return sk_sp<GrVkImage>(new GrVkImage(gpu,
+                                          dimensions,
+                                          attachmentUsages,
+                                          info,
+                                          std::move(mutableState),
+                                          std::move(framebufferView),
+                                          std::move(textureView),
+                                          budgeted));
+}
+
+sk_sp<GrVkImage> GrVkImage::MakeWrapped(GrVkGpu* gpu,
+                                        SkISize dimensions,
+                                        const GrVkImageInfo& info,
+                                        sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+                                        UsageFlags attachmentUsages,
+                                        GrWrapOwnership ownership,
+                                        GrWrapCacheable cacheable,
+                                        bool forSecondaryCB) {
+    sk_sp<const GrVkImageView> framebufferView;
+    sk_sp<const GrVkImageView> textureView;
+    if (!forSecondaryCB) {
+        if (!make_views(gpu, info, attachmentUsages, &framebufferView, &textureView)) {
+            return nullptr;
+        }
+    }
+
+    GrBackendObjectOwnership backendOwnership = kBorrow_GrWrapOwnership == ownership
+                                                        ? GrBackendObjectOwnership::kBorrowed
+                                                        : GrBackendObjectOwnership::kOwned;
+
+    return sk_sp<GrVkImage>(new GrVkImage(gpu,
+                                          dimensions,
+                                          attachmentUsages,
+                                          info,
+                                          std::move(mutableState),
+                                          std::move(framebufferView),
+                                          std::move(textureView),
+                                          backendOwnership,
+                                          cacheable,
+                                          forSecondaryCB));
+}
+
+GrVkImage::GrVkImage(GrVkGpu* gpu,
+                     SkISize dimensions,
+                     UsageFlags supportedUsages,
                      const GrVkImageInfo& info,
                      sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-                     GrBackendObjectOwnership ownership,
-                     bool forSecondaryCB)
-        : fInfo(info)
+                     sk_sp<const GrVkImageView> framebufferView,
+                     sk_sp<const GrVkImageView> textureView,
+                     SkBudgeted budgeted)
+        : GrAttachment(gpu,
+                       dimensions,
+                       supportedUsages,
+                       info.fSampleCount,
+                       info.fLevelCount > 1 ? GrMipmapped::kYes : GrMipmapped::kNo,
+                       info.fProtected)
+        , fInfo(info)
         , fInitialQueueFamily(info.fCurrentQueueFamily)
         , fMutableState(std::move(mutableState))
+        , fFramebufferView(std::move(framebufferView))
+        , fTextureView(std::move(textureView))
+        , fIsBorrowed(false) {
+    this->init(gpu, false);
+    this->registerWithCache(budgeted);
+}
+
+GrVkImage::GrVkImage(GrVkGpu* gpu,
+                               SkISize dimensions,
+                               UsageFlags supportedUsages,
+                               const GrVkImageInfo& info,
+                               sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+                               sk_sp<const GrVkImageView> framebufferView,
+                               sk_sp<const GrVkImageView> textureView,
+                               GrBackendObjectOwnership ownership,
+                               GrWrapCacheable cacheable,
+                               bool forSecondaryCB)
+        : GrAttachment(gpu,
+                       dimensions,
+                       supportedUsages,
+                       info.fSampleCount,
+                       info.fLevelCount > 1 ? GrMipmapped::kYes : GrMipmapped::kNo,
+                       info.fProtected)
+        , fInfo(info)
+        , fInitialQueueFamily(info.fCurrentQueueFamily)
+        , fMutableState(std::move(mutableState))
+        , fFramebufferView(std::move(framebufferView))
+        , fTextureView(std::move(textureView))
         , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
+    this->init(gpu, forSecondaryCB);
+    this->registerWithCacheWrapped(cacheable);
+}
+
+void GrVkImage::init(GrVkGpu* gpu, bool forSecondaryCB) {
     SkASSERT(fMutableState->getImageLayout() == fInfo.fImageLayout);
     SkASSERT(fMutableState->getQueueFamilyIndex() == fInfo.fCurrentQueueFamily);
 #ifdef SK_DEBUG
-    if (info.fImageUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
-        SkASSERT(SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT));
+    if (fInfo.fImageUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+        SkASSERT(SkToBool(fInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT));
     } else {
-        SkASSERT(SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) &&
-                 SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
+        SkASSERT(SkToBool(fInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) &&
+                 SkToBool(fInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
     }
     // We can't transfer from the non graphics queue to the graphics queue since we can't
     // release the image from the original queue without having that queue. This limits us in terms
     // of the types of queue indices we can handle.
-    if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
-        info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
-        info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
-        if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
-            if (info.fCurrentQueueFamily != gpu->queueIndex()) {
+    if (fInfo.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
+        fInfo.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
+        fInfo.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
+        if (fInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
+            if (fInfo.fCurrentQueueFamily != gpu->queueIndex()) {
                 SkASSERT(false);
             }
         } else {
@@ -49,10 +274,10 @@
     if (forSecondaryCB) {
         fResource = nullptr;
     } else if (fIsBorrowed) {
-        fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
+        fResource = new BorrowedResource(gpu, fInfo.fImage, fInfo.fAlloc, fInfo.fImageTiling);
     } else {
-        SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
-        fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
+        SkASSERT(VK_NULL_HANDLE != fInfo.fAlloc.fMemory);
+        fResource = new Resource(gpu, fInfo.fImage, fInfo.fAlloc, fInfo.fImageTiling);
     }
 }
 
@@ -285,6 +510,8 @@
 GrVkImage::~GrVkImage() {
     // should have been released first
     SkASSERT(!fResource);
+    SkASSERT(!fFramebufferView);
+    SkASSERT(!fTextureView);
 }
 
 void GrVkImage::prepareForPresent(GrVkGpu* gpu) {
@@ -310,6 +537,20 @@
         fResource->unref();
         fResource = nullptr;
     }
+    fFramebufferView.reset();
+    fTextureView.reset();
+    fCachedBlendingInputDescSet.reset();
+    fCachedMSAALoadInputDescSet.reset();
+}
+
+void GrVkImage::onRelease() {
+    this->releaseImage();
+    GrAttachment::onRelease();
+}
+
+void GrVkImage::onAbandon() {
+    this->releaseImage();
+    GrAttachment::onAbandon();
 }
 
 void GrVkImage::setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper) {
@@ -328,6 +569,79 @@
     this->invokeReleaseProc();
 }
 
+static void write_input_desc_set(GrVkGpu* gpu,
+                                 VkImageView view,
+                                 VkImageLayout layout,
+                                 VkDescriptorSet descSet) {
+    VkDescriptorImageInfo imageInfo;
+    memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
+    imageInfo.sampler = VK_NULL_HANDLE;
+    imageInfo.imageView = view;
+    imageInfo.imageLayout = layout;
+
+    VkWriteDescriptorSet writeInfo;
+    memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
+    writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    writeInfo.pNext = nullptr;
+    writeInfo.dstSet = descSet;
+    writeInfo.dstBinding = GrVkUniformHandler::kInputBinding;
+    writeInfo.dstArrayElement = 0;
+    writeInfo.descriptorCount = 1;
+    writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+    writeInfo.pImageInfo = &imageInfo;
+    writeInfo.pBufferInfo = nullptr;
+    writeInfo.pTexelBufferView = nullptr;
+
+    GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
+}
+
+gr_rp<const GrVkDescriptorSet> GrVkImage::inputDescSetForBlending(GrVkGpu* gpu) {
+    if (!this->supportsInputAttachmentUsage()) {
+        return nullptr;
+    }
+    if (fCachedBlendingInputDescSet) {
+        return fCachedBlendingInputDescSet;
+    }
+
+    fCachedBlendingInputDescSet.reset(gpu->resourceProvider().getInputDescriptorSet());
+    if (!fCachedBlendingInputDescSet) {
+        return nullptr;
+    }
+
+    write_input_desc_set(gpu,
+                         this->framebufferView()->imageView(),
+                         VK_IMAGE_LAYOUT_GENERAL,
+                         *fCachedBlendingInputDescSet->descriptorSet());
+
+    return fCachedBlendingInputDescSet;
+}
+
+gr_rp<const GrVkDescriptorSet> GrVkImage::inputDescSetForMSAALoad(GrVkGpu* gpu) {
+    if (!this->supportsInputAttachmentUsage()) {
+        return nullptr;
+    }
+    if (fCachedMSAALoadInputDescSet) {
+        return fCachedMSAALoadInputDescSet;
+    }
+
+    fCachedMSAALoadInputDescSet.reset(gpu->resourceProvider().getInputDescriptorSet());
+    if (!fCachedMSAALoadInputDescSet) {
+        return nullptr;
+    }
+
+    write_input_desc_set(gpu,
+                         this->framebufferView()->imageView(),
+                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                         *fCachedMSAALoadInputDescSet->descriptorSet());
+
+    return fCachedMSAALoadInputDescSet;
+}
+
+GrVkGpu* GrVkImage::getVkGpu() const {
+    SkASSERT(!this->wasDestroyed());
+    return static_cast<GrVkGpu*>(this->getGpu());
+}
+
 #if GR_TEST_UTILS
 void GrVkImage::setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu) {
     fMutableState->setQueueFamilyIndex(gpu->queueIndex());
diff --git a/src/gpu/vk/GrVkImage.h b/src/gpu/vk/GrVkImage.h
index 27d397f..789fa16 100644
--- a/src/gpu/vk/GrVkImage.h
+++ b/src/gpu/vk/GrVkImage.h
@@ -13,27 +13,53 @@
 #include "include/gpu/vk/GrVkTypes.h"
 #include "include/private/GrTypesPriv.h"
 #include "include/private/GrVkTypesPriv.h"
+#include "src/gpu/GrAttachment.h"
 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
 #include "src/gpu/GrManagedResource.h"
+#include "src/gpu/GrRefCnt.h"
 #include "src/gpu/GrTexture.h"
+#include "src/gpu/vk/GrVkDescriptorSet.h"
 
 #include <cinttypes>
 
 class GrVkGpu;
-class GrVkTexture;
+class GrVkImageView;
 
-class GrVkImage : SkNoncopyable {
+class GrVkImage : public GrAttachment {
 private:
     class Resource;
 
 public:
-    GrVkImage(const GrVkGpu* gpu,
-              const GrVkImageInfo& info,
-              sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
-              GrBackendObjectOwnership ownership,
-              bool forSecondaryCB = false);
+    static sk_sp<GrVkImage> MakeStencil(GrVkGpu* gpu,
+                                        SkISize dimensions,
+                                        int sampleCnt,
+                                        VkFormat format);
 
-    virtual ~GrVkImage();
+    static sk_sp<GrVkImage> MakeMSAA(GrVkGpu* gpu,
+                                     SkISize dimensions,
+                                     int numSamples,
+                                     VkFormat format,
+                                     GrProtected isProtected);
+
+    static sk_sp<GrVkImage> MakeTexture(GrVkGpu* gpu,
+                                        SkISize dimensions,
+                                        VkFormat format,
+                                        uint32_t mipLevels,
+                                        GrRenderable renderable,
+                                        int numSamples,
+                                        SkBudgeted budgeted,
+                                        GrProtected isProtected);
+
+    static sk_sp<GrVkImage> MakeWrapped(GrVkGpu* gpu,
+                                        SkISize dimensions,
+                                        const GrVkImageInfo&,
+                                        sk_sp<GrBackendSurfaceMutableStateImpl>,
+                                        UsageFlags attachmentUsages,
+                                        GrWrapOwnership,
+                                        GrWrapCacheable,
+                                        bool forSecondaryCB = false);
+
+    ~GrVkImage() override;
 
     VkImage image() const {
         // Should only be called when we have a real fResource object, i.e. never when being used as
@@ -49,7 +75,7 @@
     }
     const GrVkImageInfo& vkImageInfo() const { return fInfo; }
     VkFormat imageFormat() const { return fInfo.fFormat; }
-    GrBackendFormat getBackendFormat() const {
+    GrBackendFormat backendFormat() const override {
         if (fResource && this->ycbcrConversionInfo().isValid()) {
             SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
             return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
@@ -68,6 +94,20 @@
     bool supportsInputAttachmentUsage() const {
         return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
     }
+
+    const GrVkImageView* framebufferView() const { return fFramebufferView.get(); }
+    const GrVkImageView* textureView() const { return fTextureView.get(); }
+
+    // So that we don't need to rewrite descriptor sets each time, we keep cached input descriptor
+    // sets on the attachment and simply reuse those descriptor sets for this attachment only. These
+    // calls will fail if the attachment does not support being used as an input attachment. These
+    // calls do not ref the GrVkDescriptorSet so they called will need to manually ref them if they
+    // need to be kept alive.
+    gr_rp<const GrVkDescriptorSet> inputDescSetForBlending(GrVkGpu* gpu);
+    // Input descripotr set used when needing to read a resolve attachment to load data into a
+    // discardable msaa attachment.
+    gr_rp<const GrVkDescriptorSet> inputDescSetForMSAALoad(GrVkGpu* gpu);
+
     const Resource* resource() const {
         SkASSERT(fResource);
         return fResource;
@@ -166,16 +206,61 @@
     void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
 #endif
 
-protected:
+private:
+    static sk_sp<GrVkImage> Make(GrVkGpu* gpu,
+                                 SkISize dimensions,
+                                 UsageFlags attachmentUsages,
+                                 int sampleCnt,
+                                 VkFormat format,
+                                 uint32_t mipLevels,
+                                 VkImageUsageFlags vkUsageFlags,
+                                 GrProtected isProtected,
+                                 SkBudgeted);
+
+    GrVkImage(GrVkGpu* gpu,
+              SkISize dimensions,
+              UsageFlags supportedUsages,
+              const GrVkImageInfo&,
+              sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+              sk_sp<const GrVkImageView> framebufferView,
+              sk_sp<const GrVkImageView> textureView,
+              SkBudgeted);
+
+    GrVkImage(GrVkGpu* gpu,
+              SkISize dimensions,
+              UsageFlags supportedUsages,
+              const GrVkImageInfo&,
+              sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+              sk_sp<const GrVkImageView> framebufferView,
+              sk_sp<const GrVkImageView> textureView,
+              GrBackendObjectOwnership,
+              GrWrapCacheable,
+              bool forSecondaryCB);
+
+    void init(GrVkGpu*, bool forSecondaryCB);
+
+    void onRelease() override;
+    void onAbandon() override;
+
     void releaseImage();
     bool hasResource() const { return fResource; }
 
-    GrVkImageInfo                    fInfo;
-    uint32_t                         fInitialQueueFamily;
-    sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
-    bool                             fIsBorrowed;
+    GrVkGpu* getVkGpu() const;
 
-private:
+    GrVkImageInfo                           fInfo;
+    uint32_t                                fInitialQueueFamily;
+    sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
+
+    sk_sp<const GrVkImageView>              fFramebufferView;
+    sk_sp<const GrVkImageView>              fTextureView;
+
+    bool fIsBorrowed;
+
+    // Descriptor set used when this is used as an input attachment for reading the dst in blending.
+    gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet;
+    // Descriptor set used when this is used as an input attachment for loading an msaa attachment.
+    gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet;
+
     class Resource : public GrTextureResource {
     public:
         explicit Resource(const GrVkGpu* gpu)
diff --git a/src/gpu/vk/GrVkMSAALoadManager.cpp b/src/gpu/vk/GrVkMSAALoadManager.cpp
index e2cb496..fdd3fca 100644
--- a/src/gpu/vk/GrVkMSAALoadManager.cpp
+++ b/src/gpu/vk/GrVkMSAALoadManager.cpp
@@ -117,7 +117,7 @@
                                               GrVkCommandBuffer* commandBuffer,
                                               const GrVkRenderPass& renderPass,
                                               GrAttachment* dst,
-                                              GrVkAttachment* src,
+                                              GrVkImage* src,
                                               const SkIRect& rect) {
     if (!dst) {
         return false;
diff --git a/src/gpu/vk/GrVkMSAALoadManager.h b/src/gpu/vk/GrVkMSAALoadManager.h
index 522505c..9a5f7cb 100644
--- a/src/gpu/vk/GrVkMSAALoadManager.h
+++ b/src/gpu/vk/GrVkMSAALoadManager.h
@@ -15,9 +15,9 @@
 
 class GrAttachment;
 class GrSurface;
-class GrVkAttachment;
 class GrVkCommandBuffer;
 class GrVkGpu;
+class GrVkImage;
 class GrVkRenderPass;
 struct SkIRect;
 
@@ -31,7 +31,7 @@
                              GrVkCommandBuffer* commandBuffer,
                              const GrVkRenderPass& renderPass,
                              GrAttachment* dst,
-                             GrVkAttachment* src,
+                             GrVkImage* src,
                              const SkIRect& srcRect);
 
     void destroyResources(GrVkGpu* gpu);
diff --git a/src/gpu/vk/GrVkOpsRenderPass.cpp b/src/gpu/vk/GrVkOpsRenderPass.cpp
index b609d06..afd40a3 100644
--- a/src/gpu/vk/GrVkOpsRenderPass.cpp
+++ b/src/gpu/vk/GrVkOpsRenderPass.cpp
@@ -17,12 +17,12 @@
 #include "src/gpu/GrPipeline.h"
 #include "src/gpu/GrRenderTarget.h"
 #include "src/gpu/effects/GrTextureEffect.h"
-#include "src/gpu/vk/GrVkAttachment.h"
 #include "src/gpu/vk/GrVkBuffer.h"
 #include "src/gpu/vk/GrVkCommandBuffer.h"
 #include "src/gpu/vk/GrVkCommandPool.h"
 #include "src/gpu/vk/GrVkFramebuffer.h"
 #include "src/gpu/vk/GrVkGpu.h"
+#include "src/gpu/vk/GrVkImage.h"
 #include "src/gpu/vk/GrVkPipeline.h"
 #include "src/gpu/vk/GrVkRenderPass.h"
 #include "src/gpu/vk/GrVkRenderTarget.h"
@@ -91,7 +91,7 @@
     }
 
     if (withResolve) {
-        GrVkAttachment* resolveAttachment = fFramebuffer->resolveAttachment();
+        GrVkImage* resolveAttachment = fFramebuffer->resolveAttachment();
         SkASSERT(resolveAttachment);
         if (loadFromResolve == LoadFromResolve::kLoad) {
             resolveAttachment->setImageLayout(fGpu,
@@ -364,7 +364,7 @@
             SkASSERT(sampledProxies[i]->asTextureProxy());
             GrVkTexture* vkTex = static_cast<GrVkTexture*>(sampledProxies[i]->peekTexture());
             SkASSERT(vkTex);
-            GrVkAttachment* texture = vkTex->textureAttachment();
+            GrVkImage* texture = vkTex->textureImage();
             SkASSERT(texture);
             texture->setImageLayout(
                     fGpu, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT,
@@ -678,7 +678,7 @@
 #ifdef SK_DEBUG
 void check_sampled_texture(GrTexture* tex, GrAttachment* colorAttachment, GrVkGpu* gpu) {
     SkASSERT(!tex->isProtected() || (colorAttachment->isProtected() && gpu->protectedContext()));
-    auto vkTex = static_cast<GrVkTexture*>(tex)->textureAttachment();
+    auto vkTex = static_cast<GrVkTexture*>(tex)->textureImage();
     SkASSERT(vkTex->currentLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 }
 #endif
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 199853b..73d0043 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -150,7 +150,7 @@
 
     if (fNumSamplers == 1) {
         auto texture = samplerBindings[0].fTexture;
-        auto texAttachment = texture->textureAttachment();
+        auto texAttachment = texture->textureImage();
         const auto& samplerState = samplerBindings[0].fState;
         const GrVkDescriptorSet* descriptorSet = texture->cachedSingleDescSet(samplerState);
         if (descriptorSet) {
@@ -175,7 +175,7 @@
     for (int i = 0; i < fNumSamplers; ++i) {
         GrSamplerState state = samplerBindings[i].fState;
         GrVkTexture* texture = samplerBindings[i].fTexture;
-        auto texAttachment = texture->textureAttachment();
+        auto texAttachment = texture->textureImage();
 
         const GrVkImageView* textureView = texAttachment->textureView();
         const GrVkSampler* sampler = nullptr;
diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h
index ad034da..3a70512 100644
--- a/src/gpu/vk/GrVkPipelineState.h
+++ b/src/gpu/vk/GrVkPipelineState.h
@@ -10,7 +10,9 @@
 #define GrVkPipelineState_DEFINED
 
 #include "include/gpu/vk/GrVkTypes.h"
+#include "src/gpu/GrRefCnt.h"
 #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
+#include "src/gpu/vk/GrVkDescriptorSet.h"
 #include "src/gpu/vk/GrVkDescriptorSetManager.h"
 #include "src/gpu/vk/GrVkPipelineStateDataManager.h"
 
@@ -19,7 +21,6 @@
 class GrVkBuffer;
 class GrVkCommandBuffer;
 class GrVkDescriptorPool;
-class GrVkDescriptorSet;
 class GrVkGpu;
 class GrVkImageView;
 class GrVkPipeline;
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 590ac5f..eebe423 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -12,7 +12,6 @@
 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
 #include "src/gpu/GrDirectContextPriv.h"
 #include "src/gpu/GrResourceProvider.h"
-#include "src/gpu/vk/GrVkAttachment.h"
 #include "src/gpu/vk/GrVkCommandBuffer.h"
 #include "src/gpu/vk/GrVkDescriptorSet.h"
 #include "src/gpu/vk/GrVkFramebuffer.h"
@@ -51,8 +50,8 @@
 // constructor must be explicitly called.
 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                    SkISize dimensions,
-                                   sk_sp<GrVkAttachment> colorAttachment,
-                                   sk_sp<GrVkAttachment> resolveAttachment,
+                                   sk_sp<GrVkImage> colorAttachment,
+                                   sk_sp<GrVkImage> resolveAttachment,
                                    CreateType createType)
         : GrSurface(gpu, dimensions,
                     colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo)
@@ -107,7 +106,7 @@
     if (this->wrapsSecondaryCommandBuffer()) {
         return;
     }
-    GrVkAttachment* nonMSAAAttachment = this->nonMSAAAttachment();
+    GrVkImage* nonMSAAAttachment = this->nonMSAAAttachment();
     if (nonMSAAAttachment && nonMSAAAttachment->supportsInputAttachmentUsage()) {
         this->setVkRTSupportsInputAttachment();
     }
@@ -128,15 +127,19 @@
         return nullptr;
     }
 
-    sk_sp<GrVkAttachment> wrappedAttachment =
-            GrVkAttachment::MakeWrapped(gpu, dimensions, info, std::move(mutableState),
-                                        GrAttachment::UsageFlags::kColorAttachment,
-                                        kBorrow_GrWrapOwnership, GrWrapCacheable::kNo);
+    sk_sp<GrVkImage> wrappedAttachment =
+            GrVkImage::MakeWrapped(gpu,
+                                   dimensions,
+                                   info,
+                                   std::move(mutableState),
+                                   GrAttachment::UsageFlags::kColorAttachment,
+                                   kBorrow_GrWrapOwnership,
+                                   GrWrapCacheable::kNo);
     if (!wrappedAttachment) {
         return nullptr;
     }
 
-    sk_sp<GrVkAttachment> colorAttachment;
+    sk_sp<GrVkImage> colorAttachment;
     colorAttachment = std::move(wrappedAttachment);
 
     if (!colorAttachment) {
@@ -171,10 +174,15 @@
     sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(new GrBackendSurfaceMutableStateImpl(
             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED));
 
-    sk_sp<GrVkAttachment> colorAttachment =
-        GrVkAttachment::MakeWrapped(gpu, dimensions, info, std::move(mutableState),
-                                    GrAttachment::UsageFlags::kColorAttachment,
-                                    kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, true);
+    sk_sp<GrVkImage> colorAttachment =
+            GrVkImage::MakeWrapped(gpu,
+                                   dimensions,
+                                   info,
+                                   std::move(mutableState),
+                                   GrAttachment::UsageFlags::kColorAttachment,
+                                   kBorrow_GrWrapOwnership,
+                                   GrWrapCacheable::kNo,
+                                   true);
 
     std::unique_ptr<GrVkSecondaryCommandBuffer> scb(
             GrVkSecondaryCommandBuffer::Create(vkInfo.fSecondaryCommandBuffer, rp));
@@ -193,12 +201,12 @@
 
 GrBackendFormat GrVkRenderTarget::backendFormat() const {
     if (this->wrapsSecondaryCommandBuffer()) {
-        return fExternalFramebuffer->colorAttachment()->getBackendFormat();
+        return fExternalFramebuffer->colorAttachment()->backendFormat();
     }
-    return fColorAttachment->getBackendFormat();
+    return fColorAttachment->backendFormat();
 }
 
-GrVkAttachment* GrVkRenderTarget::nonMSAAAttachment() const {
+GrVkImage* GrVkRenderTarget::nonMSAAAttachment() const {
     if (fColorAttachment->numSamples() == 1) {
         return fColorAttachment.get();
     } else {
@@ -206,11 +214,11 @@
     }
 }
 
-GrVkAttachment* GrVkRenderTarget::dynamicMSAAAttachment() {
+GrVkImage* GrVkRenderTarget::dynamicMSAAAttachment() {
     if (fDynamicMSAAAttachment) {
         return fDynamicMSAAAttachment.get();
     }
-    const GrVkAttachment* nonMSAAColorAttachment = this->colorAttachment();
+    const GrVkImage* nonMSAAColorAttachment = this->colorAttachment();
     SkASSERT(nonMSAAColorAttachment->numSamples() == 1);
 
     GrVkGpu* gpu = this->getVkGpu();
@@ -226,12 +234,11 @@
     if (!msaaAttachment) {
         return nullptr;
     }
-    fDynamicMSAAAttachment =
-            sk_sp<GrVkAttachment>(static_cast<GrVkAttachment*>(msaaAttachment.release()));
+    fDynamicMSAAAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
     return fDynamicMSAAAttachment.get();
 }
 
-GrVkAttachment* GrVkRenderTarget::msaaAttachment() {
+GrVkImage* GrVkRenderTarget::msaaAttachment() {
     return this->colorAttachment()->numSamples() == 1 ? this->dynamicMSAAAttachment()
                                                       : this->colorAttachment();
 }
@@ -348,15 +355,13 @@
             renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
     SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
 
-    GrVkAttachment* resolve = withResolve ? this->resolveAttachment() : nullptr;
-    GrVkAttachment* colorAttachment =
-            withResolve ? this->msaaAttachment() : this->colorAttachment();
+    GrVkImage* resolve = withResolve ? this->resolveAttachment() : nullptr;
+    GrVkImage* colorAttachment = withResolve ? this->msaaAttachment() : this->colorAttachment();
 
     // Stencil attachment view is stored in the base RT stencil attachment
     bool useMSAA = this->numSamples() > 1 || withResolve;
-    GrVkAttachment* stencil =
-            withStencil ? static_cast<GrVkAttachment*>(this->getStencilAttachment(useMSAA))
-                        : nullptr;
+    GrVkImage* stencil =  withStencil ? static_cast<GrVkImage*>(this->getStencilAttachment(useMSAA))
+                                      : nullptr;
     fCachedFramebuffers[cacheIndex] =
             GrVkFramebuffer::Make(gpu, this->dimensions(),
                                   sk_sp<const GrVkRenderPass>(renderPass),
@@ -368,7 +373,7 @@
                                                 bool withResolve,
                                                 bool withStencil) {
     SkASSERT(!this->wrapsSecondaryCommandBuffer());
-    const GrVkAttachment* colorAttachment =
+    const GrVkImage* colorAttachment =
             withResolve ? this->msaaAttachment() : this->colorAttachment();
 
     desc->fColor.fFormat = colorAttachment->imageFormat();
@@ -387,7 +392,7 @@
         bool useMSAA = this->numSamples() > 1 || withResolve;
         const GrAttachment* stencil = this->getStencilAttachment(useMSAA);
         SkASSERT(stencil);
-        const GrVkAttachment* vkStencil = static_cast<const GrVkAttachment*>(stencil);
+        const GrVkImage* vkStencil = static_cast<const GrVkImage*>(stencil);
         desc->fStencil.fFormat = vkStencil->imageFormat();
         desc->fStencil.fSamples = vkStencil->numSamples();
         SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
@@ -475,7 +480,7 @@
     // This should only get called with a non-released GrVkRenderTargets.
     SkASSERT(!this->wasDestroyed());
     // If we have a resolve attachment that is what we return for the backend render target
-    const GrVkAttachment* beAttachment = this->externalAttachment();
+    const GrVkImage* beAttachment = this->externalAttachment();
     return GrBackendRenderTarget(beAttachment->width(), beAttachment->height(),
                                  beAttachment->vkImageInfo(), beAttachment->getMutableState());
 }
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index a3f65ab..f0bc6c6 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -19,7 +19,6 @@
 class GrVkFramebuffer;
 class GrVkGpu;
 class GrVkImageView;
-class GrVkAttachment;
 
 struct GrVkImageInfo;
 
@@ -53,7 +52,7 @@
                                     renderPass.loadFromResolve());
     }
 
-    GrVkAttachment* colorAttachment() const {
+    GrVkImage* colorAttachment() const {
         SkASSERT(!this->wrapsSecondaryCommandBuffer());
         return fColorAttachment.get();
     }
@@ -62,7 +61,7 @@
         return this->colorAttachment()->framebufferView();
     }
 
-    GrVkAttachment* resolveAttachment() const {
+    GrVkImage* resolveAttachment() const {
         SkASSERT(!this->wrapsSecondaryCommandBuffer());
         return fResolveAttachment.get();
     }
@@ -71,15 +70,15 @@
         return fResolveAttachment->framebufferView();
     }
 
-    // Returns the GrVkAttachment of the non-msaa attachment. If the color attachment has 1 sample,
+    // Returns the GrVkImage of the non-msaa attachment. If the color attachment has 1 sample,
     // then the color attachment will be returned. Otherwise, the resolve attachment is returned.
     // Note that in this second case the resolve attachment may be null if this was created by
     // wrapping an msaa VkImage.
-    GrVkAttachment* nonMSAAAttachment() const;
+    GrVkImage* nonMSAAAttachment() const;
 
     // Returns the attachment that is used for all external client facing operations. This will be
     // either a wrapped color attachment or the resolve attachment for created VkImages.
-    GrVkAttachment* externalAttachment() const {
+    GrVkImage* externalAttachment() const {
         return fResolveAttachment ? fResolveAttachment.get() : fColorAttachment.get();
     }
 
@@ -122,8 +121,8 @@
 
     GrVkRenderTarget(GrVkGpu* gpu,
                      SkISize dimensions,
-                     sk_sp<GrVkAttachment> colorAttachment,
-                     sk_sp<GrVkAttachment> resolveAttachment,
+                     sk_sp<GrVkImage> colorAttachment,
+                     sk_sp<GrVkImage> resolveImage,
                      CreateType createType);
 
     void onAbandon() override;
@@ -142,8 +141,8 @@
 
     GrVkGpu* getVkGpu() const;
 
-    GrVkAttachment* dynamicMSAAAttachment();
-    GrVkAttachment* msaaAttachment();
+    GrVkImage* dynamicMSAAAttachment();
+    GrVkImage* msaaAttachment();
 
     std::pair<const GrVkRenderPass*, GrVkResourceProvider::CompatibleRPHandle>
         createSimpleRenderPass(bool withResolve,
@@ -162,16 +161,16 @@
     void onSetRelease(sk_sp<GrRefCntedCallback> releaseHelper) override {
         // Forward the release proc on to the GrVkImage of the release attachment if we have one,
         // otherwise the color attachment.
-        GrVkAttachment* attachment =
+        GrVkImage* attachment =
                 fResolveAttachment ? fResolveAttachment.get() : fColorAttachment.get();
         attachment->setResourceRelease(std::move(releaseHelper));
     }
 
     void releaseInternalObjects();
 
-    sk_sp<GrVkAttachment> fColorAttachment;
-    sk_sp<GrVkAttachment> fResolveAttachment;
-    sk_sp<GrVkAttachment> fDynamicMSAAAttachment;
+    sk_sp<GrVkImage> fColorAttachment;
+    sk_sp<GrVkImage> fResolveAttachment;
+    sk_sp<GrVkImage> fDynamicMSAAAttachment;
 
     // We can have a renderpass with and without resolve attachment, stencil attachment,
     // input attachment dependency, advanced blend dependency, and loading from resolve. All 5 of
diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp
index 61019ec..35454fe 100644
--- a/src/gpu/vk/GrVkTexture.cpp
+++ b/src/gpu/vk/GrVkTexture.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+
 #include "src/gpu/vk/GrVkTexture.h"
 
 #include "src/gpu/GrTexture.h"
@@ -22,7 +23,7 @@
 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
                          SkBudgeted budgeted,
                          SkISize dimensions,
-                         sk_sp<GrVkAttachment> texture,
+                         sk_sp<GrVkImage> texture,
                          GrMipmapStatus mipmapStatus)
         : GrSurface(gpu, dimensions,
                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
@@ -43,7 +44,7 @@
 }
 
 GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions,
-                         sk_sp<GrVkAttachment> texture, GrMipmapStatus mipmapStatus,
+                         sk_sp<GrVkImage> texture, GrMipmapStatus mipmapStatus,
                          GrWrapCacheable cacheable, GrIOType ioType, bool isExternal)
         : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
         , GrTexture(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
@@ -61,7 +62,7 @@
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
                          SkISize dimensions,
-                         sk_sp<GrVkAttachment> texture,
+                         sk_sp<GrVkImage> texture,
                          GrMipmapStatus mipmapStatus)
         : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
         , GrTexture(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
@@ -80,7 +81,7 @@
                                                VkFormat format, uint32_t mipLevels,
                                                GrProtected isProtected,
                                                GrMipmapStatus mipmapStatus) {
-    sk_sp<GrVkAttachment> texture = GrVkAttachment::MakeTexture(
+    sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(
             gpu, dimensions, format, mipLevels, GrRenderable::kNo, /*numSamples=*/1, budgeted,
             isProtected);
 
@@ -99,10 +100,13 @@
     SkASSERT(VK_NULL_HANDLE != info.fImage &&
              (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
 
-    sk_sp<GrVkAttachment> texture =
-            GrVkAttachment::MakeWrapped(gpu, dimensions, info, std::move(mutableState),
-                                        GrAttachment::UsageFlags::kTexture, wrapOwnership,
-                                        cacheable);
+    sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
+                                                      dimensions,
+                                                      info,
+                                                      std::move(mutableState),
+                                                      GrAttachment::UsageFlags::kTexture,
+                                                      wrapOwnership,
+                                                      cacheable);
     if (!texture) {
         return nullptr;
     }
diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h
index c0c32ff..cbae00e 100644
--- a/src/gpu/vk/GrVkTexture.h
+++ b/src/gpu/vk/GrVkTexture.h
@@ -12,7 +12,7 @@
 #include "src/core/SkLRUCache.h"
 #include "src/gpu/GrSamplerState.h"
 #include "src/gpu/GrTexture.h"
-#include "src/gpu/vk/GrVkAttachment.h"
+#include "src/gpu/vk/GrVkImage.h"
 
 class GrVkDescriptorSet;
 class GrVkGpu;
@@ -41,11 +41,11 @@
 
     GrBackendTexture getBackendTexture() const override;
 
-    GrBackendFormat backendFormat() const override { return fTexture->getBackendFormat(); }
+    GrBackendFormat backendFormat() const override { return fTexture->backendFormat(); }
 
     void textureParamsModified() override {}
 
-    GrVkAttachment* textureAttachment() const { return fTexture.get(); }
+    GrVkImage* textureImage() const { return fTexture.get(); }
     const GrVkImageView* textureView();
 
     // For each GrVkTexture, there is a cache of GrVkDescriptorSets which only contain a single
@@ -60,7 +60,7 @@
 protected:
     GrVkTexture(GrVkGpu*,
                 SkISize dimensions,
-                sk_sp<GrVkAttachment> texture,
+                sk_sp<GrVkImage> texture,
                 GrMipmapStatus);
 
     GrVkGpu* getVkGpu() const;
@@ -80,11 +80,11 @@
     }
 
 private:
-    GrVkTexture(GrVkGpu*, SkBudgeted, SkISize, sk_sp<GrVkAttachment> texture, GrMipmapStatus);
-    GrVkTexture(GrVkGpu*, SkISize, sk_sp<GrVkAttachment> texture, GrMipmapStatus,
+    GrVkTexture(GrVkGpu*, SkBudgeted, SkISize, sk_sp<GrVkImage> texture, GrMipmapStatus);
+    GrVkTexture(GrVkGpu*, SkISize, sk_sp<GrVkImage> texture, GrMipmapStatus,
                 GrWrapCacheable, GrIOType, bool isExternal);
 
-    sk_sp<GrVkAttachment> fTexture;
+    sk_sp<GrVkImage> fTexture;
 
     struct SamplerHash {
         uint32_t operator()(GrSamplerState state) const { return state.asIndex(); }
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp
index 1b5a7ad..fc9dc69 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -10,8 +10,8 @@
 #include "src/gpu/GrDirectContextPriv.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrTexture.h"
-#include "src/gpu/vk/GrVkAttachment.h"
 #include "src/gpu/vk/GrVkGpu.h"
+#include "src/gpu/vk/GrVkImage.h"
 #include "src/gpu/vk/GrVkImageView.h"
 #include "src/gpu/vk/GrVkUtil.h"
 
@@ -25,9 +25,9 @@
         GrVkGpu* gpu,
         SkBudgeted budgeted,
         SkISize dimensions,
-        sk_sp<GrVkAttachment> texture,
-        sk_sp<GrVkAttachment> colorAttachment,
-        sk_sp<GrVkAttachment> resolveAttachment,
+        sk_sp<GrVkImage> texture,
+        sk_sp<GrVkImage> colorAttachment,
+        sk_sp<GrVkImage> resolveAttachment,
         GrMipmapStatus mipmapStatus)
         : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
         , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus)
@@ -39,9 +39,9 @@
 GrVkTextureRenderTarget::GrVkTextureRenderTarget(
         GrVkGpu* gpu,
         SkISize dimensions,
-        sk_sp<GrVkAttachment> texture,
-        sk_sp<GrVkAttachment> colorAttachment,
-        sk_sp<GrVkAttachment> resolveAttachment,
+        sk_sp<GrVkImage> texture,
+        sk_sp<GrVkImage> colorAttachment,
+        sk_sp<GrVkImage> resolveAttachment,
         GrMipmapStatus mipmapStatus,
         GrWrapCacheable cacheable)
         : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
@@ -52,9 +52,10 @@
 }
 
 bool create_rt_attachments(GrVkGpu* gpu, SkISize dimensions, VkFormat format, int sampleCnt,
-                           GrProtected isProtected, sk_sp<GrVkAttachment> texture,
-                           sk_sp<GrVkAttachment>* colorAttachment,
-                           sk_sp<GrVkAttachment>* resolveAttachment) {
+                           GrProtected isProtected,
+                           sk_sp<GrVkImage> texture,
+                           sk_sp<GrVkImage>* colorAttachment,
+                           sk_sp<GrVkImage>* resolveAttachment) {
     if (sampleCnt > 1) {
         auto rp = gpu->getContext()->priv().resourceProvider();
         sk_sp<GrAttachment> msaaAttachment = rp->makeMSAAAttachment(
@@ -62,8 +63,7 @@
         if (!msaaAttachment) {
             return false;
         }
-        *colorAttachment =
-                sk_sp<GrVkAttachment>(static_cast<GrVkAttachment*>(msaaAttachment.release()));
+        *colorAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
         *resolveAttachment = std::move(texture);
     } else {
         *colorAttachment = std::move(texture);
@@ -80,15 +80,20 @@
         int sampleCnt,
         GrMipmapStatus mipmapStatus,
         GrProtected isProtected) {
-    sk_sp<GrVkAttachment> texture =
-            GrVkAttachment::MakeTexture(gpu, dimensions, format, mipLevels, GrRenderable::kYes,
-                                        /*numSamples=*/1, budgeted, isProtected);
+    sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(gpu,
+                                                      dimensions,
+                                                      format,
+                                                      mipLevels,
+                                                      GrRenderable::kYes,
+                                                      /*numSamples=*/1,
+                                                      budgeted,
+                                                      isProtected);
     if (!texture) {
         return nullptr;
     }
 
-    sk_sp<GrVkAttachment> colorAttachment;
-    sk_sp<GrVkAttachment> resolveAttachment;
+    sk_sp<GrVkImage> colorAttachment;
+    sk_sp<GrVkImage> resolveAttachment;
     if (!create_rt_attachments(gpu, dimensions, format, sampleCnt, isProtected, texture,
                                &colorAttachment, &resolveAttachment)) {
         return nullptr;
@@ -117,15 +122,19 @@
         textureUsageFlags |= GrAttachment::UsageFlags::kColorAttachment;
     }
 
-    sk_sp<GrVkAttachment> texture =
-            GrVkAttachment::MakeWrapped(gpu, dimensions, info, std::move(mutableState),
-                                        textureUsageFlags, wrapOwnership, cacheable);
+    sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
+                                                      dimensions,
+                                                      info,
+                                                      std::move(mutableState),
+                                                      textureUsageFlags,
+                                                      wrapOwnership,
+                                                      cacheable);
     if (!texture) {
         return nullptr;
     }
 
-    sk_sp<GrVkAttachment> colorAttachment;
-    sk_sp<GrVkAttachment> resolveAttachment;
+    sk_sp<GrVkImage> colorAttachment;
+    sk_sp<GrVkImage> resolveAttachment;
     if (!create_rt_attachments(gpu, dimensions, info.fFormat, sampleCnt, info.fProtected, texture,
                                &colorAttachment, &resolveAttachment)) {
         return nullptr;
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.h b/src/gpu/vk/GrVkTextureRenderTarget.h
index 07eb8dd..d089d44 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.h
+++ b/src/gpu/vk/GrVkTextureRenderTarget.h
@@ -64,16 +64,16 @@
     GrVkTextureRenderTarget(GrVkGpu* gpu,
                             SkBudgeted budgeted,
                             SkISize dimensions,
-                            sk_sp<GrVkAttachment> texture,
-                            sk_sp<GrVkAttachment> colorAttachment,
-                            sk_sp<GrVkAttachment> resolveAttachment,
+                            sk_sp<GrVkImage> texture,
+                            sk_sp<GrVkImage> colorAttachment,
+                            sk_sp<GrVkImage> resolveAttachment,
                             GrMipmapStatus);
 
     GrVkTextureRenderTarget(GrVkGpu* gpu,
                             SkISize dimensions,
-                            sk_sp<GrVkAttachment> texture,
-                            sk_sp<GrVkAttachment> colorAttachment,
-                            sk_sp<GrVkAttachment> resolveAttachment,
+                            sk_sp<GrVkImage> texture,
+                            sk_sp<GrVkImage> colorAttachment,
+                            sk_sp<GrVkImage> resolveAttachment,
                             GrMipmapStatus,
                             GrWrapCacheable);
 
diff --git a/tests/BackendSurfaceMutableStateTest.cpp b/tests/BackendSurfaceMutableStateTest.cpp
index 725d25e..60d58c4 100644
--- a/tests/BackendSurfaceMutableStateTest.cpp
+++ b/tests/BackendSurfaceMutableStateTest.cpp
@@ -70,7 +70,7 @@
     REPORTER_ASSERT(reporter, texture);
 
     // Verify that modifying the layout via the GrVkTexture is reflected in the GrBackendTexture
-    GrVkAttachment* vkTexture = static_cast<GrVkTexture*>(texture)->textureAttachment();
+    GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage();
     REPORTER_ASSERT(reporter, initLayout == vkTexture->currentLayout());
     REPORTER_ASSERT(reporter, initQueue == vkTexture->currentQueueFamilyIndex());
     vkTexture->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
diff --git a/tests/VkBackendSurfaceTest.cpp b/tests/VkBackendSurfaceTest.cpp
index cc06457..a018005 100644
--- a/tests/VkBackendSurfaceTest.cpp
+++ b/tests/VkBackendSurfaceTest.cpp
@@ -78,7 +78,7 @@
     REPORTER_ASSERT(reporter, texture);
 
     // Verify that modifying the layout via the GrVkTexture is reflected in the GrBackendTexture
-    GrVkAttachment* vkTexture = static_cast<GrVkTexture*>(texture)->textureAttachment();
+    GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage();
     REPORTER_ASSERT(reporter, initLayout == vkTexture->currentLayout());
     vkTexture->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);