Revise system for checking for uninstantiated proxies

The new pattern is:
  we will "instantiate" pipelines at flush time
  at flush time we will only access the backing GrSurface by peeking

  If instantiation fails we should never try to access the GrSurfaces


Change-Id: I87f7ff41bd0e84d9ca3dbdd61d3361d3d4ceefd6
Reviewed-on: https://skia-review.googlesource.com/17932
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 2c0d5f0..cd481a1 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -653,7 +653,8 @@
 void GrGLDisplacementMapEffect::onSetData(const GrGLSLProgramDataManager& pdman,
                                           const GrFragmentProcessor& proc) {
     const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
-    GrTexture* colorTex = displacementMap.textureSampler(1).texture();
+    GrTexture* colorTex = displacementMap.textureSampler(1).peekTexture();
+
     SkScalar scaleX = displacementMap.scale().fX / colorTex->width();
     SkScalar scaleY = displacementMap.scale().fY / colorTex->height();
     pdman.set2f(fScaleUni, SkScalarToFloat(scaleX),
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index e6c4661..c856841 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -1932,7 +1932,8 @@
         fLight = lighting.light()->createGLLight();
     }
 
-    GrTexture* texture = lighting.textureSampler(0).texture();
+    GrTexture* texture = lighting.textureSampler(0).peekTexture();
+
     float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
     pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
     pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index 8e289e5..197b805 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -204,8 +204,7 @@
                                     const GrFragmentProcessor& effect) {
     const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>();
 
-    GrTexture* tex = zoom.textureSampler(0).texture();
-    SkASSERT(tex);
+    GrTexture* tex = zoom.textureSampler(0).peekTexture();
 
     SkScalar invW = 1.0f / tex->width();
     SkScalar invH = 1.0f / tex->height();
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index e783488..57abec9 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -294,7 +294,7 @@
 void GrGLMorphologyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
                                      const GrFragmentProcessor& proc) {
     const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
-    GrTexture& texture = *m.textureSampler(0).texture();
+    GrTexture& texture = *m.textureSampler(0).peekTexture();
 
     float pixelSize = 0.0f;
     switch (m.direction()) {
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index b0a36fc..70de165 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -61,11 +61,21 @@
     SkDEBUGCODE(transform->setInProcessor();)
 }
 
-int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
-    if (child->isBad()) {
-        this->markAsBad();
+bool GrFragmentProcessor::instantiate(GrResourceProvider* resourceProvider) const {
+    if (!INHERITED::instantiate(resourceProvider)) {
+        return false;
     }
 
+    for (int i = 0; i < this->numChildProcessors(); ++i) {
+        if (!this->childProcessor(i).instantiate(resourceProvider)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
     this->combineRequiredFeatures(*child);
 
     if (child->usesLocalCoords()) {
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 00f2dbd..ec8f317 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -109,6 +109,8 @@
 
     const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
 
+    bool instantiate(GrResourceProvider*) const;
+
     /** Do any of the coordtransforms for this processor require local coords? */
     bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
 
@@ -345,7 +347,7 @@
      */
     SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors;
 
-    typedef GrProcessor INHERITED;
+    typedef GrResourceIOProcessor INHERITED;
 };
 
 GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp
index ee7414e..043c54f 100644
--- a/src/gpu/GrGpuCommandBuffer.cpp
+++ b/src/gpu/GrGpuCommandBuffer.cpp
@@ -7,6 +7,7 @@
 
 #include "GrGpuCommandBuffer.h"
 
+#include "GrContext.h"
 #include "GrCaps.h"
 #include "GrFixedClip.h"
 #include "GrGpu.h"
@@ -46,7 +47,7 @@
     }
 #endif
 
-    if (pipeline.isBad() || primProc.isBad()) {
+    if (pipeline.isBad() || !primProc.instantiate(this->gpu()->getContext()->resourceProvider())) {
         return false;
     }
 
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index 7c0338c..3bdf3bb 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -62,7 +62,7 @@
     for (int i = 0; i < args.fProcessors->numColorFragmentProcessors(); ++i, ++currFPIdx) {
         const GrFragmentProcessor* fp = args.fProcessors->colorFragmentProcessor(i);
         fFragmentProcessors[currFPIdx].reset(fp);
-        if (fp->isBad()) {
+        if (!fp->instantiate(args.fResourceProvider)) {
             this->markAsBad();
         }
     }
@@ -70,14 +70,14 @@
     for (int i = 0; i < args.fProcessors->numCoverageFragmentProcessors(); ++i, ++currFPIdx) {
         const GrFragmentProcessor* fp = args.fProcessors->coverageFragmentProcessor(i);
         fFragmentProcessors[currFPIdx].reset(fp);
-        if (fp->isBad()) {
+        if (!fp->instantiate(args.fResourceProvider)) {
             this->markAsBad();
         }
     }
     if (args.fAppliedClip) {
         if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) {
             fFragmentProcessors[currFPIdx].reset(fp);
-            if (fp->isBad()) {
+            if (!fp->instantiate(args.fResourceProvider)) {
                 this->markAsBad();
             }
         }
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 67e137c..41f6d59 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -75,6 +75,7 @@
         const GrAppliedClip* fAppliedClip = nullptr;
         GrRenderTarget* fRenderTarget = nullptr;
         const GrCaps* fCaps = nullptr;
+        GrResourceProvider* fResourceProvider = nullptr;
         GrXferProcessor::DstTexture fDstTexture;
     };
 
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index c20ebab..6895eaa 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -129,12 +129,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void GrResourceIOProcessor::addTextureSampler(const TextureSampler* access) {
-    // MDB TODO: this 'isBad' call checks to ensure the underlying texture exists. It needs to
-    // be moved later.
-    if (access->isBad()) {
-        this->markAsBad();
-    }
-
     fTextureSamplers.push_back(access);
 }
 
@@ -144,11 +138,6 @@
 
 void GrResourceIOProcessor::addImageStorageAccess(GrResourceProvider* resourceProvider,
                                                   const ImageStorageAccess* access) {
-    // MDB TODO: this 'isBad' call attempts to instantiate 'access'. It needs to be moved later.
-    if (access->isBad(resourceProvider)) {
-        this->markAsBad();
-    }
-
     fImageStorageAccesses.push_back(access);
 }
 
@@ -188,6 +177,22 @@
     }
 }
 
+bool GrResourceIOProcessor::instantiate(GrResourceProvider* resourceProvider) const {
+    for (const auto& sampler : fTextureSamplers) {
+        if (!sampler->instantiate(resourceProvider)) {
+            return false;
+        }
+    }
+
+    for (const auto& imageStorage : fImageStorageAccesses) {
+        if (!imageStorage->instantiate(resourceProvider)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 bool GrResourceIOProcessor::hasSameSamplersAndAccesses(const GrResourceIOProcessor& that) const {
     if (this->numTextureSamplers() != that.numTextureSamplers() ||
         this->numBuffers() != that.numBuffers() ||
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 027a34e..4195696 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -177,10 +177,10 @@
         return *fImageStorageAccesses[index];
     }
 
-    bool isBad() const { return fIsBad; }
+    bool instantiate(GrResourceProvider* resourceProvider) const;
 
 protected:
-    GrResourceIOProcessor() : fIsBad(false) {}
+    GrResourceIOProcessor() {}
 
     /**
      * Subclasses call these from their constructor to register sampler/image sources. The processor
@@ -199,13 +199,10 @@
     void removeRefs() const;
     void pendingIOComplete() const;
 
-    void markAsBad() { fIsBad = true; }
-
 private:
     SkSTArray<4, const TextureSampler*, true> fTextureSamplers;
     SkSTArray<1, const BufferAccess*, true> fBufferAccesses;
     SkSTArray<1, const ImageStorageAccess*, true> fImageStorageAccesses;
-    bool fIsBad;
 
     typedef GrProcessor INHERITED;
 };
@@ -249,7 +246,28 @@
 
     bool operator!=(const TextureSampler& other) const { return !(*this == other); }
 
+    // MDB TODO: remove the remaining callers of this accessor
     GrTexture* texture() const { return fTexture.get(); }
+
+    // 'instantiate' should only ever be called at flush time.
+    bool instantiate(GrResourceProvider* resourceProvider) const {
+        // MDB TODO: return SkToBool(fProxy->instantiate(resourceProvider));
+        // and remove the following 2 lines
+        SkDEBUGCODE(fInstantiated = true;)
+        return SkToBool(fTexture.get());
+    }
+
+    // 'peekTexture' should only ever be called after a successful 'instantiate' call
+    GrTexture* peekTexture() const {
+        // MDB TODO:
+        // SkASSERT(fProxy->priv().peekTexture());
+        // return fProxy->priv().peekTexture();
+        // and remove the following 3 lines:
+        SkASSERT(fInstantiated);
+        SkASSERT(fTexture.get());
+        return fTexture.get();
+    }
+
     GrShaderFlags visibility() const { return fVisibility; }
     const GrSamplerParams& params() const { return fParams; }
 
@@ -258,15 +276,13 @@
      */
     const GrGpuResourceRef* programTexture() const { return &fTexture; }
 
-    bool isBad() const { return !fTexture.get(); }
-
 private:
-
     typedef GrTGpuResourceRef<GrTexture> ProgramTexture;
 
     ProgramTexture                  fTexture;
     GrSamplerParams                 fParams;
     GrShaderFlags                   fVisibility;
+    SkDEBUGCODE(mutable bool fInstantiated = false;)   // MDB TODO: remove this line
 
     typedef SkNoncopyable INHERITED;
 };
@@ -334,7 +350,6 @@
 
     bool operator!=(const ImageStorageAccess& that) const { return !(*this == that); }
 
-    GrTexture* texture() const { return fProxyRef.getProxy()->priv().peekTexture(); }
     GrTextureProxy* proxy() const { return fProxyRef.getProxy()->asTextureProxy(); }
     GrShaderFlags visibility() const { return fVisibility; }
     GrIOType ioType() const { return fProxyRef.ioType(); }
@@ -342,9 +357,14 @@
     GrSLMemoryModel memoryModel() const { return fMemoryModel; }
     GrSLRestrict restrict() const { return fRestrict; }
 
-    // MDB: In the future this should be renamed instantiate
-    bool isBad(GrResourceProvider* resourceProvider) const {
-        return SkToBool(!fProxyRef.getProxy()->instantiate(resourceProvider));
+    // 'instantiate' should only ever be called at flush time.
+    bool instantiate(GrResourceProvider* resourceProvider) const {
+        return SkToBool(fProxyRef.getProxy()->instantiate(resourceProvider));
+    }
+    // 'peekTexture' should only ever be called after a successful 'instantiate' call
+    GrTexture* peekTexture() const {
+        SkASSERT(fProxyRef.getProxy()->priv().peekTexture());
+        return fProxyRef.getProxy()->priv().peekTexture();
     }
 
     /**
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index 41993e1..ebcfb07 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -82,7 +82,8 @@
     int j = 0;
     for (int i = 0; i < numTextureSamplers; ++i, ++j) {
         const GrResourceIOProcessor::TextureSampler& sampler = proc.textureSampler(i);
-        const GrTexture* tex = sampler.texture();
+        const GrTexture* tex = sampler.peekTexture();
+
         k16[j] = sampler_key(tex->texturePriv().samplerType(), tex->config(), sampler.visibility(),
                              caps);
     }
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 37de07e..deec8c7 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1798,6 +1798,7 @@
     args.fAppliedClip = &appliedClip;
     args.fRenderTarget = rt;
     args.fCaps = this->caps();
+    args.fResourceProvider = this->resourceProvider();
 
     if (analysis.requiresDstTexture()) {
         if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, bounds, &args.fDstTexture)) {
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 70a0096..7d1eba3 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -119,7 +119,8 @@
 void GrGLBicubicEffect::onSetData(const GrGLSLProgramDataManager& pdman,
                                   const GrFragmentProcessor& processor) {
     const GrBicubicEffect& bicubicEffect = processor.cast<GrBicubicEffect>();
-    GrTexture* texture = processor.textureSampler(0).texture();
+    GrTexture* texture = processor.textureSampler(0).peekTexture();
+
     float imageIncrement[2];
     imageIncrement[0] = 1.0f / texture->width();
     imageIncrement[1] = 1.0f / texture->height();
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index cd2fe56..93b4a0f 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -31,7 +31,7 @@
 
         // compute numbers to be hardcoded to convert texture coordinates from int to float
         SkASSERT(cte.numTextureSamplers() == 1);
-        SkDEBUGCODE(GrTexture* atlas = cte.textureSampler(0).texture());
+        SkDEBUGCODE(GrTexture* atlas = cte.textureSampler(0).peekTexture());
         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
 
         GrGLSLVertToFrag v(kVec2f_GrSLType);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 7d22ad3..6101c41 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -82,7 +82,7 @@
 
         // compute numbers to be hardcoded to convert texture coordinates from float to int
         SkASSERT(dfTexEffect.numTextureSamplers() == 1);
-        GrTexture* atlas = dfTexEffect.textureSampler(0).texture();
+        GrTexture* atlas = dfTexEffect.textureSampler(0).peekTexture();
         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
 
         GrGLSLVertToFrag st(kVec2f_GrSLType);
@@ -431,7 +431,8 @@
                  FPCoordTransformIter&& transformIter) override {
         SkASSERT(fTextureSizeUni.isValid());
 
-        GrTexture* texture = proc.textureSampler(0).texture();
+        GrTexture* texture = proc.textureSampler(0).peekTexture();
+
         if (texture->width() != fTextureSize.width() ||
             texture->height() != fTextureSize.height()) {
             fTextureSize = SkISize::Make(texture->width(), texture->height());
@@ -596,7 +597,7 @@
 
         // compute numbers to be hardcoded to convert texture coordinates from float to int
         SkASSERT(dfTexEffect.numTextureSamplers() == 1);
-        GrTexture* atlas = dfTexEffect.textureSampler(0).texture();
+        GrTexture* atlas = dfTexEffect.textureSampler(0).peekTexture();
         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
 
         GrGLSLVertToFrag st(kVec2f_GrSLType);
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index 324c61e..9a0936c 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -98,7 +98,7 @@
                                       const GrFragmentProcessor& processor) {
     const GrGaussianConvolutionFragmentProcessor& conv =
             processor.cast<GrGaussianConvolutionFragmentProcessor>();
-    GrTexture& texture = *conv.textureSampler(0).texture();
+    GrTexture& texture = *conv.textureSampler(0).peekTexture();
 
     float imageIncrement[2] = {0};
     float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index b3ea81a..776eff0 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -130,7 +130,7 @@
 void GrGLMatrixConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdman,
                                             const GrFragmentProcessor& processor) {
     const GrMatrixConvolutionEffect& conv = processor.cast<GrMatrixConvolutionEffect>();
-    GrTexture* texture = conv.textureSampler(0).texture();
+    GrTexture* texture = conv.textureSampler(0).peekTexture();
 
     float imageIncrement[2];
     float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index fb945de..d3ba015 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -24,7 +24,10 @@
 public:
     SkString dumpInfo() const override {
         SkString str;
-        str.appendf("Texture: %d", fTextureSampler.texture()->uniqueID().asUInt());
+        // MDB TODO: this should just print out the uniqueID of the proxy
+        str.appendf("Texture: %d", fTextureSampler.peekTexture()
+                                            ? fTextureSampler.peekTexture()->uniqueID().asUInt()
+                                            : -1);
         return str;
     }
 
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index ee21841..1a6db7a 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -309,7 +309,9 @@
                        const GrFragmentProcessor& fp) override {
             const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
             const GrTextureDomain& domain = tde.fTextureDomain;
-            fGLDomain.setData(pdman, domain, tde.textureSampler(0).texture());
+            GrTexture* texture =  tde.textureSampler(0).peekTexture();
+
+            fGLDomain.setData(pdman, domain, texture);
             if (SkToBool(tde.colorSpaceXform())) {
                 fColorSpaceHelper.setData(pdman, tde.colorSpaceXform());
             }
@@ -412,7 +414,8 @@
                        const GrFragmentProcessor& fp) override {
             const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
                     fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
-            GrTexture* texture = dstdfp.textureSampler(0).texture();
+            GrTexture* texture = dstdfp.textureSampler(0).peekTexture();
+
             fGLDomain.setData(pdman, dstdfp.fTextureDomain, texture);
             float iw = 1.f / texture->width();
             float ih = 1.f / texture->height();
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index ec08bf4..9750e70 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -170,7 +170,7 @@
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
         fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.params(),
-                          allowSRGBInputs, static_cast<GrGLTexture*>(sampler.texture()));
+                          allowSRGBInputs, static_cast<GrGLTexture*>(sampler.peekTexture()));
     }
     for (int i = 0; i < processor.numBuffers(); ++i) {
         const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(i);
@@ -180,7 +180,7 @@
     for (int i = 0; i < processor.numImageStorages(); ++i) {
         const GrResourceIOProcessor::ImageStorageAccess& access = processor.imageStorageAccess(i);
         fGpu->bindImageStorage((*nextImageStorageIdx)++, access.ioType(),
-                               static_cast<GrGLTexture *>(access.texture()));
+                               static_cast<GrGLTexture *>(access.peekTexture()));
     }
 }
 
@@ -188,6 +188,6 @@
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
         fGpu->generateMipmaps(sampler.params(), allowSRGBInputs,
-                              static_cast<GrGLTexture*>(sampler.texture()));
+                              static_cast<GrGLTexture*>(sampler.peekTexture()));
     }
 }
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index f63e56b..dda2ac1 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -8,6 +8,7 @@
 #include "GrGLProgramBuilder.h"
 
 #include "GrAutoLocaleSetter.h"
+#include "GrContext.h"
 #include "GrCoordTransform.h"
 #include "GrGLProgramBuilder.h"
 #include "GrProgramDesc.h"
@@ -32,7 +33,7 @@
                                                const GrPrimitiveProcessor& primProc,
                                                GrProgramDesc* desc,
                                                GrGLGpu* gpu) {
-    SkASSERT(!pipeline.isBad() && !primProc.isBad());
+    SkASSERT(!pipeline.isBad() && primProc.instantiate(gpu->getContext()->resourceProvider()));
 
     ATRACE_ANDROID_FRAMEWORK("Shader Compile");
     GrAutoLocaleSetter als("C");
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 96b3359..756e29c 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -275,7 +275,7 @@
     for (int t = 0; t < numTextureSamplers; ++t) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(t);
         name.printf("TextureSampler_%d", outTexSamplerHandles->count());
-        GrSLType samplerType = sampler.texture()->texturePriv().samplerType();
+        GrSLType samplerType = sampler.peekTexture()->texturePriv().samplerType();
         if (kTextureExternalSampler_GrSLType == samplerType) {
             const char* externalFeatureString =
                     this->shaderCaps()->externalTextureExtensionString();
@@ -286,7 +286,7 @@
                              externalFeatureString);
         }
         outTexSamplerHandles->emplace_back(this->emitSampler(
-                samplerType, sampler.texture()->config(), name.c_str(), sampler.visibility()));
+                samplerType, sampler.peekTexture()->config(), name.c_str(), sampler.visibility()));
     }
     if (int numBuffers = processor.numBuffers()) {
         SkASSERT(this->shaderCaps()->texelBufferSupport());
diff --git a/src/gpu/instanced/InstancedOp.cpp b/src/gpu/instanced/InstancedOp.cpp
index 83a10da..9fbec13 100644
--- a/src/gpu/instanced/InstancedOp.cpp
+++ b/src/gpu/instanced/InstancedOp.cpp
@@ -229,6 +229,7 @@
     GrPipeline::InitArgs args;
     args.fAppliedClip = state->drawOpArgs().fAppliedClip;
     args.fCaps = &state->caps();
+    args.fResourceProvider = state->resourceProvider();
     args.fProcessors = &fProcessors;
     args.fFlags = GrAATypeIsHW(fInfo.aaType()) ? GrPipeline::kHWAntialias_Flag : 0;
     if (fAllowsSRGBInputs) {
diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp
index ccb12bf..cd4c30e 100644
--- a/src/gpu/ops/GrDrawPathOp.cpp
+++ b/src/gpu/ops/GrDrawPathOp.cpp
@@ -48,6 +48,7 @@
     args.fAppliedClip = state.drawOpArgs().fAppliedClip;
     args.fRenderTarget = state.drawOpArgs().fRenderTarget;
     args.fCaps = &state.caps();
+    args.fResourceProvider = state.resourceProvider();
     args.fDstTexture = state.drawOpArgs().fDstTexture;
 
     return pipeline->init(args);
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
index 427543b..9d7cbf9 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -139,6 +139,7 @@
         args.fAppliedClip = target->clip();
         args.fDstTexture = target->dstTexture();
         args.fCaps = &target->caps();
+        args.fResourceProvider = target->resourceProvider();
         return args;
     }
 
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index c5b8aff..0df9cfb 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -493,8 +493,7 @@
 static void prepare_sampled_images(const GrResourceIOProcessor& processor, GrVkGpu* gpu) {
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
-        GrVkTexture* vkTexture = static_cast<GrVkTexture*>(sampler.texture());
-        SkASSERT(vkTexture);
+        GrVkTexture* vkTexture = static_cast<GrVkTexture*>(sampler.peekTexture());
 
         // We may need to resolve the texture first if it is also a render target
         GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(vkTexture->asRenderTarget());
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index c4d723f..b3f6c1b 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -7,6 +7,7 @@
 
 #include "GrVkPipelineState.h"
 
+#include "GrContext.h"
 #include "GrPipeline.h"
 #include "GrTexturePriv.h"
 #include "GrVkBufferView.h"
@@ -264,6 +265,7 @@
     if (dstTexture) {
         // MDB TODO: this is the last usage of a GrTexture-based TextureSampler reset method
         dstTextureSampler.reset(dstTexture);
+        SkAssertResult(dstTextureSampler.instantiate(gpu->getContext()->resourceProvider()));
         textureBindings.push_back(&dstTextureSampler);
     }
 
@@ -373,7 +375,7 @@
     for (int i = 0; i < textureBindings.count(); ++i) {
         const GrSamplerParams& params = textureBindings[i]->params();
 
-        GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->texture());
+        GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->peekTexture());
 
         fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler(params,
                                                           texture->texturePriv().maxMipMapLevel()));
diff --git a/tests/ImageStorageTest.cpp b/tests/ImageStorageTest.cpp
index aa81118..d818b39 100644
--- a/tests/ImageStorageTest.cpp
+++ b/tests/ImageStorageTest.cpp
@@ -54,7 +54,7 @@
                     fb->codeAppend("highp vec2 coord = sk_FragCoord.xy;");
                     fb->appendImageStorageLoad(&imageLoadStr, args.fImageStorages[0],
                                                "ivec2(coord)");
-                    if (GrPixelConfigIsSint(tfp.fImageStorageAccess.texture()->config())) {
+                    if (GrPixelConfigIsSint(tfp.fImageStorageAccess.peekTexture()->config())) {
                         // Map the signed bytes so that when then get read back as unorm values they
                         // will have their original bit pattern.
                         fb->codeAppendf("highp ivec4 ivals = %s;", imageLoadStr.c_str());
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 5169615..399a307 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -353,7 +353,7 @@
         }
         for (int j = 0; j < timesToInvokeFactory; ++j) {
             fp = FPFactory::MakeIdx(i, &testData);
-            if (fp->isBad()) {
+            if (!fp->instantiate(context->resourceProvider())) {
                 continue;
             }