Refactor to separate backend object lifecycle and GpuResource budget decision

Refactor GrGpuResource to contain two different pieces of state:
 a) instance is budgeted or not budgeted
 b) instance references wrapped backend objects or not

The "object lifecycle" was also attached to backend object
handles (ids), which made the code a bit unclear. Backend objects
would be associated with GrGpuResource::LifeCycle, even though
GrGpuResource::LifeCycle refers to the GpuResource, and individual
backend objects in one GpuResource might be governed with different
"lifecycle".

Mark the budgeted/not budgeted with SkBudgeted::kYes, SkBudgeted::kNo.
This was previously GrGpuResource::kCached_LifeCycle,
GrGpuResource::kUncached_LifeCycle.

Mark the "references wrapped object" with boolean. This was previously
GrGpuResource::kBorrowed_LifeCycle,
GrGpuResource::kAdopted_LifeCycle for GrGpuResource.

Associate the backend object ownership status with
GrBackendObjectOwnership for the backend object handles.

The resource type leaf constuctors, such has GrGLTexture or
GrGLTextureRenderTarget take "budgeted" parameter. This parameter
is passed to GrGpuResource::registerWithCache().

The resource type intermediary constructors, such as GrGLTexture
constructors for class GrGLTextureRenderTarget do not take "budgeted"
parameters, intermediary construtors do not call registerWithCache.

Removes the need for tagging GrGpuResource -derived subclass
constructors with "Derived" parameter.

Makes instances that wrap backend objects be registered with
a new function GrGpuResource::registerWithCacheWrapped().

Removes "budgeted" parameter from classes such as StencilAttahment, as
they are always cached and never wrap any external backend objects.

Removes the use of concept "external" from the member function names.
The API refers to the objects as "wrapped", so make all related
functions use the term consistently.

No change in functionality. Resources referencing wrapped objects are
always inserted to the cache with budget decision kNo.

BUG=594928
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1862043002

Review URL: https://codereview.chromium.org/1862043002
diff --git a/bench/GrResourceCacheBench.cpp b/bench/GrResourceCacheBench.cpp
index 890bc96..295a5bc 100644
--- a/bench/GrResourceCacheBench.cpp
+++ b/bench/GrResourceCacheBench.cpp
@@ -23,8 +23,8 @@
 class BenchResource : public GrGpuResource {
 public:
     BenchResource (GrGpu* gpu)
-        : INHERITED(gpu, kCached_LifeCycle) {
-        this->registerWithCache();
+        : INHERITED(gpu) {
+        this->registerWithCache(SkBudgeted::kYes);
     }
 
     static void ComputeKey(int i, int keyData32Count, GrUniqueKey* key) {
diff --git a/include/gpu/GrBuffer.h b/include/gpu/GrBuffer.h
index 7e04577..829596e 100644
--- a/include/gpu/GrBuffer.h
+++ b/include/gpu/GrBuffer.h
@@ -110,22 +110,24 @@
 protected:
     GrBuffer(GrGpu* gpu, size_t gpuMemorySize, GrBufferType intendedType,
              GrAccessPattern accessPattern, bool cpuBacked)
-        : INHERITED(gpu, kCached_LifeCycle),
+        : INHERITED(gpu),
           fMapPtr(nullptr),
           fGpuMemorySize(gpuMemorySize), // TODO: Zero for cpu backed buffers?
           fAccessPattern(accessPattern),
-          fCPUBacked(cpuBacked) {
+          fCPUBacked(cpuBacked),
+          fIntendedType(intendedType) {
+    }
+
+    void computeScratchKey(GrScratchKey* key) const override {
         if (!fCPUBacked && SkIsPow2(fGpuMemorySize) && kDynamic_GrAccessPattern == fAccessPattern) {
-            GrScratchKey key;
-            ComputeScratchKeyForDynamicBuffer(fGpuMemorySize, intendedType, &key);
-            this->setScratchKey(key);
+            ComputeScratchKeyForDynamicBuffer(fGpuMemorySize, fIntendedType, key);
         }
     }
 
     void* fMapPtr;
 
 private:
-    virtual size_t onGpuMemorySize() const { return fGpuMemorySize; }
+    size_t onGpuMemorySize() const override { return fGpuMemorySize; }
 
     virtual void onMap() = 0;
     virtual void onUnmap() = 0;
@@ -134,7 +136,7 @@
     size_t            fGpuMemorySize;
     GrAccessPattern   fAccessPattern;
     bool              fCPUBacked;
-
+    GrBufferType      fIntendedType;
     typedef GrGpuResource INHERITED;
 };
 
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 8103959..37a87d3 100644
--- a/include/gpu/GrGpuResource.h
+++ b/include/gpu/GrGpuResource.h
@@ -140,34 +140,6 @@
 class SK_API GrGpuResource : public GrIORef<GrGpuResource> {
 public:
 
-
-    enum LifeCycle {
-        /**
-         * The resource is cached and owned by Skia. Resources with this status may be kept alive
-         * by the cache as either scratch or unique resources even when there are no refs to them.
-         * The cache may release them whenever there are no refs.
-         */
-        kCached_LifeCycle,
-
-        /**
-         * The resource is uncached. As soon as there are no more refs to it, it is released. Under
-         * the hood the cache may opaquely recycle it as a cached resource.
-         */
-        kUncached_LifeCycle,
-
-        /**
-         * Similar to uncached, but Skia does not manage the lifetime of the underlying backend
-         * 3D API object(s). The client is responsible for freeing those. Used to inject client-
-         * created GPU resources into Skia (e.g. to render to a client-created texture).
-         */
-        kBorrowed_LifeCycle,
-
-        /**
-         * An external resource with ownership transfered into Skia. Skia will free the resource.
-         */
-        kAdopted_LifeCycle,
-    };
-
     /**
      * Tests whether a object has been abandoned or released. All objects will
      * be in this state after their creating GrContext is destroyed or has
@@ -261,11 +233,16 @@
     virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
 
 protected:
-    // This must be called by every GrGpuObject. It should be called once the object is fully
-    // initialized (i.e. not in a base class constructor).
-    void registerWithCache();
+    // This must be called by every non-wrapped GrGpuObject. It should be called once the object is
+    // fully initialized (i.e. only from the constructors of the final class).
+    void registerWithCache(SkBudgeted);
 
-    GrGpuResource(GrGpu*, LifeCycle);
+    // This must be called by every GrGpuObject that references any wrapped backend objects. It
+    // should be called once the object is fully initialized (i.e. only from the constructors of the
+    // final class).
+    void registerWithCacheWrapped();
+
+    GrGpuResource(GrGpu*);
     virtual ~GrGpuResource();
 
     GrGpu* getGpu() const { return fGpu; }
@@ -277,13 +254,6 @@
         backend API calls should be made. */
     virtual void onAbandon() { }
 
-    bool shouldFreeResources() const { return fLifeCycle != kBorrowed_LifeCycle; }
-
-    bool isExternal() const {
-        return GrGpuResource::kAdopted_LifeCycle == fLifeCycle ||
-               GrGpuResource::kBorrowed_LifeCycle == fLifeCycle;
-    }
-
     /**
      * This entry point should be called whenever gpuMemorySize() should report a different size.
      * The cache will call gpuMemorySize() to update the current size of the resource.
@@ -291,12 +261,6 @@
     void didChangeGpuMemorySize() const;
 
     /**
-     * Optionally called by the GrGpuResource subclass if the resource can be used as scratch.
-     * By default resources are not usable as scratch. This should only be called once.
-     **/
-    void setScratchKey(const GrScratchKey& scratchKey);
-
-    /**
      * Allows subclasses to add additional backing information to the SkTraceMemoryDump. Called by
      * onMemoryDump. The default implementation adds no backing information.
      **/
@@ -304,6 +268,14 @@
 
 private:
     /**
+     * Called by the registerWithCache if the resource is available to be used as scratch.
+     * Resource subclasses should override this if the instances should be recycled as scratch
+     * resources and populate the scratchKey with the key.
+     * By default resources are not recycled as scratch.
+     **/
+    virtual void computeScratchKey(GrScratchKey*) const { };
+
+    /**
      * Frees the object in the underlying 3D API. Called by CacheAccess.
      */
     void release();
@@ -341,7 +313,8 @@
     GrGpu*                      fGpu;
     mutable size_t              fGpuMemorySize;
 
-    LifeCycle                   fLifeCycle;
+    SkBudgeted                  fBudgeted;
+    bool                        fRefsWrappedObjects;
     const uint32_t              fUniqueID;
 
     SkAutoTUnref<const SkData>  fData;
diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h
index d39d284..eb9f142 100644
--- a/include/gpu/GrRenderTarget.h
+++ b/include/gpu/GrRenderTarget.h
@@ -156,9 +156,9 @@
     GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
 
 protected:
-    GrRenderTarget(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
+    GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
                    SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr)
-        : INHERITED(gpu, lifeCycle, desc)
+        : INHERITED(gpu, desc)
         , fStencilAttachment(stencil)
         , fSampleConfig(sampleConfig)
         , fLastDrawTarget(nullptr) {
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index b59d802..b87b2db 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -146,8 +146,8 @@
     // Provides access to methods that should be public within Skia code.
     friend class GrSurfacePriv;
 
-    GrSurface(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
-        : INHERITED(gpu, lifeCycle)
+    GrSurface(GrGpu* gpu, const GrSurfaceDesc& desc)
+        : INHERITED(gpu)
         , fDesc(desc)
         , fReleaseProc(NULL)
         , fReleaseCtx(NULL)
diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h
index 1d589ed..1aa2cbd 100644
--- a/include/gpu/GrTexture.h
+++ b/include/gpu/GrTexture.h
@@ -46,11 +46,12 @@
     inline const GrTexturePriv texturePriv() const;
 
 protected:
-    GrTexture(GrGpu*, LifeCycle, const GrSurfaceDesc&, GrSLType, bool wasMipMapDataProvided);
+    GrTexture(GrGpu*, const GrSurfaceDesc&, GrSLType, bool wasMipMapDataProvided);
 
     void validateDesc() const;
 
 private:
+    void computeScratchKey(GrScratchKey*) const override;
     size_t onGpuMemorySize() const override;
     void dirtyMipMaps(bool mipMapsDirty);
 
diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h
index 9a96521..18bc644 100644
--- a/include/gpu/GrTypesPriv.h
+++ b/include/gpu/GrTypesPriv.h
@@ -464,4 +464,14 @@
 #define GrCapsDebugf(caps, ...)
 #endif
 
+/**
+ * Specifies if the holder owns the backend, OpenGL or Vulkan, object.
+ */
+enum class GrBackendObjectOwnership : bool {
+    /** Holder does not destroy the backend object. */
+    kBorrowed = false,
+    /** Holder destroys the backend object. */
+    kOwned = true
+};
+
 #endif
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index d062a48..eef7118 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -150,9 +150,6 @@
     desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
 
     GrTexture* tex = nullptr;
-    GrGpuResource::LifeCycle lifeCycle = SkBudgeted::kYes == budgeted ?
-                                            GrGpuResource::kCached_LifeCycle :
-                                            GrGpuResource::kUncached_LifeCycle;
 
     if (GrPixelConfigIsCompressed(desc.fConfig)) {
         // We shouldn't be rendering into this
@@ -165,10 +162,10 @@
         }
 
         this->handleDirtyContext();
-        tex = this->onCreateCompressedTexture(desc, lifeCycle, texels);
+        tex = this->onCreateCompressedTexture(desc, budgeted, texels);
     } else {
         this->handleDirtyContext();
-        tex = this->onCreateTexture(desc, lifeCycle, texels);
+        tex = this->onCreateTexture(desc, budgeted, texels);
     }
     if (tex) {
         if (!caps->reuseScratchTextures() && !isRT) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 883b7ee..97ca11c 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -529,10 +529,10 @@
     // Texture size and sample size will have already been validated in base class before
     // onCreateTexture/CompressedTexture are called.
     virtual GrTexture* onCreateTexture(const GrSurfaceDesc& desc,
-                                       GrGpuResource::LifeCycle lifeCycle,
+                                       SkBudgeted budgeted,
                                        const SkTArray<GrMipLevel>& texels) = 0;
     virtual GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
-                                                 GrGpuResource::LifeCycle lifeCycle,
+                                                 SkBudgeted budgeted,
                                                  const SkTArray<GrMipLevel>& texels) = 0;
 
     virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) = 0;
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index 53e568b..ff858fe 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -19,15 +19,26 @@
     return gpu->getContext()->getResourceCache();
 }
 
-GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle)
+GrGpuResource::GrGpuResource(GrGpu* gpu)
     : fGpu(gpu)
     , fGpuMemorySize(kInvalidGpuMemorySize)
-    , fLifeCycle(lifeCycle)
+    , fBudgeted(SkBudgeted::kNo)
+    , fRefsWrappedObjects(false)
     , fUniqueID(CreateUniqueID()) {
     SkDEBUGCODE(fCacheArrayIndex = -1);
 }
 
-void GrGpuResource::registerWithCache() {
+void GrGpuResource::registerWithCache(SkBudgeted budgeted) {
+    SkASSERT(fBudgeted == SkBudgeted::kNo);
+    fBudgeted = budgeted;
+    this->computeScratchKey(&fScratchKey);
+    get_resource_cache(fGpu)->resourceAccess().insertResource(this);
+}
+
+void GrGpuResource::registerWithCacheWrapped() {
+    SkASSERT(fBudgeted == SkBudgeted::kNo);
+    // Currently resources referencing wrapped objects are not budgeted.
+    fRefsWrappedObjects = true;
     get_resource_cache(fGpu)->resourceAccess().insertResource(this);
 }
 
@@ -164,16 +175,6 @@
     return false;
 }
 
-void GrGpuResource::setScratchKey(const GrScratchKey& scratchKey) {
-    SkASSERT(!fScratchKey.isValid());
-    SkASSERT(scratchKey.isValid());
-    // Wrapped resources can never have a scratch key.
-    if (this->resourcePriv().isExternal()) {
-        return;
-    }
-    fScratchKey = scratchKey;
-}
-
 void GrGpuResource::removeScratchKey() {
     if (!this->wasDestroyed() && fScratchKey.isValid()) {
         get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this);
@@ -182,16 +183,18 @@
 }
 
 void GrGpuResource::makeBudgeted() {
-    if (!this->wasDestroyed() && GrGpuResource::kUncached_LifeCycle == fLifeCycle) {
-        fLifeCycle = kCached_LifeCycle;
+    if (!this->wasDestroyed() && SkBudgeted::kNo == fBudgeted) {
+        // Currently resources referencing wrapped objects are not budgeted.
+        SkASSERT(!fRefsWrappedObjects);
+        fBudgeted = SkBudgeted::kYes;
         get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
     }
 }
 
 void GrGpuResource::makeUnbudgeted() {
-    if (!this->wasDestroyed() && GrGpuResource::kCached_LifeCycle == fLifeCycle &&
+    if (!this->wasDestroyed() && SkBudgeted::kYes == fBudgeted &&
         !fUniqueKey.isValid()) {
-        fLifeCycle = kUncached_LifeCycle;
+        fBudgeted = SkBudgeted::kNo;
         get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
     }
 }
diff --git a/src/gpu/GrGpuResourceCacheAccess.h b/src/gpu/GrGpuResourceCacheAccess.h
index cccbecf..b09dcc1 100644
--- a/src/gpu/GrGpuResourceCacheAccess.h
+++ b/src/gpu/GrGpuResourceCacheAccess.h
@@ -30,18 +30,6 @@
     }
 
     /**
-     * Is the resource object wrapping an externally allocated GPU resource that Skia has not taken
-     * ownership of.
-     */
-    bool isBorrowed() const { return GrGpuResource::kBorrowed_LifeCycle == fResource->fLifeCycle; }
-
-    /**
-     * Is the resource object wrapping an externally allocated GPU resource that Skia has taken
-     * ownership of.
-     */
-    bool isAdopted() const { return GrGpuResource::kAdopted_LifeCycle == fResource->fLifeCycle; }
-
-    /**
      * Called by the cache to delete the resource under normal circumstances.
      */
     void release() {
diff --git a/src/gpu/GrGpuResourcePriv.h b/src/gpu/GrGpuResourcePriv.h
index 8b67283..82bf072 100644
--- a/src/gpu/GrGpuResourcePriv.h
+++ b/src/gpu/GrGpuResourcePriv.h
@@ -44,7 +44,7 @@
      * Does the resource count against the resource budget?
      */
     SkBudgeted isBudgeted() const {
-        bool ret = GrGpuResource::kCached_LifeCycle == fResource->fLifeCycle;
+        bool ret = SkBudgeted::kYes == fResource->fBudgeted;
         SkASSERT(ret || !fResource->getUniqueKey().isValid());
         return SkBudgeted(ret);
     }
@@ -52,7 +52,7 @@
     /**
      * Is the resource object wrapping an externally allocated GPU resource?
      */
-    bool isExternal() const { return fResource->isExternal(); }
+    bool refsWrappedObjects() const { return fResource->fRefsWrappedObjects; }
 
     /**
      * If this resource can be used as a scratch resource this returns a valid scratch key.
diff --git a/src/gpu/GrPath.h b/src/gpu/GrPath.h
index 09d317e..4cb12f4 100644
--- a/src/gpu/GrPath.h
+++ b/src/gpu/GrPath.h
@@ -20,7 +20,7 @@
      * Initialize to a path with a fixed stroke. Stroke must not be hairline.
      */
     GrPath(GrGpu* gpu, const SkPath& skPath, const GrStrokeInfo& stroke)
-        : INHERITED(gpu, kCached_LifeCycle)
+        : INHERITED(gpu)
         , fBounds(SkRect::MakeEmpty())
         , fFillType(GrPathRendering::kWinding_FillType)
 #ifdef SK_DEBUG
diff --git a/src/gpu/GrPathRange.cpp b/src/gpu/GrPathRange.cpp
index 754aca0..6cf9de2 100644
--- a/src/gpu/GrPathRange.cpp
+++ b/src/gpu/GrPathRange.cpp
@@ -10,7 +10,7 @@
 
 GrPathRange::GrPathRange(GrGpu* gpu,
                          PathGenerator* pathGenerator)
-    : INHERITED(gpu, kCached_LifeCycle),
+    : INHERITED(gpu),
       fPathGenerator(SkRef(pathGenerator)),
       fNumPaths(fPathGenerator->getNumPaths()) {
     const int numGroups = (fNumPaths + kPathsPerGroup - 1) / kPathsPerGroup;
@@ -20,7 +20,7 @@
 
 GrPathRange::GrPathRange(GrGpu* gpu,
                          int numPaths)
-    : INHERITED(gpu, kCached_LifeCycle),
+    : INHERITED(gpu),
       fNumPaths(numPaths) {
 }
 
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 96816dd..1d32c23 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -146,7 +146,7 @@
 #endif
     }
     if (resource->resourcePriv().getScratchKey().isValid()) {
-        SkASSERT(!resource->resourcePriv().isExternal());
+        SkASSERT(!resource->resourcePriv().refsWrappedObjects());
         fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource);
     }
 
@@ -376,7 +376,7 @@
 
     if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) {
         // Check whether this resource could still be used as a scratch resource.
-        if (!resource->resourcePriv().isExternal() &&
+        if (!resource->resourcePriv().refsWrappedObjects() &&
             resource->resourcePriv().getScratchKey().isValid()) {
             // We won't purge an existing resource to make room for this one.
             if (fBudgetedCount < fMaxCount &&
@@ -661,19 +661,19 @@
                 SkASSERT(!resource->getUniqueKey().isValid());
                 ++fScratch;
                 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
-                SkASSERT(!resource->resourcePriv().isExternal());
+                SkASSERT(!resource->resourcePriv().refsWrappedObjects());
             } else if (resource->resourcePriv().getScratchKey().isValid()) {
                 SkASSERT(SkBudgeted::kNo == resource->resourcePriv().isBudgeted() ||
                          resource->getUniqueKey().isValid());
                 ++fCouldBeScratch;
                 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
-                SkASSERT(!resource->resourcePriv().isExternal());
+                SkASSERT(!resource->resourcePriv().refsWrappedObjects());
             }
             const GrUniqueKey& uniqueKey = resource->getUniqueKey();
             if (uniqueKey.isValid()) {
                 ++fContent;
                 SkASSERT(fUniqueHash->find(uniqueKey) == resource);
-                SkASSERT(!resource->resourcePriv().isExternal());
+                SkASSERT(!resource->resourcePriv().refsWrappedObjects());
                 SkASSERT(SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
             }
 
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 5939c51..6c64ddc 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -188,9 +188,7 @@
         int fNumNonPurgeable;
 
         int fScratch;
-        int fExternal;
-        int fBorrowed;
-        int fAdopted;
+        int fWrapped;
         size_t fUnbudgetedSize;
 
         Stats() { this->reset(); }
@@ -200,9 +198,7 @@
             fNumPurgeable = 0;
             fNumNonPurgeable = 0;
             fScratch = 0;
-            fExternal = 0;
-            fBorrowed = 0;
-            fAdopted = 0;
+            fWrapped = 0;
             fUnbudgetedSize = 0;
         }
 
@@ -210,14 +206,8 @@
             if (resource->cacheAccess().isScratch()) {
                 ++fScratch;
             }
-            if (resource->resourcePriv().isExternal()) {
-                ++fExternal;
-            }
-            if (resource->cacheAccess().isBorrowed()) {
-                ++fBorrowed;
-            }
-            if (resource->cacheAccess().isAdopted()) {
-                ++fAdopted;
+            if (resource->resourcePriv().refsWrappedObjects()) {
+                ++fWrapped;
             }
             if (SkBudgeted::kNo  == resource->resourcePriv().isBudgeted()) {
                 fUnbudgetedSize += resource->gpuMemorySize();
diff --git a/src/gpu/GrStencilAttachment.h b/src/gpu/GrStencilAttachment.h
index 2faa7b6..5b7ae63 100644
--- a/src/gpu/GrStencilAttachment.h
+++ b/src/gpu/GrStencilAttachment.h
@@ -52,9 +52,9 @@
                                                   GrUniqueKey* key);
 
 protected:
-    GrStencilAttachment(GrGpu* gpu, LifeCycle lifeCycle, int width, int height, int bits,
+    GrStencilAttachment(GrGpu* gpu, int width, int height, int bits,
                         int sampleCnt)
-        : GrGpuResource(gpu, lifeCycle)
+        : GrGpuResource(gpu)
         , fWidth(width)
         , fHeight(height)
         , fBits(bits)
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 349e6a3..033f1da 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -86,16 +86,10 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////
-GrTexture::GrTexture(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
-                     GrSLType samplerType, bool wasMipMapDataProvided)
-    : INHERITED(gpu, lifeCycle, desc)
+GrTexture::GrTexture(GrGpu* gpu, const GrSurfaceDesc& desc, GrSLType samplerType,
+                     bool wasMipMapDataProvided)
+    : INHERITED(gpu, desc)
     , fSamplerType(samplerType) {
-    if (!this->isExternal() && !GrPixelConfigIsCompressed(desc.fConfig)) {
-        GrScratchKey key;
-        GrTexturePriv::ComputeScratchKey(desc, &key);
-        this->setScratchKey(key);
-    }
-
     if (wasMipMapDataProvided) {
         fMipMapsStatus = kValid_MipMapsStatus;
         fMaxMipMapLevel = SkMipMap::ComputeLevelCount(fDesc.fWidth, fDesc.fHeight);
@@ -105,6 +99,12 @@
     }
 }
 
+void GrTexture::computeScratchKey(GrScratchKey* key) const {
+    if (!GrPixelConfigIsCompressed(fDesc.fConfig)) {
+        GrTexturePriv::ComputeScratchKey(fDesc, key);
+    }
+}
+
 void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* key) {
     static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType();
 
diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp
index 24fd592..37ce273 100644
--- a/src/gpu/gl/GrGLBuffer.cpp
+++ b/src/gpu/gl/GrGLBuffer.cpp
@@ -128,7 +128,7 @@
         }
     }
     VALIDATE();
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 inline GrGLGpu* GrGLBuffer::glGpu() const {
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 3a7f531..d259d2f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -649,13 +649,10 @@
         return nullptr;
     }
 
-    switch (ownership) {
-        case kAdopt_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
-            break;
-        case kBorrow_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
-            break;
+    if (kAdopt_GrWrapOwnership == ownership) {
+        idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
+    } else {
+        idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
     }
 
     surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
@@ -676,13 +673,12 @@
     GrGLTexture* texture = nullptr;
     if (renderTarget) {
         GrGLRenderTarget::IDDesc rtIDDesc;
-        if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
-                                             idDesc.fInfo, &rtIDDesc)) {
+        if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
             return nullptr;
         }
-        texture = new GrGLTextureRenderTarget(this, surfDesc, idDesc, rtIDDesc);
+        texture = GrGLTextureRenderTarget::CreateWrapped(this, surfDesc, idDesc, rtIDDesc);
     } else {
-        texture = new GrGLTexture(this, surfDesc, idDesc);
+        texture = GrGLTexture::CreateWrapped(this, surfDesc, idDesc);
     }
     if (nullptr == texture) {
         return nullptr;
@@ -697,13 +693,10 @@
     idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
     idDesc.fMSColorRenderbufferID = 0;
     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
-    switch (ownership) {
-        case kAdopt_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
-            break;
-        case kBorrow_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
-            break;
+    if (kAdopt_GrWrapOwnership == ownership) {
+        idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
+    } else {
+        idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
     }
     idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig;
 
@@ -765,8 +758,7 @@
     }
 
     GrGLRenderTarget::IDDesc rtIDDesc;
-    if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
-                                         texInfo, &rtIDDesc)) {
+    if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
         return nullptr;
     }
     return GrGLRenderTarget::CreateWrapped(this, surfDesc, rtIDDesc, 0);
@@ -1487,13 +1479,12 @@
 }
 
 bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
-                                        GrGpuResource::LifeCycle lifeCycle,
                                         const GrGLTextureInfo& texInfo,
                                         GrGLRenderTarget::IDDesc* idDesc) {
     idDesc->fMSColorRenderbufferID = 0;
     idDesc->fRTFBOID = 0;
+    idDesc->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
     idDesc->fTexFBOID = 0;
-    idDesc->fLifeCycle = lifeCycle;
     idDesc->fSampleConfig = (GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType() &&
                             desc.fSampleCnt > 0) ? GrRenderTarget::kStencil_SampleConfig :
                                                    GrRenderTarget::kUnified_SampleConfig;
@@ -1605,12 +1596,11 @@
 }
 #endif
 
-static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface,
-                                               GrGpuResource::LifeCycle lifeCycle) {
+static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface) {
     GrGLTexture::IDDesc idDesc;
     idDesc.fInfo.fID = 0;
     GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID));
-    idDesc.fLifeCycle = lifeCycle;
+    idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
     // When we create the texture, we only
     // create GL_TEXTURE_2D at the moment.
     // External clients can do something different.
@@ -1645,7 +1635,7 @@
 }
 
 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
-                                    GrGpuResource::LifeCycle lifeCycle,
+                                    SkBudgeted budgeted,
                                     const SkTArray<GrMipLevel>& texels) {
     // We fail if the MSAA was requested and is not available.
     if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
@@ -1656,7 +1646,7 @@
     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
 
     GrGLTexture::IDDesc idDesc;
-    idDesc.fLifeCycle = lifeCycle;
+    idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
     GrGLTexture::TexParams initialTexParams;
     if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, &initialTexParams, texels)) {
         return return_null_texture();
@@ -1668,17 +1658,17 @@
         GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0));
         GrGLRenderTarget::IDDesc rtIDDesc;
 
-        if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtIDDesc)) {
+        if (!this->createRenderTargetObjects(desc, idDesc.fInfo, &rtIDDesc)) {
             GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
             return return_null_texture();
         }
-        tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc);
+        tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc);
     } else {
         bool wasMipMapDataProvided = false;
         if (texels.count() > 1) {
             wasMipMapDataProvided = true;
         }
-        tex = new GrGLTexture(this, desc, idDesc, wasMipMapDataProvided);
+        tex = new GrGLTexture(this, budgeted, desc, idDesc, wasMipMapDataProvided);
     }
     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
 #ifdef TRACE_TEXTURE_CREATION
@@ -1689,14 +1679,14 @@
 }
 
 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
-                                              GrGpuResource::LifeCycle lifeCycle,
+                                              SkBudgeted budgeted,
                                               const SkTArray<GrMipLevel>& texels) {
     // Make sure that we're not flipping Y.
     if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
         return return_null_texture();
     }
 
-    GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCycle);
+    GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface());
     if (!idDesc.fInfo.fID) {
         return return_null_texture();
     }
@@ -1713,7 +1703,7 @@
     }
 
     GrGLTexture* tex;
-    tex = new GrGLTexture(this, desc, idDesc);
+    tex = new GrGLTexture(this, budgeted, desc, idDesc);
     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
 #ifdef TRACE_TEXTURE_CREATION
     SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n",
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 00ceb85..c6f0f22 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -126,10 +126,10 @@
 
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
 
-    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
+    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                const SkTArray<GrMipLevel>& texels) override;
     GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
-                                         GrGpuResource::LifeCycle lifeCycle,
+                                         SkBudgeted budgeted,
                                          const SkTArray<GrMipLevel>& texels) override;
 
     GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
@@ -347,8 +347,8 @@
                                  int left = 0, int top = 0,
                                  int width = -1, int height = -1);
 
-    bool createRenderTargetObjects(const GrSurfaceDesc&, GrGpuResource::LifeCycle lifeCycle,
-                                   const GrGLTextureInfo& texInfo, GrGLRenderTarget::IDDesc*);
+    bool createRenderTargetObjects(const GrSurfaceDesc&, const GrGLTextureInfo& texInfo,
+                                   GrGLRenderTarget::IDDesc*);
 
     enum TempFBOTarget {
         kSrc_TempFBOTarget,
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
index 4600655..ed5a31d 100644
--- a/src/gpu/gl/GrGLPath.cpp
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -330,11 +330,11 @@
         }
     }
 
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 void GrGLPath::onRelease() {
-    if (0 != fPathID && this->shouldFreeResources()) {
+    if (0 != fPathID) {
         static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fPathID, 1);
         fPathID = 0;
     }
diff --git a/src/gpu/gl/GrGLPathRange.cpp b/src/gpu/gl/GrGLPathRange.cpp
index cc660ed..6ed7bcc 100644
--- a/src/gpu/gl/GrGLPathRange.cpp
+++ b/src/gpu/gl/GrGLPathRange.cpp
@@ -16,7 +16,7 @@
       fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
       fGpuMemorySize(0) {
     this->init();
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
@@ -29,7 +29,7 @@
       fBasePathID(basePathID),
       fGpuMemorySize(gpuMemorySize) {
     this->init();
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 void GrGLPathRange::init() {
@@ -101,7 +101,7 @@
 void GrGLPathRange::onRelease() {
     SkASSERT(this->getGpu());
 
-    if (0 != fBasePathID && this->shouldFreeResources()) {
+    if (0 != fBasePathID) {
         static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
                                                                               this->getNumPaths());
         fBasePathID = 0;
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index b77ec4b..3c27535 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -7,29 +7,31 @@
 
 #include "GrGLRenderTarget.h"
 
-#include "GrRenderTargetPriv.h"
 #include "GrGLGpu.h"
 #include "GrGLUtil.h"
+#include "GrGpuResourcePriv.h"
+#include "GrRenderTargetPriv.h"
 #include "SkTraceMemoryDump.h"
 
 #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
+// Constructor for wrapped render targets.
 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
                                    const GrSurfaceDesc& desc,
                                    const IDDesc& idDesc,
                                    GrGLStencilAttachment* stencil)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig, stencil) {
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, idDesc.fSampleConfig, stencil) {
     this->init(desc, idDesc);
-    this->registerWithCache();
+    this->registerWithCacheWrapped();
 }
 
-GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
-                                   Derived)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
+GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc,
+                                   const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, idDesc.fSampleConfig) {
     this->init(desc, idDesc);
 }
 
@@ -37,7 +39,7 @@
     fRTFBOID                = idDesc.fRTFBOID;
     fTexFBOID               = idDesc.fTexFBOID;
     fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
-    fRTLifecycle            = idDesc.fLifeCycle;
+    fRTFBOOwnership         = idDesc.fRTFBOOwnership;
 
     fViewport.fLeft   = 0;
     fViewport.fBottom = 0;
@@ -127,7 +129,7 @@
 }
 
 void GrGLRenderTarget::onRelease() {
-    if (kBorrowed_LifeCycle != fRTLifecycle) {
+    if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
         if (fTexFBOID) {
             GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
         }
@@ -156,6 +158,13 @@
     return static_cast<GrGLGpu*>(this->getGpu());
 }
 
+bool GrGLRenderTarget::canAttemptStencilAttachment() const {
+    // When we have not created the FBO ID we do not attempt to modify its attachments.
+    // Direct GrGLRenderTarget instances are always created with CreateWrapped.
+    SkASSERT(this->resourcePriv().refsWrappedObjects());
+    return false;
+}
+
 void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
     // Don't log the backing texture's contribution to the memory size. This will be handled by the
     // texture object.
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index d1365ef..edf35a1 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -24,9 +24,9 @@
 
     struct IDDesc {
         GrGLuint                     fRTFBOID;
+        GrBackendObjectOwnership     fRTFBOOwnership;
         GrGLuint                     fTexFBOID;
         GrGLuint                     fMSColorRenderbufferID;
-        GrGpuResource::LifeCycle     fLifeCycle;
         GrRenderTarget::SampleConfig fSampleConfig;
     };
 
@@ -61,21 +61,15 @@
 
     GrBackendObject getRenderTargetHandle() const override { return fRTFBOID; }
 
-    /** When we don't own the FBO ID we don't attempt to modify its attachments. */
-    bool canAttemptStencilAttachment() const override {
-        return kCached_LifeCycle == fRTLifecycle || kUncached_LifeCycle == fRTLifecycle;
-    }
+    bool canAttemptStencilAttachment() const override;
 
     // GrGLRenderTarget overrides dumpMemoryStatistics so it can log its texture and renderbuffer
     // components seperately.
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
 
 protected:
-    // The public constructor registers this object with the cache. However, only the most derived
-    // class should register with the cache. This constructor does not do the registration and
-    // rather moves that burden onto the derived class.
-    enum Derived { kDerived };
-    GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, Derived);
+    // Constructor for subclasses.
+    GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
 
     void init(const GrSurfaceDesc&, const IDDesc&);
 
@@ -86,8 +80,7 @@
     size_t onGpuMemorySize() const override;
 
 private:
-    // This ctor is used only for creating wrapped render targets and is only called for the static
-    // create function CreateWrapped(...).
+    // Constructor for instances wrapping backend objects.
     GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrGLStencilAttachment*);
 
     GrGLGpu* getGLGpu() const;
@@ -103,9 +96,7 @@
     GrGLuint    fTexFBOID;
     GrGLuint    fMSColorRenderbufferID;
 
-    // We track this separately from GrGpuResource because this may be both a texture and a render
-    // target, and the texture may be wrapped while the render target is not.
-    LifeCycle   fRTLifecycle;
+    GrBackendObjectOwnership fRTFBOOwnership;
 
     // when we switch to this render target we want to set the viewport to
     // only render to content area (as opposed to the whole allocation) and
diff --git a/src/gpu/gl/GrGLStencilAttachment.cpp b/src/gpu/gl/GrGLStencilAttachment.cpp
index 15e531b..aa813ed 100644
--- a/src/gpu/gl/GrGLStencilAttachment.cpp
+++ b/src/gpu/gl/GrGLStencilAttachment.cpp
@@ -19,7 +19,7 @@
 }
 
 void GrGLStencilAttachment::onRelease() {
-    if (0 != fRenderbufferID && this->shouldFreeResources()) {
+    if (0 != fRenderbufferID) {
         GrGLGpu* gpuGL = (GrGLGpu*) this->getGpu();
         const GrGLInterface* gl = gpuGL->glInterface();
         GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID));
diff --git a/src/gpu/gl/GrGLStencilAttachment.h b/src/gpu/gl/GrGLStencilAttachment.h
index 3b89a5a..f578bf8 100644
--- a/src/gpu/gl/GrGLStencilAttachment.h
+++ b/src/gpu/gl/GrGLStencilAttachment.h
@@ -24,20 +24,19 @@
     };
 
     struct IDDesc {
-        IDDesc() : fRenderbufferID(0), fLifeCycle(kCached_LifeCycle) {}
+        IDDesc() : fRenderbufferID(0) {}
         GrGLuint fRenderbufferID;
-        GrGpuResource::LifeCycle fLifeCycle;
     };
 
     GrGLStencilAttachment(GrGpu* gpu,
-                      const IDDesc& idDesc,
-                      int width, int height,
-                      int sampleCnt,
-                      const Format& format)
-        : GrStencilAttachment(gpu, idDesc.fLifeCycle, width, height, format.fStencilBits, sampleCnt)
+                          const IDDesc& idDesc,
+                          int width, int height,
+                          int sampleCnt,
+                          const Format& format)
+        : GrStencilAttachment(gpu, width, height, format.fStencilBits, sampleCnt)
         , fFormat(format)
         , fRenderbufferID(idDesc.fRenderbufferID) {
-        this->registerWithCache();
+        this->registerWithCache(SkBudgeted::kYes);
     }
 
     GrGLuint renderbufferID() const {
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index ea02274..6c8f901 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -26,24 +26,33 @@
 }
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), false) {
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
+                         const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
     this->init(desc, idDesc);
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
 }
 
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
+                         const IDDesc& idDesc,
                          bool wasMipMapDataProvided)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) {
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) {
     this->init(desc, idDesc);
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
 }
 
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, Derived)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), false) {
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
+    this->init(desc, idDesc);
+    this->registerWithCacheWrapped();
+}
+
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
     this->init(desc, idDesc);
 }
 
@@ -52,12 +61,12 @@
     fTexParams.invalidate();
     fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
     fInfo = idDesc.fInfo;
-    fTextureIDLifecycle = idDesc.fLifeCycle;
+    fTextureIDOwnership = idDesc.fOwnership;
 }
 
 void GrGLTexture::onRelease() {
     if (fInfo.fID) {
-        if (GrGpuResource::kBorrowed_LifeCycle != fTextureIDLifecycle) {
+        if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) {
             GL_CALL(DeleteTextures(1, &fInfo.fID));
         }
         fInfo.fID = 0;
@@ -86,3 +95,9 @@
     traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
                                       texture_id.c_str());
 }
+
+GrGLTexture* GrGLTexture::CreateWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
+                                        const IDDesc& idDesc) {
+    return new GrGLTexture(gpu, kWrapped, desc, idDesc);
+}
+
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index 6ee8dcf..05d26c8 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -16,7 +16,6 @@
 class GrGLGpu;
 
 class GrGLTexture : public GrTexture {
-
 public:
     struct TexParams {
         GrGLenum fMinFilter;
@@ -31,11 +30,11 @@
 
     struct IDDesc {
         GrGLTextureInfo             fInfo;
-        GrGpuResource::LifeCycle    fLifeCycle;
+        GrBackendObjectOwnership    fOwnership;
     };
-
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, bool wasMipMapDataProvided);
+    GrGLTexture(GrGLGpu*, SkBudgeted, const GrSurfaceDesc&, const IDDesc&);
+    GrGLTexture(GrGLGpu*, SkBudgeted, const GrSurfaceDesc&, const IDDesc&,
+                bool wasMipMapDataProvided);
 
     GrBackendObject getTextureHandle() const override;
 
@@ -57,12 +56,14 @@
 
     GrGLenum target() const { return fInfo.fTarget; }
 
+    static GrGLTexture* CreateWrapped(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
 protected:
-    // The public constructor registers this object with the cache. However, only the most derived
-    // class should register with the cache. This constructor does not do the registration and
-    // rather moves that burden onto the derived class.
-    enum Derived { kDerived };
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, Derived);
+    // Constructor for subclasses.
+    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
+
+    enum Wrapped { kWrapped };
+    // Constructor for instances wrapping backend objects.
+    GrGLTexture(GrGLGpu*, Wrapped, const GrSurfaceDesc&, const IDDesc&);
 
     void init(const GrSurfaceDesc&, const IDDesc&);
 
@@ -77,10 +78,7 @@
     // Holds the texture target and ID. A pointer to this may be shared to external clients for
     // direct interaction with the GL object.
     GrGLTextureInfo                 fInfo;
-
-    // We track this separately from GrGpuResource because this may be both a texture and a render
-    // target, and the texture may be wrapped while the render target is not.
-    LifeCycle                       fTextureIDLifecycle;
+    GrBackendObjectOwnership        fTextureIDOwnership;
 
     typedef GrTexture INHERITED;
 };
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp
index b6068a4..1fa0a21 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.cpp
+++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp
@@ -37,3 +37,16 @@
   traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
                                     texture_id.c_str());
 }
+
+bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const {
+    // The RT FBO of GrGLTextureRenderTarget is never created from a
+    // wrapped FBO.
+    return true;
+}
+
+GrGLTextureRenderTarget* GrGLTextureRenderTarget::CreateWrapped(GrGLGpu* gpu,
+                                                                const GrSurfaceDesc& desc,
+                                                                const GrGLTexture::IDDesc& texIDDesc,
+                                                                const GrGLRenderTarget::IDDesc& rtIDDesc) {
+    return new GrGLTextureRenderTarget(gpu, desc, texIDDesc, rtIDDesc);
+}
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.h b/src/gpu/gl/GrGLTextureRenderTarget.h
index 02db8bc..0826cf3 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.h
+++ b/src/gpu/gl/GrGLTextureRenderTarget.h
@@ -26,17 +26,23 @@
     // We're virtually derived from GrSurface (via both GrGLTexture and GrGLRenderTarget) so its
     // constructor must be explicitly called.
     GrGLTextureRenderTarget(GrGLGpu* gpu,
+                            SkBudgeted budgeted,
                             const GrSurfaceDesc& desc,
                             const GrGLTexture::IDDesc& texIDDesc,
                             const GrGLRenderTarget::IDDesc& rtIDDesc)
-        : GrSurface(gpu, texIDDesc.fLifeCycle, desc)
-        , GrGLTexture(gpu, desc, texIDDesc, GrGLTexture::kDerived)
-        , GrGLRenderTarget(gpu, desc, rtIDDesc, GrGLRenderTarget::kDerived) {
-        this->registerWithCache();
+        : GrSurface(gpu, desc)
+        , GrGLTexture(gpu, desc, texIDDesc)
+        , GrGLRenderTarget(gpu, desc, rtIDDesc) {
+        this->registerWithCache(budgeted);
     }
 
+    bool canAttemptStencilAttachment() const override;
+
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
 
+    static GrGLTextureRenderTarget* CreateWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
+                                                  const GrGLTexture::IDDesc& texIDDesc,
+                                                  const GrGLRenderTarget::IDDesc& rtIDDesc);
 protected:
     void onAbandon() override {
         GrGLRenderTarget::onAbandon();
@@ -49,6 +55,17 @@
     }
 
 private:
+    // Constructor for instances wrapping backend objects.
+    GrGLTextureRenderTarget(GrGLGpu* gpu,
+                            const GrSurfaceDesc& desc,
+                            const GrGLTexture::IDDesc& texIDDesc,
+                            const GrGLRenderTarget::IDDesc& rtIDDesc)
+        : GrSurface(gpu, desc)
+        , GrGLTexture(gpu, desc, texIDDesc)
+        , GrGLRenderTarget(gpu, desc, rtIDDesc) {
+        this->registerWithCacheWrapped();
+    }
+
     // GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory.
     size_t onGpuMemorySize() const override {
         return GrGLRenderTarget::onGpuMemorySize();
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index eebb589..4d0ecbf 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -438,7 +438,7 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
+GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                     const SkTArray<GrMipLevel>& texels) {
     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
 
@@ -493,10 +493,10 @@
 
     GrVkTexture* tex;
     if (renderTarget) {
-        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, desc, lifeCycle,
+        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
                                                                     imageDesc);
     } else {
-        tex = GrVkTexture::CreateNewTexture(this, desc, lifeCycle, imageDesc);
+        tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
     }
 
     if (!tex) {
@@ -548,10 +548,6 @@
         return nullptr;
     }
 
-    GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership)
-                                         ? GrGpuResource::kAdopted_LifeCycle
-                                         : GrGpuResource::kBorrowed_LifeCycle;
-
     GrSurfaceDesc surfDesc;
     // next line relies on GrBackendTextureDesc's flags matching GrTexture's
     surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
@@ -567,11 +563,10 @@
     GrVkTexture* texture = nullptr;
     if (renderTarget) {
         texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
-                                                                            lifeCycle, format,
+                                                                            ownership, format,
                                                                             info);
     } else {
-        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, lifeCycle, format,
-                                                    info);
+        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, format, info);
     }
     if (!texture) {
         return nullptr;
@@ -590,10 +585,6 @@
         return nullptr;
     }
 
-    GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership)
-                                         ? GrGpuResource::kAdopted_LifeCycle
-                                         : GrGpuResource::kBorrowed_LifeCycle;
-
     GrSurfaceDesc desc;
     desc.fConfig = wrapDesc.fConfig;
     desc.fFlags = kCheckAllocation_GrSurfaceFlag;
@@ -604,7 +595,7 @@
     desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
 
     GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
-                                                                        lifeCycle,
+                                                                        ownership,
                                                                         info);
     if (tgt && wrapDesc.fStencilBits) {
         if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
@@ -652,7 +643,6 @@
     const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
 
     GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
-                                                                 GrGpuResource::kCached_LifeCycle,
                                                                  width,
                                                                  height,
                                                                  samples,
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 76b18ac..da9d8b6 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -117,10 +117,10 @@
 
     void onResetContext(uint32_t resetBits) override {}
 
-    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
+    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                const SkTArray<GrMipLevel>&) override;
 
-    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
+    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, SkBudgeted,
                                          const SkTArray<GrMipLevel>&) override { return NULL; }
 
     GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override;
diff --git a/src/gpu/vk/GrVkIndexBuffer.cpp b/src/gpu/vk/GrVkIndexBuffer.cpp
index 02e100d..c641318 100644
--- a/src/gpu/vk/GrVkIndexBuffer.cpp
+++ b/src/gpu/vk/GrVkIndexBuffer.cpp
@@ -13,7 +13,7 @@
     : INHERITED(gpu, desc.fSizeInBytes, kIndex_GrBufferType,
                 desc.fDynamic ? kDynamic_GrAccessPattern : kStatic_GrAccessPattern, false)
     , GrVkBuffer(desc, bufferResource) {
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 GrVkIndexBuffer* GrVkIndexBuffer::Create(GrVkGpu* gpu, size_t size, bool dynamic) {
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 4d84455..8ad3968 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -22,16 +22,16 @@
 // We're virtually derived from GrSurface (via GrRenderTarget) so its
 // constructor must be explicitly called.
 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
+                                   SkBudgeted budgeted,
                                    const GrSurfaceDesc& desc,
-                                   GrGpuResource::LifeCycle lifeCycle,
                                    const GrVkImage::Resource* imageResource,
                                    const GrVkImage::Resource* msaaResource,
                                    const GrVkImageView* colorAttachmentView,
                                    const GrVkImageView* resolveAttachmentView)
-    : GrSurface(gpu, lifeCycle, desc)
+    : GrSurface(gpu, desc)
     , GrVkImage(imageResource)
     // for the moment we only support 1:1 color to stencil
-    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
+    , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
     , fFramebuffer(nullptr)
     , fColorAttachmentView(colorAttachmentView)
     , fMSAAImageResource(msaaResource)
@@ -41,7 +41,7 @@
     // The plus 1 is to account for the resolve texture.
     fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
     this->createFramebuffer(gpu);
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
     msaaResource->ref();
 }
 
@@ -49,16 +49,14 @@
 // constructor must be explicitly called.
 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                    const GrSurfaceDesc& desc,
-                                   GrGpuResource::LifeCycle lifeCycle,
                                    const GrVkImage::Resource* imageResource,
                                    const GrVkImage::Resource* msaaResource,
                                    const GrVkImageView* colorAttachmentView,
-                                   const GrVkImageView* resolveAttachmentView,
-                                   Derived)
-    : GrSurface(gpu, lifeCycle, desc)
+                                   const GrVkImageView* resolveAttachmentView)
+    : GrSurface(gpu, desc)
     , GrVkImage(imageResource)
     // for the moment we only support 1:1 color to stencil
-    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
+    , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
     , fFramebuffer(nullptr)
     , fColorAttachmentView(colorAttachmentView)
     , fMSAAImageResource(msaaResource)
@@ -74,13 +72,13 @@
 // We're virtually derived from GrSurface (via GrRenderTarget) so its
 // constructor must be explicitly called.
 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
+                                   SkBudgeted budgeted,
                                    const GrSurfaceDesc& desc,
-                                   GrGpuResource::LifeCycle lifeCycle,
                                    const GrVkImage::Resource* imageResource,
                                    const GrVkImageView* colorAttachmentView)
-    : GrSurface(gpu, lifeCycle, desc)
+    : GrSurface(gpu, desc)
     , GrVkImage(imageResource)
-    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
+    , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
     , fFramebuffer(nullptr)
     , fColorAttachmentView(colorAttachmentView)
     , fMSAAImageResource(nullptr)
@@ -89,20 +87,18 @@
     SkASSERT(!desc.fSampleCnt);
     fColorValuesPerPixel = 1;
     this->createFramebuffer(gpu);
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
 }
 
 // We're virtually derived from GrSurface (via GrRenderTarget) so its
 // constructor must be explicitly called.
 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                    const GrSurfaceDesc& desc,
-                                   GrGpuResource::LifeCycle lifeCycle,
                                    const GrVkImage::Resource* imageResource,
-                                   const GrVkImageView* colorAttachmentView,
-                                   Derived)
-    : GrSurface(gpu, lifeCycle, desc)
+                                   const GrVkImageView* colorAttachmentView)
+    : GrSurface(gpu, desc)
     , GrVkImage(imageResource)
-    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
+    , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
     , fFramebuffer(nullptr)
     , fColorAttachmentView(colorAttachmentView)
     , fMSAAImageResource(nullptr)
@@ -115,8 +111,8 @@
 
 GrVkRenderTarget*
 GrVkRenderTarget::Create(GrVkGpu* gpu,
+                         SkBudgeted budgeted,
                          const GrSurfaceDesc& desc,
-                         GrGpuResource::LifeCycle lifeCycle,
                          const GrVkImage::Resource* imageResource) {
     VkFormat pixelFormat;
     GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
@@ -172,11 +168,11 @@
 
     GrVkRenderTarget* texRT;
     if (msaaResource) {
-        texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, msaaResource,
+        texRT = new GrVkRenderTarget(gpu, budgeted, desc, imageResource, msaaResource,
                                      colorAttachmentView, resolveAttachmentView);
         msaaResource->unref(gpu);
     } else {
-        texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource,
+        texRT = new GrVkRenderTarget(gpu, budgeted, desc, imageResource,
                                      colorAttachmentView);
     }
 
@@ -185,8 +181,8 @@
 
 GrVkRenderTarget*
 GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
+                                        SkBudgeted budgeted,
                                         const GrSurfaceDesc& desc,
-                                        GrGpuResource::LifeCycle lifeCycle,
                                         const GrVkImage::ImageDesc& imageDesc) {
     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
 
@@ -195,7 +191,7 @@
         return nullptr;
     }
 
-    GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
+    GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, budgeted, desc, imageResource);
     // Create() will increment the refCount of the image resource if it succeeds
     imageResource->unref(gpu);
     return rt;
@@ -204,18 +200,18 @@
 GrVkRenderTarget*
 GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
                                             const GrSurfaceDesc& desc,
-                                            GrGpuResource::LifeCycle lifeCycle,
+                                            GrWrapOwnership ownership,
                                             const GrVkTextureInfo* info) {
     SkASSERT(info);
     // We can wrap a rendertarget without its allocation, as long as we don't take ownership
     SkASSERT(VK_NULL_HANDLE != info->fImage);
-    SkASSERT(VK_NULL_HANDLE != info->fAlloc || kAdopted_LifeCycle != lifeCycle);
+    SkASSERT(VK_NULL_HANDLE != info->fAlloc || kAdopt_GrWrapOwnership != ownership);
 
     GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling)
                                      ? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
 
     const GrVkImage::Resource* imageResource;
-    if (kBorrowed_LifeCycle == lifeCycle) {
+    if (kBorrow_GrWrapOwnership == ownership) {
         imageResource = new GrVkImage::BorrowedResource(info->fImage,
                                                         info->fAlloc,
                                                         flags,
@@ -227,7 +223,7 @@
         return nullptr;
     }
 
-    GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
+    GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, SkBudgeted::kNo, desc, imageResource);
     if (rt) {
         rt->fCurrentLayout = info->fImageLayout;
     }
@@ -367,12 +363,7 @@
 
 void GrVkRenderTarget::onRelease() {
     this->releaseInternalObjects();
-    if (this->shouldFreeResources()) {
-        this->releaseImage(this->getVkGpu());
-    } else {
-        this->abandonImage();
-    }
-
+    this->releaseImage(this->getVkGpu());
     GrRenderTarget::onRelease();
 }
 
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index f8c08e6..8c720ae 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -30,12 +30,11 @@
 
 class GrVkRenderTarget: public GrRenderTarget, public virtual GrVkImage {
 public:
-    static GrVkRenderTarget* CreateNewRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
-                                                   GrGpuResource::LifeCycle,
+    static GrVkRenderTarget* CreateNewRenderTarget(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&,
                                                    const GrVkImage::ImageDesc&);
 
     static GrVkRenderTarget* CreateWrappedRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
-                                                       GrGpuResource::LifeCycle,
+                                                       GrWrapOwnership,
                                                        const GrVkTextureInfo*);
 
     ~GrVkRenderTarget() override;
@@ -67,11 +66,9 @@
     void addResources(GrVkCommandBuffer& commandBuffer) const;
 
 protected:
-    enum Derived { kDerived };
-
     GrVkRenderTarget(GrVkGpu* gpu,
+                     SkBudgeted,
                      const GrSurfaceDesc& desc,
-                     GrGpuResource::LifeCycle,
                      const GrVkImage::Resource* imageResource,
                      const GrVkImage::Resource* msaaImageResource,
                      const GrVkImageView* colorAttachmentView,
@@ -79,28 +76,23 @@
 
     GrVkRenderTarget(GrVkGpu* gpu,
                      const GrSurfaceDesc& desc,
-                     GrGpuResource::LifeCycle,
                      const GrVkImage::Resource* imageResource,
                      const GrVkImage::Resource* msaaImageResource,
                      const GrVkImageView* colorAttachmentView,
-                     const GrVkImageView* resolveAttachmentView,
-                     Derived);
+                     const GrVkImageView* resolveAttachmentView);
 
     GrVkRenderTarget(GrVkGpu* gpu,
+                     SkBudgeted,
                      const GrSurfaceDesc& desc,
-                     GrGpuResource::LifeCycle,
                      const GrVkImage::Resource* imageResource,
                      const GrVkImageView* colorAttachmentView);
 
     GrVkRenderTarget(GrVkGpu* gpu,
                      const GrSurfaceDesc& desc,
-                     GrGpuResource::LifeCycle,
                      const GrVkImage::Resource* imageResource,
-                     const GrVkImageView* colorAttachmentView,
-                     Derived);
+                     const GrVkImageView* colorAttachmentView);
 
-    static GrVkRenderTarget* Create(GrVkGpu*, const GrSurfaceDesc&,
-                                    GrGpuResource::LifeCycle,
+    static GrVkRenderTarget* Create(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&,
                                     const GrVkImage::Resource* imageResource);
 
     GrVkGpu* getVkGpu() const;
diff --git a/src/gpu/vk/GrVkStencilAttachment.cpp b/src/gpu/vk/GrVkStencilAttachment.cpp
index a3d3af3..3af5488 100644
--- a/src/gpu/vk/GrVkStencilAttachment.cpp
+++ b/src/gpu/vk/GrVkStencilAttachment.cpp
@@ -14,22 +14,20 @@
 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
 
 GrVkStencilAttachment::GrVkStencilAttachment(GrVkGpu* gpu,
-                                             GrGpuResource::LifeCycle lifeCycle,
                                              const Format& format,
                                              const GrVkImage::ImageDesc& desc,
                                              const GrVkImage::Resource* imageResource,
                                              const GrVkImageView* stencilView)
-    : GrStencilAttachment(gpu, lifeCycle, desc.fWidth, desc.fHeight,
+    : GrStencilAttachment(gpu, desc.fWidth, desc.fHeight,
                           format.fStencilBits, desc.fSamples)
     , GrVkImage(imageResource)
     , fFormat(format)
     , fStencilView(stencilView) {
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
     stencilView->ref();
 }
 
 GrVkStencilAttachment* GrVkStencilAttachment::Create(GrVkGpu* gpu,
-                                                     GrGpuResource::LifeCycle lifeCycle,
                                                      int width,
                                                      int height,
                                                      int sampleCnt,
@@ -59,7 +57,7 @@
         return nullptr;
     }
 
-    GrVkStencilAttachment* stencil = new GrVkStencilAttachment(gpu, lifeCycle, format, imageDesc,
+    GrVkStencilAttachment* stencil = new GrVkStencilAttachment(gpu, format, imageDesc,
                                                                imageResource, imageView);
     imageResource->unref(gpu);
     imageView->unref(gpu);
diff --git a/src/gpu/vk/GrVkStencilAttachment.h b/src/gpu/vk/GrVkStencilAttachment.h
index 282fdf7..f106c69 100644
--- a/src/gpu/vk/GrVkStencilAttachment.h
+++ b/src/gpu/vk/GrVkStencilAttachment.h
@@ -24,8 +24,7 @@
         bool fPacked;
     };
 
-    static GrVkStencilAttachment* Create(GrVkGpu* gpu, GrGpuResource::LifeCycle lifeCycle,
-                                         int width, int height,
+    static GrVkStencilAttachment* Create(GrVkGpu* gpu, int width, int height,
                                          int sampleCnt, const Format& format);
 
     ~GrVkStencilAttachment() override;
@@ -43,7 +42,6 @@
     size_t onGpuMemorySize() const override;
 
     GrVkStencilAttachment(GrVkGpu* gpu,
-                          GrGpuResource::LifeCycle lifeCycle,
                           const Format& format,
                           const GrVkImage::ImageDesc&,
                           const GrVkImage::Resource*,
diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp
index 8dcc368..cdbc84f 100644
--- a/src/gpu/vk/GrVkTexture.cpp
+++ b/src/gpu/vk/GrVkTexture.cpp
@@ -16,35 +16,47 @@
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
+                         SkBudgeted budgeted,
                          const GrSurfaceDesc& desc,
-                         GrGpuResource::LifeCycle lifeCycle,
                          const GrVkImage::Resource* imageResource,
                          const GrVkImageView* view)
-    : GrSurface(gpu, lifeCycle, desc)
+    : GrSurface(gpu, desc)
     , GrVkImage(imageResource)
-    , INHERITED(gpu, lifeCycle, desc, kSampler2D_GrSLType,
+    , INHERITED(gpu, desc, kSampler2D_GrSLType,
                 false) // false because we don't upload MIP data in Vk yet
     , fTextureView(view) {
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
+}
+
+GrVkTexture::GrVkTexture(GrVkGpu* gpu,
+                         Wrapped,
+                         const GrSurfaceDesc& desc,
+                         const GrVkImage::Resource* imageResource,
+                         const GrVkImageView* view)
+    : GrSurface(gpu, desc)
+    , GrVkImage(imageResource)
+    , INHERITED(gpu, desc, kSampler2D_GrSLType,
+                false) // false because we don't upload MIP data in Vk yet
+    , fTextureView(view) {
+    this->registerWithCacheWrapped();
 }
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
                          const GrSurfaceDesc& desc,
-                         GrGpuResource::LifeCycle lifeCycle,
                          const GrVkImage::Resource* imageResource,
-                         const GrVkImageView* view,
-                         Derived)
-    : GrSurface(gpu, lifeCycle, desc)
+                         const GrVkImageView* view)
+    : GrSurface(gpu, desc)
     , GrVkImage(imageResource)
-    , INHERITED(gpu, lifeCycle, desc, kSampler2D_GrSLType,
+    , INHERITED(gpu, desc, kSampler2D_GrSLType,
                 false) // false because we don't upload MIP data in Vk yet
     , fTextureView(view) {}
 
 
+template<typename ResourceType>
 GrVkTexture* GrVkTexture::Create(GrVkGpu* gpu,
+                                 ResourceType type,
                                  const GrSurfaceDesc& desc,
-                                 GrGpuResource::LifeCycle lifeCycle,
                                  VkFormat format,
                                  const GrVkImage::Resource* imageResource) {
     VkImage image = imageResource->fImage;
@@ -54,11 +66,11 @@
         return nullptr;
     }
 
-    return new GrVkTexture(gpu, desc, lifeCycle, imageResource, imageView);
+    return new GrVkTexture(gpu, type, desc, imageResource, imageView);
 }
 
-GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
-                                           GrGpuResource::LifeCycle lifeCycle,
+GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
+                                           const GrSurfaceDesc& desc,
                                            const GrVkImage::ImageDesc& imageDesc) {
     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
 
@@ -67,15 +79,16 @@
         return nullptr;
     }
 
-    GrVkTexture* texture = Create(gpu, desc, lifeCycle, imageDesc.fFormat, imageResource);
+    GrVkTexture* texture = Create(gpu, budgeted, desc, imageDesc.fFormat, imageResource);
     // Create() will increment the refCount of the image resource if it succeeds
     imageResource->unref(gpu);
 
     return texture;
 }
 
-GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
-                                               GrGpuResource::LifeCycle lifeCycle,
+GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu,
+                                               const GrSurfaceDesc& desc,
+                                               GrWrapOwnership ownership,
                                                VkFormat format,
                                                const GrVkTextureInfo* info) {
     SkASSERT(info);
@@ -86,7 +99,7 @@
                                      ? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
 
     const GrVkImage::Resource* imageResource;
-    if (kBorrowed_LifeCycle == lifeCycle) {
+    if (kBorrow_GrWrapOwnership == ownership) {
         imageResource = new GrVkImage::BorrowedResource(info->fImage,
                                                         info->fAlloc,
                                                         flags,
@@ -98,7 +111,7 @@
         return nullptr;
     }
 
-    GrVkTexture* texture = Create(gpu, desc, lifeCycle, format, imageResource);
+    GrVkTexture* texture = Create(gpu, kWrapped, desc, format, imageResource);
     if (texture) {
         texture->fCurrentLayout = info->fImageLayout;
     }
@@ -120,11 +133,7 @@
         fTextureView = nullptr;
     }
 
-    if (this->shouldFreeResources()) {
-        this->releaseImage(this->getVkGpu());
-    } else {
-        this->abandonImage();
-    }
+    this->releaseImage(this->getVkGpu());
 
     INHERITED::onRelease();
 }
diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h
index 7c476ca..936eeb7 100644
--- a/src/gpu/vk/GrVkTexture.h
+++ b/src/gpu/vk/GrVkTexture.h
@@ -18,12 +18,11 @@
 
 class GrVkTexture : public GrTexture, public virtual GrVkImage {
 public:
-    static GrVkTexture* CreateNewTexture(GrVkGpu*, const GrSurfaceDesc&,
-                                         GrGpuResource::LifeCycle,
+    static GrVkTexture* CreateNewTexture(GrVkGpu*, SkBudgeted budgeted, const GrSurfaceDesc&,
                                          const GrVkImage::ImageDesc&);
 
     static GrVkTexture* CreateWrappedTexture(GrVkGpu*, const GrSurfaceDesc&,
-                                             GrGpuResource::LifeCycle,
+                                             GrWrapOwnership,
                                              VkFormat, const GrVkTextureInfo*);
 
     ~GrVkTexture() override;
@@ -35,16 +34,11 @@
     const GrVkImageView* textureView() const { return fTextureView; }
 
 protected:
-    enum Derived { kDerived };
-
-    GrVkTexture(GrVkGpu*, const GrSurfaceDesc&, GrGpuResource::LifeCycle,
+    GrVkTexture(GrVkGpu*, const GrSurfaceDesc&,
                 const GrVkImage::Resource*, const GrVkImageView* imageView);
 
-    GrVkTexture(GrVkGpu*, const GrSurfaceDesc&, GrGpuResource::LifeCycle,
-                const GrVkImage::Resource*, const GrVkImageView* imageView, Derived);
-
-    static GrVkTexture* Create(GrVkGpu*, const GrSurfaceDesc&,
-                               GrGpuResource::LifeCycle, VkFormat,
+    template<typename ResourceType>
+    static GrVkTexture* Create(GrVkGpu*, ResourceType, const GrSurfaceDesc&, VkFormat,
                                const GrVkImage::Resource* texImpl);
 
     GrVkGpu* getVkGpu() const;
@@ -53,6 +47,13 @@
     void onRelease() override;
 
 private:
+    enum Wrapped { kWrapped };
+    GrVkTexture(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&,
+                const GrVkImage::Resource*, const GrVkImageView* imageView);
+    GrVkTexture(GrVkGpu*, Wrapped, const GrSurfaceDesc&,
+                const GrVkImage::Resource*, const GrVkImageView* imageView);
+
+
     const GrVkImageView* fTextureView;
 
     typedef GrTexture INHERITED;
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp
index 7c085a3..6bfdf3e 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -16,13 +16,12 @@
 
 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
 
-GrVkTextureRenderTarget*
-GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
-                                const GrSurfaceDesc& desc,
-                                GrGpuResource::LifeCycle lifeCycle,
-                                VkFormat format,
-                                const GrVkImage::Resource* imageResource) {
-
+template<typename ResourceType>
+GrVkTextureRenderTarget* GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
+                                                         ResourceType resourceType,
+                                                         const GrSurfaceDesc& desc,
+                                                         VkFormat format,
+                                                         const GrVkImage::Resource* imageResource) {
     VkImage image = imageResource->fImage;
     // Create the texture ImageView
     const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, format,
@@ -99,16 +98,15 @@
             return nullptr;
         }
     }
-
     GrVkTextureRenderTarget* texRT;
     if (msaaImageResource) {
-        texRT = new GrVkTextureRenderTarget(gpu, desc, lifeCycle,
+        texRT = new GrVkTextureRenderTarget(gpu, resourceType, desc,
                                             imageResource, imageView, msaaImageResource,
                                             colorAttachmentView,
                                             resolveAttachmentView);
         msaaImageResource->unref(gpu);
     } else {
-        texRT = new GrVkTextureRenderTarget(gpu, desc, lifeCycle,
+        texRT = new GrVkTextureRenderTarget(gpu, resourceType, desc,
                                             imageResource, imageView,
                                             colorAttachmentView);
     }
@@ -117,9 +115,9 @@
 
 GrVkTextureRenderTarget*
 GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
-                                                     const GrSurfaceDesc& desc,
-                                                     GrGpuResource::LifeCycle lifeCycle,
-                                                     const GrVkImage::ImageDesc& imageDesc) {
+                                                      SkBudgeted budgeted,
+                                                      const GrSurfaceDesc& desc,
+                                                      const GrVkImage::ImageDesc& imageDesc) {
     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
 
@@ -129,8 +127,8 @@
         return nullptr;
     }
 
-    GrVkTextureRenderTarget* trt = GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle,
-                                                                   imageDesc.fFormat, imageRsrc);
+    GrVkTextureRenderTarget* trt = Create(gpu, budgeted, desc, imageDesc.fFormat,
+                                          imageRsrc);
     // Create() will increment the refCount of the image resource if it succeeds
     imageRsrc->unref(gpu);
 
@@ -140,7 +138,7 @@
 GrVkTextureRenderTarget*
 GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(GrVkGpu* gpu,
                                                           const GrSurfaceDesc& desc,
-                                                          GrGpuResource::LifeCycle lifeCycle,
+                                                          GrWrapOwnership ownership,
                                                           VkFormat format,
                                                           const GrVkTextureInfo* info) {
     SkASSERT(info);
@@ -151,7 +149,7 @@
                                      ? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
 
     const GrVkImage::Resource* imageResource;
-    if (kBorrowed_LifeCycle == lifeCycle) {
+    if (kBorrow_GrWrapOwnership == ownership) {
         imageResource = new GrVkImage::BorrowedResource(info->fImage,
                                                         info->fAlloc,
                                                         flags,
@@ -162,9 +160,7 @@
     if (!imageResource) {
         return nullptr;
     }
-
-    GrVkTextureRenderTarget* trt = GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle,
-                                                                   format, imageResource);
+    GrVkTextureRenderTarget* trt = Create(gpu, kWrapped, desc, format, imageResource);
     if (trt) {
         trt->fCurrentLayout = info->fImageLayout;
     }
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.h b/src/gpu/vk/GrVkTextureRenderTarget.h
index f2580eb..e888397 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.h
+++ b/src/gpu/vk/GrVkTextureRenderTarget.h
@@ -24,13 +24,13 @@
 
 class GrVkTextureRenderTarget: public GrVkTexture, public GrVkRenderTarget {
 public:
-    static GrVkTextureRenderTarget* CreateNewTextureRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
-                                                                 GrGpuResource::LifeCycle,
+    static GrVkTextureRenderTarget* CreateNewTextureRenderTarget(GrVkGpu*, SkBudgeted,
+                                                                 const GrSurfaceDesc&,
                                                                  const GrVkImage::ImageDesc&);
 
     static GrVkTextureRenderTarget* CreateWrappedTextureRenderTarget(GrVkGpu*,
                                                                      const GrSurfaceDesc&,
-                                                                     GrGpuResource::LifeCycle,
+                                                                     GrWrapOwnership,
                                                                      VkFormat,
                                                                      const GrVkTextureInfo*);
 
@@ -47,38 +47,68 @@
 
 private:
     GrVkTextureRenderTarget(GrVkGpu* gpu,
+                            SkBudgeted budgeted,
                             const GrSurfaceDesc& desc,
-                            GrGpuResource::LifeCycle lifeCycle,
                             const GrVkImage::Resource* imageResource,
                             const GrVkImageView* texView,
                             const GrVkImage::Resource* msaaResource,
                             const GrVkImageView* colorAttachmentView,
                             const GrVkImageView* resolveAttachmentView)
-        : GrSurface(gpu, lifeCycle, desc)
+        : GrSurface(gpu, desc)
         , GrVkImage(imageResource)
-        , GrVkTexture(gpu, desc, lifeCycle, imageResource, texView, GrVkTexture::kDerived)
-        , GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, msaaResource, colorAttachmentView,
-                           resolveAttachmentView, GrVkRenderTarget::kDerived) {
-        this->registerWithCache();
+        , GrVkTexture(gpu, desc, imageResource, texView)
+        , GrVkRenderTarget(gpu, desc, imageResource, msaaResource, colorAttachmentView,
+                           resolveAttachmentView) {
+        this->registerWithCache(budgeted);
     }
 
     GrVkTextureRenderTarget(GrVkGpu* gpu,
+                            SkBudgeted budgeted,
                             const GrSurfaceDesc& desc,
-                            GrGpuResource::LifeCycle lifeCycle,
                             const GrVkImage::Resource* imageResource,
                             const GrVkImageView* texView,
                             const GrVkImageView* colorAttachmentView)
-        : GrSurface(gpu, lifeCycle, desc)
+        : GrSurface(gpu, desc)
         , GrVkImage(imageResource)
-        , GrVkTexture(gpu, desc, lifeCycle, imageResource, texView, GrVkTexture::kDerived)
-        , GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, colorAttachmentView,
-                           GrVkRenderTarget::kDerived) {
-        this->registerWithCache();
+        , GrVkTexture(gpu, desc, imageResource, texView)
+        , GrVkRenderTarget(gpu, desc, imageResource, colorAttachmentView) {
+        this->registerWithCache(budgeted);
+    }
+    enum Wrapped { kWrapped };
+    GrVkTextureRenderTarget(GrVkGpu* gpu,
+                            Wrapped,
+                            const GrSurfaceDesc& desc,
+                            const GrVkImage::Resource* imageResource,
+                            const GrVkImageView* texView,
+                            const GrVkImage::Resource* msaaResource,
+                            const GrVkImageView* colorAttachmentView,
+                            const GrVkImageView* resolveAttachmentView)
+        : GrSurface(gpu, desc)
+        , GrVkImage(imageResource)
+        , GrVkTexture(gpu, desc, imageResource, texView)
+        , GrVkRenderTarget(gpu, desc, imageResource, msaaResource, colorAttachmentView,
+                           resolveAttachmentView) {
+        this->registerWithCacheWrapped();
     }
 
-    static GrVkTextureRenderTarget* Create(GrVkGpu*, const GrSurfaceDesc&,
-                                           GrGpuResource::LifeCycle,
-                                           VkFormat format,
+    GrVkTextureRenderTarget(GrVkGpu* gpu,
+                            Wrapped,
+                            const GrSurfaceDesc& desc,
+                            const GrVkImage::Resource* imageResource,
+                            const GrVkImageView* texView,
+                            const GrVkImageView* colorAttachmentView)
+        : GrSurface(gpu, desc)
+        , GrVkImage(imageResource)
+        , GrVkTexture(gpu, desc, imageResource, texView)
+        , GrVkRenderTarget(gpu, desc, imageResource, colorAttachmentView) {
+        this->registerWithCacheWrapped();
+    }
+
+    template <typename ResourceType>
+    static GrVkTextureRenderTarget* Create(GrVkGpu*,
+                                           ResourceType,
+                                           const GrSurfaceDesc&,
+                                           VkFormat,
                                            const GrVkImage::Resource* imageResource);
 
     // GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory.
diff --git a/src/gpu/vk/GrVkTransferBuffer.cpp b/src/gpu/vk/GrVkTransferBuffer.cpp
index 0556111..4cf5c1b 100644
--- a/src/gpu/vk/GrVkTransferBuffer.cpp
+++ b/src/gpu/vk/GrVkTransferBuffer.cpp
@@ -36,7 +36,7 @@
                     kXferCpuToGpu_GrBufferType : kXferGpuToCpu_GrBufferType,
                 kStream_GrAccessPattern, false)
     , GrVkBuffer(desc, bufferResource) {
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 void GrVkTransferBuffer::onRelease() {
diff --git a/src/gpu/vk/GrVkVertexBuffer.cpp b/src/gpu/vk/GrVkVertexBuffer.cpp
index 32fb037..aa41cbb 100644
--- a/src/gpu/vk/GrVkVertexBuffer.cpp
+++ b/src/gpu/vk/GrVkVertexBuffer.cpp
@@ -13,7 +13,7 @@
     : INHERITED(gpu, desc.fSizeInBytes, kVertex_GrBufferType,
                 desc.fDynamic ? kDynamic_GrAccessPattern : kStatic_GrAccessPattern, false)
     , GrVkBuffer(desc, bufferResource) {
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 GrVkVertexBuffer* GrVkVertexBuffer::Create(GrVkGpu* gpu, size_t size, bool dynamic) {
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 2203f47..fa09911 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -85,7 +85,7 @@
     // If the original render target is a buffer originally created by the client, then we don't
     // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
     // copy-on-write.
-    if (kYes_ForceCopyMode == forceCopyMode || !tex || rt->resourcePriv().isExternal()) {
+    if (kYes_ForceCopyMode == forceCopyMode || !tex || rt->resourcePriv().refsWrappedObjects()) {
         GrSurfaceDesc desc = fDevice->accessRenderTarget()->desc();
         GrContext* ctx = fDevice->context();
         desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag;
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 0ac64ed..a733d39 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -249,35 +249,22 @@
      * For example, textures have width, height, ... */
     enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
 
-    TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
-        : INHERITED(gpu, lifeCycle)
+    TestResource(GrGpu* gpu, SkBudgeted budgeted = SkBudgeted::kYes, size_t size = kDefaultSize)
+        : INHERITED(gpu)
         , fToDelete(nullptr)
         , fSize(size)
-        , fProperty(kA_SimulatedProperty) {
+        , fProperty(kA_SimulatedProperty)
+        , fIsScratch(false) {
         ++fNumAlive;
-        this->registerWithCache();
+        this->registerWithCache(budgeted);
     }
 
-    TestResource(GrGpu* gpu, GrGpuResource::LifeCycle lifeCycle)
-        : INHERITED(gpu, lifeCycle)
-        , fToDelete(nullptr)
-        , fSize(kDefaultSize)
-        , fProperty(kA_SimulatedProperty) {
-        ++fNumAlive;
-        this->registerWithCache();
+    static TestResource* CreateScratch(GrGpu* gpu, SkBudgeted budgeted,
+                                       SimulatedProperty property) {
+        return new TestResource(gpu, budgeted, property, kScratchConstructor);
     }
-
-    TestResource(GrGpu* gpu)
-        : INHERITED(gpu, kCached_LifeCycle)
-        , fToDelete(nullptr)
-        , fSize(kDefaultSize)
-        , fProperty(kA_SimulatedProperty) {
-        ++fNumAlive;
-        this->registerWithCache();
-    }
-
-    static TestResource* CreateScratch(GrGpu* gpu, SimulatedProperty property, bool cached = true) {
-        return new TestResource(gpu, property, cached, kScratchConstructor);
+    static TestResource* CreateWrapped(GrGpu* gpu, size_t size = kDefaultSize) {
+        return new TestResource(gpu, size);
     }
 
     ~TestResource() {
@@ -307,20 +294,34 @@
     static size_t ExpectedScratchKeySize() {
         return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
     }
-
 private:
     static const int kScratchKeyFieldCnt = 6;
 
-    TestResource(GrGpu* gpu, SimulatedProperty property, bool cached, ScratchConstructor)
-        : INHERITED(gpu, cached ? kCached_LifeCycle : kUncached_LifeCycle)
+    TestResource(GrGpu* gpu, SkBudgeted budgeted, SimulatedProperty property, ScratchConstructor)
+        : INHERITED(gpu)
         , fToDelete(nullptr)
         , fSize(kDefaultSize)
-        , fProperty(property) {
-        GrScratchKey scratchKey;
-        ComputeScratchKey(fProperty, &scratchKey);
-        this->setScratchKey(scratchKey);
+        , fProperty(property)
+        , fIsScratch(true) {
         ++fNumAlive;
-        this->registerWithCache();
+        this->registerWithCache(budgeted);
+    }
+
+    // Constructor for simulating resources that wrap backend objects.
+    TestResource(GrGpu* gpu, size_t size)
+        : INHERITED(gpu)
+        , fToDelete(nullptr)
+        , fSize(size)
+        , fProperty(kA_SimulatedProperty)
+        , fIsScratch(false) {
+        ++fNumAlive;
+        this->registerWithCacheWrapped();
+    }
+
+    void computeScratchKey(GrScratchKey* key) const override {
+        if (fIsScratch) {
+            ComputeScratchKey(fProperty, key);
+        }
     }
 
     size_t onGpuMemorySize() const override { return fSize; }
@@ -329,6 +330,7 @@
     size_t fSize;
     static int fNumAlive;
     SimulatedProperty fProperty;
+    bool fIsScratch;
     typedef GrGpuResource INHERITED;
 };
 int TestResource::fNumAlive = 0;
@@ -418,15 +420,15 @@
 
     // Create a scratch, a unique, and a wrapped resource
     TestResource* scratch =
-            TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
+            TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes, TestResource::kB_SimulatedProperty);
     scratch->setSize(10);
     TestResource* unique = new TestResource(context->getGpu());
     unique->setSize(11);
     unique->resourcePriv().setUniqueKey(uniqueKey);
-    TestResource* wrapped = new TestResource(context->getGpu(), GrGpuResource::kBorrowed_LifeCycle);
+    TestResource* wrapped = TestResource::CreateWrapped(context->getGpu());
     wrapped->setSize(12);
     TestResource* unbudgeted =
-            new TestResource(context->getGpu(), GrGpuResource::kUncached_LifeCycle);
+            new TestResource(context->getGpu(), SkBudgeted::kNo);
     unbudgeted->setSize(13);
 
     // Make sure we can't add a unique key to the wrapped resource
@@ -461,7 +463,7 @@
                               unbudgeted->gpuMemorySize() == cache->getResourceBytes());
 
     // Now try freeing the budgeted resources first
-    wrapped = new TestResource(context->getGpu(), GrGpuResource::kBorrowed_LifeCycle);
+    wrapped = TestResource::CreateWrapped(context->getGpu());
     scratch->setSize(12);
     unique->unref();
     cache->purgeAllUnlocked();
@@ -506,7 +508,9 @@
     TestResource* unbudgeted;
 
     // A large uncached or wrapped resource shouldn't evict anything.
-    scratch = TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
+    scratch = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
+                                          TestResource::kB_SimulatedProperty);
+
     scratch->setSize(10);
     scratch->unref();
     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
@@ -524,7 +528,7 @@
     REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
 
     size_t large = 2 * cache->getResourceBytes();
-    unbudgeted = new TestResource(context->getGpu(), large, GrGpuResource::kUncached_LifeCycle);
+    unbudgeted = new TestResource(context->getGpu(), SkBudgeted::kNo, large);
     REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
     REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
     REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
@@ -536,7 +540,7 @@
     REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
     REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
 
-    wrapped = new TestResource(context->getGpu(), large, GrGpuResource::kBorrowed_LifeCycle);
+    wrapped = TestResource::CreateWrapped(context->getGpu(), large);
     REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
     REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
     REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
@@ -563,7 +567,8 @@
     GrResourceCache* cache = mock.cache();
 
     TestResource* resource =
-        TestResource::CreateScratch(context->getGpu(), TestResource::kA_SimulatedProperty, false);
+        TestResource::CreateScratch(context->getGpu(), SkBudgeted::kNo,
+                                    TestResource::kA_SimulatedProperty);
     GrScratchKey key;
     TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
 
@@ -623,8 +628,10 @@
 
     // Create two resources that have the same scratch key.
     TestResource* a = TestResource::CreateScratch(context->getGpu(),
+                                                  SkBudgeted::kYes,
                                                   TestResource::kB_SimulatedProperty);
     TestResource* b = TestResource::CreateScratch(context->getGpu(),
+                                                  SkBudgeted::kYes,
                                                   TestResource::kB_SimulatedProperty);
     a->setSize(11);
     b->setSize(12);
@@ -667,9 +674,9 @@
     GrResourceCache* cache = mock.cache();
 
     // Create two resources that have the same scratch key.
-    TestResource* a = TestResource::CreateScratch(context->getGpu(),
+    TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
                                                   TestResource::kB_SimulatedProperty);
-    TestResource* b = TestResource::CreateScratch(context->getGpu(),
+    TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
                                                   TestResource::kB_SimulatedProperty);
     a->unref();
     b->unref();
@@ -726,9 +733,9 @@
     GrResourceCache* cache = mock.cache();
 
     // Create two resources that have the same scratch key.
-    TestResource* a = TestResource::CreateScratch(context->getGpu(),
+    TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
                                                   TestResource::kB_SimulatedProperty);
-    TestResource* b = TestResource::CreateScratch(context->getGpu(),
+    TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
                                                   TestResource::kB_SimulatedProperty);
     a->unref();
     b->unref();
@@ -888,7 +895,7 @@
     // Add three resources to the cache. Only c is usable as scratch.
     TestResource* a = new TestResource(context->getGpu());
     TestResource* b = new TestResource(context->getGpu());
-    TestResource* c = TestResource::CreateScratch(context->getGpu(),
+    TestResource* c = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
                                                   TestResource::kA_SimulatedProperty);
     a->resourcePriv().setUniqueKey(key1);
     b->resourcePriv().setUniqueKey(key2);
diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp
index 5771a78..6f9d2c4 100644
--- a/tools/gpu/GrTest.cpp
+++ b/tools/gpu/GrTest.cpp
@@ -222,10 +222,9 @@
 
     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
     out->appendf("\t\tEntry Count: current %d"
-                 " (%d budgeted, %d external(%d borrowed, %d adopted), %d locked, %d scratch %.2g%% full), high %d\n",
-                 stats.fTotal, fBudgetedCount, stats.fExternal, stats.fBorrowed,
-                 stats.fAdopted, stats.fNumNonPurgeable, stats.fScratch, countUtilization,
-                 fHighWaterCount);
+                 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
+                 stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
+                 stats.fScratch, countUtilization, fHighWaterCount);
     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
@@ -323,12 +322,12 @@
 
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
 
-    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
+    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                const SkTArray<GrMipLevel>& texels) override {
         return nullptr;
     }
 
-    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
+    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                          const SkTArray<GrMipLevel>& texels) override {
         return nullptr;
     }