Update GrVkRenderTarget to store both stencil & non-stencil render passes (for real)

This is to allow reuse of a Vk render target in both stencil and non-stencil use cases.

Change-Id: Ic35285e66c173db7c0bf6440d95549cf1371ed43
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291077
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 58723df..f20e6ba 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -350,8 +350,14 @@
 
     // Returns a GrOpsRenderPass which GrOpsTasks send draw commands to instead of directly
     // to the Gpu object. The 'bounds' rect is the content rect of the renderTarget.
+    // If a 'stencil' is provided it will be the one bound to 'renderTarget'. If one is not
+    // provided but 'renderTarget' has a stencil buffer then that is a signal that the
+    // render target's stencil buffer should be ignored.
     virtual GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget* renderTarget, GrSurfaceOrigin, const SkIRect& bounds,
+            GrRenderTarget* renderTarget,
+            GrStencilAttachment* stencil,
+            GrSurfaceOrigin,
+            const SkIRect& bounds,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) = 0;
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index c811883..4537242 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -469,9 +469,10 @@
 }
 
 static GrOpsRenderPass* create_render_pass(
-        GrGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
-        GrLoadOp colorLoadOp, const SkPMColor4f& loadClearColor, GrLoadOp stencilLoadOp,
-        GrStoreOp stencilStoreOp, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
+        GrGpu* gpu, GrRenderTarget* rt, GrStencilAttachment* stencil, GrSurfaceOrigin origin,
+        const SkIRect& bounds, GrLoadOp colorLoadOp, const SkPMColor4f& loadClearColor,
+        GrLoadOp stencilLoadOp, GrStoreOp stencilStoreOp,
+        const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
     const GrOpsRenderPass::LoadAndStoreInfo kColorLoadStoreInfo {
         colorLoadOp,
         GrStoreOp::kStore,
@@ -488,8 +489,8 @@
         stencilStoreOp,
     };
 
-    return gpu->getOpsRenderPass(rt, origin, bounds, kColorLoadStoreInfo, stencilLoadAndStoreInfo,
-                                 sampledProxies);
+    return gpu->getOpsRenderPass(rt, stencil, origin, bounds,
+                                 kColorLoadStoreInfo, stencilLoadAndStoreInfo, sampledProxies);
 }
 
 // TODO: this is where GrOp::renderTarget is used (which is fine since it
@@ -571,7 +572,7 @@
             : GrStoreOp::kStore;
 
     GrOpsRenderPass* renderPass = create_render_pass(
-            flushState->gpu(), proxy->peekRenderTarget(), fTargetView.origin(),
+            flushState->gpu(), proxy->peekRenderTarget(), stencil, fTargetView.origin(),
             fClippedContentBounds, fColorLoadOp, fLoadClearColor, stencilLoadOp, stencilStoreOp,
             fSampledProxies);
     if (!renderPass) {
diff --git a/src/gpu/GrProgramInfo.h b/src/gpu/GrProgramInfo.h
index 373b3bb..f8ce3fc 100644
--- a/src/gpu/GrProgramInfo.h
+++ b/src/gpu/GrProgramInfo.h
@@ -49,6 +49,7 @@
 
     int numSamples() const { return fNumSamples; }
     int numStencilSamples() const { return fNumStencilSamples; }
+    bool isStencilEnabled() const { return fPipeline->isStencilEnabled(); }
 
     int numRasterSamples() const {
         return fPipeline->isStencilEnabled() ? fNumStencilSamples : fNumSamples;
diff --git a/src/gpu/d3d/GrD3DGpu.cpp b/src/gpu/d3d/GrD3DGpu.cpp
index 3cc4112..e722b37 100644
--- a/src/gpu/d3d/GrD3DGpu.cpp
+++ b/src/gpu/d3d/GrD3DGpu.cpp
@@ -93,7 +93,8 @@
 }
 
 GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
-    GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+    GrRenderTarget* rt, GrStencilAttachment*,
+    GrSurfaceOrigin origin, const SkIRect& bounds,
     const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
     const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
     const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
diff --git a/src/gpu/d3d/GrD3DGpu.h b/src/gpu/d3d/GrD3DGpu.h
index 3ffff98..be8fbc5 100644
--- a/src/gpu/d3d/GrD3DGpu.h
+++ b/src/gpu/d3d/GrD3DGpu.h
@@ -70,7 +70,8 @@
             const GrRenderTarget*, int width, int height, int numStencilSamples) override;
 
     GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+            GrRenderTarget*, GrStencilAttachment*,
+            GrSurfaceOrigin, const SkIRect&,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp
index f21c17d..f4756e7 100644
--- a/src/gpu/dawn/GrDawnGpu.cpp
+++ b/src/gpu/dawn/GrDawnGpu.cpp
@@ -137,7 +137,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrOpsRenderPass* GrDawnGpu::getOpsRenderPass(
-            GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+            GrRenderTarget* rt, GrStencilAttachment*,
+            GrSurfaceOrigin origin, const SkIRect& bounds,
             const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
             const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h
index ac4f983..fd09f9e 100644
--- a/src/gpu/dawn/GrDawnGpu.h
+++ b/src/gpu/dawn/GrDawnGpu.h
@@ -61,7 +61,8 @@
                                                                 int numStencilSamples) override;
 
     GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds,
+            GrRenderTarget*, GrStencilAttachment*,
+            GrSurfaceOrigin, const SkIRect& bounds,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 2ca42ac..ef000ad 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2158,7 +2158,8 @@
 }
 
 GrOpsRenderPass* GrGLGpu::getOpsRenderPass(
-        GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+        GrRenderTarget* rt, GrStencilAttachment*,
+        GrSurfaceOrigin origin, const SkIRect& bounds,
         const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
         const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
         const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 164d057..3f22309 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -124,7 +124,8 @@
                           const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore);
 
     GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+            GrRenderTarget*, GrStencilAttachment*,
+            GrSurfaceOrigin, const SkIRect&,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index 3348c4b..ccd1157 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -53,7 +53,8 @@
 }
 
 GrOpsRenderPass* GrMockGpu::getOpsRenderPass(
-                                GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+                                GrRenderTarget* rt, GrStencilAttachment*,
+                                GrSurfaceOrigin origin, const SkIRect& bounds,
                                 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
                                 const GrOpsRenderPass::StencilLoadAndStoreInfo&,
                                 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 05fdda7..29dda81 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -25,7 +25,10 @@
     ~GrMockGpu() override {}
 
     GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+            GrRenderTarget*,
+            GrStencilAttachment*,
+            GrSurfaceOrigin,
+            const SkIRect&,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 191c0ba..431a04d 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -79,7 +79,8 @@
                        const SkIPoint& dstPoint) override;
 
     GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds,
+            GrRenderTarget*, GrStencilAttachment*,
+            GrSurfaceOrigin, const SkIRect& bounds,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 420bb89..af90ffc 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -159,7 +159,8 @@
 }
 
 GrOpsRenderPass* GrMtlGpu::getOpsRenderPass(
-            GrRenderTarget* renderTarget, GrSurfaceOrigin origin, const SkIRect& bounds,
+            GrRenderTarget* renderTarget, GrStencilAttachment*,
+            GrSurfaceOrigin origin, const SkIRect& bounds,
             const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
             const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index eacce98..028c0dc 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1716,9 +1716,12 @@
     b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
 
     GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
+
+    bool needsStencil = programInfo.numStencilSamples() || programInfo.isStencilEnabled();
     // TODO: support failure in getSimpleRenderPass
-    SkASSERT(vkRT->getSimpleRenderPass());
-    vkRT->getSimpleRenderPass()->genKey(&b);
+    const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil);
+    SkASSERT(rp);
+    rp->genKey(&b);
 
     GrStencilSettings stencil = programInfo.nonGLStencilSettings();
     stencil.genKey(&b, true);
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp
index e23459b..953b8da 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -472,7 +472,7 @@
     SkASSERT(!fActiveRenderPass);
     SkASSERT(renderPass->isCompatible(*target));
 
-    const GrVkFramebuffer* framebuffer = target->getFramebuffer();
+    const GrVkFramebuffer* framebuffer = target->getFramebuffer(renderPass->hasStencilAttachment());
     if (!framebuffer) {
         return false;
     }
@@ -499,7 +499,7 @@
     GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents));
     fActiveRenderPass = renderPass;
     this->addResource(renderPass);
-    target->addResources(*this);
+    target->addResources(*this, renderPass->hasStencilAttachment());
     return true;
 }
 
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index f2ab810..e4f4fa0 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -309,7 +309,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrOpsRenderPass* GrVkGpu::getOpsRenderPass(
-            GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+            GrRenderTarget* rt, GrStencilAttachment* stencil,
+            GrSurfaceOrigin origin, const SkIRect& bounds,
             const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
             const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -317,7 +318,8 @@
         fCachedOpsRenderPass.reset(new GrVkOpsRenderPass(this));
     }
 
-    if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
+    if (!fCachedOpsRenderPass->set(rt, stencil, origin, bounds,
+                                   colorInfo, stencilInfo, sampledProxies)) {
         return nullptr;
     }
     return fCachedOpsRenderPass.get();
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index be7a03c..af10a22 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -98,7 +98,8 @@
             const GrRenderTarget*, int width, int height, int numStencilSamples) override;
 
     GrOpsRenderPass* getOpsRenderPass(
-            GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+            GrRenderTarget*, GrStencilAttachment*,
+            GrSurfaceOrigin, const SkIRect&,
             const GrOpsRenderPass::LoadAndStoreInfo&,
             const GrOpsRenderPass::StencilLoadAndStoreInfo&,
             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/src/gpu/vk/GrVkOpsRenderPass.cpp b/src/gpu/vk/GrVkOpsRenderPass.cpp
index 3327cf8..5eef9cc 100644
--- a/src/gpu/vk/GrVkOpsRenderPass.cpp
+++ b/src/gpu/vk/GrVkOpsRenderPass.cpp
@@ -61,7 +61,8 @@
 
 bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
                              const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
-                             const SkPMColor4f& clearColor) {
+                             const SkPMColor4f& clearColor,
+                             bool withStencil) {
 
     VkAttachmentLoadOp loadOp;
     VkAttachmentStoreOp storeOp;
@@ -87,8 +88,11 @@
                                 false);
 
     // If we are using a stencil attachment we also need to update its layout
-    if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment()) {
-        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
+    if (withStencil) {
+        GrVkStencilAttachment* vkStencil =
+                (GrVkStencilAttachment*) fRenderTarget->renderTargetPriv().getStencilAttachment();
+        SkASSERT(vkStencil);
+
         // We need the write and read access bits since we may load and store the stencil.
         // The initial load happens in the VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT so we
         // wait there.
@@ -101,7 +105,7 @@
     }
 
     const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
-            vkRT->compatibleRenderPassHandle();
+            vkRT->compatibleRenderPassHandle(withStencil);
     if (rpHandle.isValid()) {
         fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
                                                                      vkColorOps,
@@ -109,7 +113,9 @@
     } else {
         fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(vkRT,
                                                                      vkColorOps,
-                                                                     vkStencilOps);
+                                                                     vkStencilOps,
+                                                                     nullptr,
+                                                                     withStencil);
     }
     if (!fCurrentRenderPass) {
         return false;
@@ -128,7 +134,8 @@
             fCurrentRenderPass = nullptr;
             return false;
         }
-        fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(), fCurrentRenderPass);
+        fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil),
+                                              fCurrentRenderPass);
     }
 
     if (!fGpu->beginRenderPass(fCurrentRenderPass, &vkClearColor, vkRT, fOrigin, fBounds,
@@ -196,7 +203,8 @@
     fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds);
 }
 
-bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrStencilAttachment* stencil,
+                            GrSurfaceOrigin origin, const SkIRect& bounds,
                             const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
                             const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
                             const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -227,7 +235,7 @@
         return this->initWrapped();
     }
 
-    return this->init(colorInfo, stencilInfo, colorInfo.fClearColor);
+    return this->init(colorInfo, stencilInfo, colorInfo.fClearColor, SkToBool(stencil));
 }
 
 void GrVkOpsRenderPass::reset() {
@@ -374,8 +382,10 @@
     GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
                                               VK_ATTACHMENT_STORE_OP_STORE);
 
+    bool withStencil = fCurrentRenderPass->hasStencilAttachment();
+
     const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
-            vkRT->compatibleRenderPassHandle();
+            vkRT->compatibleRenderPassHandle(withStencil);
     SkASSERT(fCurrentRenderPass);
     fCurrentRenderPass->unref();
     if (rpHandle.isValid()) {
@@ -385,7 +395,9 @@
     } else {
         fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(vkRT,
                                                                      vkColorOps,
-                                                                     vkStencilOps);
+                                                                     vkStencilOps,
+                                                                     nullptr,
+                                                                     withStencil);
     }
     if (!fCurrentRenderPass) {
         return;
@@ -402,7 +414,8 @@
             fCurrentRenderPass = nullptr;
             return;
         }
-        fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(), fCurrentRenderPass);
+        fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil),
+                                              fCurrentRenderPass);
     }
 
     // We use the same fBounds as the whole GrVkOpsRenderPass since we have no way of tracking the
diff --git a/src/gpu/vk/GrVkOpsRenderPass.h b/src/gpu/vk/GrVkOpsRenderPass.h
index 195bb92..53bb07e 100644
--- a/src/gpu/vk/GrVkOpsRenderPass.h
+++ b/src/gpu/vk/GrVkOpsRenderPass.h
@@ -32,7 +32,8 @@
 
     void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override;
 
-    bool set(GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds,
+    bool set(GrRenderTarget*, GrStencilAttachment*,
+             GrSurfaceOrigin, const SkIRect& bounds,
              const GrOpsRenderPass::LoadAndStoreInfo&,
              const GrOpsRenderPass::StencilLoadAndStoreInfo&,
              const SkTArray<GrSurfaceProxy*, true>& sampledProxies);
@@ -47,7 +48,8 @@
 private:
     bool init(const GrOpsRenderPass::LoadAndStoreInfo&,
               const GrOpsRenderPass::StencilLoadAndStoreInfo&,
-              const SkPMColor4f& clearColor);
+              const SkPMColor4f& clearColor,
+              bool withStencil);
 
     // Called instead of init when we are drawing to a render target that already wraps a secondary
     // command buffer.
diff --git a/src/gpu/vk/GrVkRenderPass.cpp b/src/gpu/vk/GrVkRenderPass.cpp
index 627eb22..281983f 100644
--- a/src/gpu/vk/GrVkRenderPass.cpp
+++ b/src/gpu/vk/GrVkRenderPass.cpp
@@ -234,7 +234,7 @@
 
     AttachmentsDescriptor desc;
     AttachmentFlags flags;
-    target.getAttachmentsDescriptor(&desc, &flags);
+    target.getAttachmentsDescriptor(&desc, &flags, this->hasStencilAttachment());
 
     return this->isCompatible(desc, flags);
 }
diff --git a/src/gpu/vk/GrVkRenderPass.h b/src/gpu/vk/GrVkRenderPass.h
index 8b8c641..5009e1e 100644
--- a/src/gpu/vk/GrVkRenderPass.h
+++ b/src/gpu/vk/GrVkRenderPass.h
@@ -94,6 +94,7 @@
     // index value.
     bool colorAttachmentIndex(uint32_t* index) const;
     bool stencilAttachmentIndex(uint32_t* index) const;
+    bool hasStencilAttachment() const { return fAttachmentFlags & kStencil_AttachmentFlag; }
 
     // Returns whether or not the structure of a RenderTarget matches that of the VkRenderPass in
     // this object. Specifically this compares that the number of attachments, format of
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 3021298..761dd97 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -40,7 +40,9 @@
                                    GrBackendObjectOwnership::kOwned))
         , fResolveAttachmentView(resolveAttachmentView)
         , fCachedFramebuffer(nullptr)
-        , fCachedSimpleRenderPass(nullptr) {
+        , fCachedStencilFramebuffer(nullptr)
+        , fCachedSimpleRenderPass(nullptr)
+        , fCachedStencilRenderPass(nullptr) {
     SkASSERT(info.fProtected == msaaInfo.fProtected);
     SkASSERT(sampleCnt > 1);
     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
@@ -67,7 +69,9 @@
                                    GrBackendObjectOwnership::kOwned))
         , fResolveAttachmentView(resolveAttachmentView)
         , fCachedFramebuffer(nullptr)
-        , fCachedSimpleRenderPass(nullptr) {
+        , fCachedStencilFramebuffer(nullptr)
+        , fCachedSimpleRenderPass(nullptr)
+        , fCachedStencilRenderPass(nullptr) {
     SkASSERT(info.fProtected == msaaInfo.fProtected);
     SkASSERT(sampleCnt > 1);
 }
@@ -86,7 +90,9 @@
         , fMSAAImage(nullptr)
         , fResolveAttachmentView(nullptr)
         , fCachedFramebuffer(nullptr)
-        , fCachedSimpleRenderPass(nullptr) {
+        , fCachedStencilFramebuffer(nullptr)
+        , fCachedSimpleRenderPass(nullptr)
+        , fCachedStencilRenderPass(nullptr) {
     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
 }
 
@@ -105,7 +111,9 @@
         , fMSAAImage(nullptr)
         , fResolveAttachmentView(nullptr)
         , fCachedFramebuffer(nullptr)
-        , fCachedSimpleRenderPass(nullptr) {}
+        , fCachedStencilFramebuffer(nullptr)
+        , fCachedSimpleRenderPass(nullptr)
+        , fCachedStencilRenderPass(nullptr) {}
 
 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                    SkISize dimensions,
@@ -120,7 +128,9 @@
         , fMSAAImage(nullptr)
         , fResolveAttachmentView(nullptr)
         , fCachedFramebuffer(nullptr)
+        , fCachedStencilFramebuffer(nullptr)
         , fCachedSimpleRenderPass(renderPass)
+        , fCachedStencilRenderPass(nullptr)
         , fSecondaryCommandBuffer(secondaryCommandBuffer) {
     SkASSERT(fSecondaryCommandBuffer != VK_NULL_HANDLE);
     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
@@ -231,70 +241,91 @@
 
 bool GrVkRenderTarget::completeStencilAttachment() {
     SkASSERT(!this->wrapsSecondaryCommandBuffer());
-    // If we have a previous renderpass or framebuffer it will have been made without stencil, so
-    // we set it to null to trigger creating a new one the next time we need it.
-    if (fCachedSimpleRenderPass) {
-        fCachedSimpleRenderPass->unref();
-        fCachedSimpleRenderPass = nullptr;
-    }
-    if (fCachedFramebuffer) {
-        fCachedFramebuffer->unref();
-        fCachedFramebuffer = nullptr;
-    }
-    fCompatibleRPHandle = GrVkResourceProvider::CompatibleRPHandle();
     return true;
 }
 
-const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass() {
-    if (fCachedSimpleRenderPass) {
+const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil) {
+    if (withStencil) {
+        if (fCachedStencilRenderPass) {
+            return fCachedStencilRenderPass;
+        }
+    } else {
+        if (fCachedSimpleRenderPass) {
+            return fCachedSimpleRenderPass;
+        }
+    }
+
+    return this->createSimpleRenderPass(withStencil);
+}
+
+const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass(bool withStencil) {
+    SkASSERT(!this->wrapsSecondaryCommandBuffer());
+
+    GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();
+    if (withStencil) {
+        SkASSERT(!fCachedStencilRenderPass);
+        fCachedStencilRenderPass = rp.findCompatibleRenderPass(*this, &fCompatibleStencilRPHandle,
+                                                               withStencil);
+        return fCachedStencilRenderPass;
+    } else {
+        SkASSERT(!fCachedSimpleRenderPass);
+        fCachedSimpleRenderPass = rp.findCompatibleRenderPass(*this, &fCompatibleRPHandle,
+                                                              withStencil);
         return fCachedSimpleRenderPass;
     }
-    return this->createSimpleRenderPass();
 }
 
-const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass() {
-    SkASSERT(!this->wrapsSecondaryCommandBuffer());
-    SkASSERT(!fCachedSimpleRenderPass);
-
-    fCachedSimpleRenderPass =
-        this->getVkGpu()->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
-    return fCachedSimpleRenderPass;
-}
-
-const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer() {
-    if (fCachedFramebuffer) {
-        return fCachedFramebuffer;
+const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil) {
+    if (withStencil) {
+        if (fCachedStencilFramebuffer) {
+            return fCachedStencilFramebuffer;
+        }
+    } else {
+        if (fCachedFramebuffer) {
+            return fCachedFramebuffer;
+        }
     }
-    return this->createFramebuffer();
+    return this->createFramebuffer(withStencil);
 }
 
-const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer() {
+const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer(bool withStencil) {
     SkASSERT(!this->wrapsSecondaryCommandBuffer());
-    SkASSERT(!fCachedFramebuffer);
-
     GrVkGpu* gpu = this->getVkGpu();
-    // Stencil attachment view is stored in the base RT stencil attachment
-    const GrVkImageView* stencilView = this->stencilAttachmentView();
-    const GrVkRenderPass* renderPass = this->getSimpleRenderPass();
+
+    const GrVkRenderPass* renderPass = this->getSimpleRenderPass(withStencil);
     if (!renderPass) {
         return nullptr;
     }
-    fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), renderPass,
-                                                 fColorAttachmentView, stencilView);
-    return fCachedFramebuffer;
+
+    // Stencil attachment view is stored in the base RT stencil attachment
+    const GrVkImageView* stencilView = withStencil ? this->stencilAttachmentView() : nullptr;
+    GrVkFramebuffer* frameBuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
+                                                           renderPass, fColorAttachmentView,
+                                                           stencilView);
+
+    if (withStencil) {
+        SkASSERT(!fCachedStencilFramebuffer);
+        fCachedStencilFramebuffer = frameBuffer;
+    } else {
+        SkASSERT(!fCachedFramebuffer);
+        fCachedFramebuffer = frameBuffer;
+    }
+
+    return frameBuffer;
 }
 
-void GrVkRenderTarget::getAttachmentsDescriptor(
-                                           GrVkRenderPass::AttachmentsDescriptor* desc,
-                                           GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
+void GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
+                                                GrVkRenderPass::AttachmentFlags* attachmentFlags,
+                                                bool withStencil) const {
     SkASSERT(!this->wrapsSecondaryCommandBuffer());
     desc->fColor.fFormat = this->imageFormat();
     desc->fColor.fSamples = this->numSamples();
     *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
     uint32_t attachmentCount = 1;
 
-    const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
-    if (stencil) {
+    if (withStencil) {
+        const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
+        SkASSERT(stencil);
         const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
         desc->fStencil.fFormat = vkStencil->imageFormat();
         desc->fStencil.fSamples = vkStencil->numSamples();
@@ -317,11 +348,13 @@
     SkASSERT(!fResolveAttachmentView);
     SkASSERT(!fColorAttachmentView);
     SkASSERT(!fCachedFramebuffer);
+    SkASSERT(!fCachedStencilFramebuffer);
     SkASSERT(!fCachedSimpleRenderPass);
+    SkASSERT(!fCachedStencilRenderPass);
 }
 
-void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) {
-    commandBuffer.addResource(this->getFramebuffer());
+void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer, bool withStencil) {
+    commandBuffer.addResource(this->getFramebuffer(withStencil));
     commandBuffer.addResource(this->colorAttachmentView());
     commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
                                                         : this->resource());
@@ -351,10 +384,18 @@
         fCachedFramebuffer->unref();
         fCachedFramebuffer = nullptr;
     }
+    if (fCachedStencilFramebuffer) {
+        fCachedStencilFramebuffer->unref();
+        fCachedStencilFramebuffer = nullptr;
+    }
     if (fCachedSimpleRenderPass) {
         fCachedSimpleRenderPass->unref();
         fCachedSimpleRenderPass = nullptr;
     }
+    if (fCachedStencilRenderPass) {
+        fCachedStencilRenderPass->unref();
+        fCachedStencilRenderPass = nullptr;
+    }
     for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) {
         SkASSERT(fGrSecondaryCommandBuffers[i]);
         fGrSecondaryCommandBuffers[i]->releaseResources();
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index daae1a0..da6f084 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -43,7 +43,7 @@
 
     GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
 
-    const GrVkFramebuffer* getFramebuffer();
+    const GrVkFramebuffer* getFramebuffer(bool withStencil);
     const GrVkImageView* colorAttachmentView() const { return fColorAttachmentView; }
     const GrManagedResource* msaaImageResource() const {
         if (fMSAAImage) {
@@ -56,15 +56,26 @@
     const GrManagedResource* stencilImageResource() const;
     const GrVkImageView* stencilAttachmentView() const;
 
-    const GrVkRenderPass* getSimpleRenderPass();
-    GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle() {
+    const GrVkRenderPass* getSimpleRenderPass(bool withStencil);
+    GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle(bool withStencil) {
         SkASSERT(!this->wrapsSecondaryCommandBuffer());
-        if (!fCompatibleRPHandle.isValid()) {
-            SkASSERT(!fCachedSimpleRenderPass);
-            this->createSimpleRenderPass();
+
+        auto pRPHandle = withStencil ? &fCompatibleStencilRPHandle : &fCompatibleRPHandle;
+        if (!pRPHandle->isValid()) {
+            this->createSimpleRenderPass(withStencil);
         }
-        SkASSERT(fCompatibleRPHandle.isValid() == SkToBool(fCachedSimpleRenderPass));
-        return fCompatibleRPHandle;
+
+#ifdef SK_DEBUG
+        if (withStencil) {
+            SkASSERT(pRPHandle->isValid() == SkToBool(fCachedStencilRenderPass));
+            SkASSERT(fCachedStencilRenderPass->hasStencilAttachment());
+        } else {
+            SkASSERT(pRPHandle->isValid() == SkToBool(fCachedSimpleRenderPass));
+            SkASSERT(!fCachedSimpleRenderPass->hasStencilAttachment());
+        }
+#endif
+
+        return *pRPHandle;
     }
     const GrVkRenderPass* externalRenderPass() const {
         SkASSERT(this->wrapsSecondaryCommandBuffer());
@@ -86,9 +97,10 @@
     GrBackendRenderTarget getBackendRenderTarget() const override;
 
     void getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
-                                  GrVkRenderPass::AttachmentFlags* flags) const;
+                                  GrVkRenderPass::AttachmentFlags* flags,
+                                  bool withStencil) const;
 
-    void addResources(GrVkCommandBuffer& commandBuffer);
+    void addResources(GrVkCommandBuffer& commandBuffer, bool withStencil);
 
     void addWrappedGrSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> cmdBuffer) {
         fGrSecondaryCommandBuffers.push_back(std::move(cmdBuffer));
@@ -154,8 +166,8 @@
 
     GrVkGpu* getVkGpu() const;
 
-    const GrVkRenderPass* createSimpleRenderPass();
-    const GrVkFramebuffer* createFramebuffer();
+    const GrVkRenderPass* createSimpleRenderPass(bool withStencil);
+    const GrVkFramebuffer* createFramebuffer(bool withStencil);
 
     bool completeStencilAttachment() override;
 
@@ -173,12 +185,18 @@
     const GrVkImageView*       fResolveAttachmentView;
 
     const GrVkFramebuffer*     fCachedFramebuffer;
+    const GrVkFramebuffer*     fCachedStencilFramebuffer;
 
-    // This is a cached pointer to a simple render pass. The render target should unref it
-    // once it is done with it.
+    // Cached pointers to a simple and stencil render passes. The render target should unref them
+    // once it is done with them.
     const GrVkRenderPass*      fCachedSimpleRenderPass;
-    // This is a handle to be used to quickly get compatible GrVkRenderPasses for this render target
+    const GrVkRenderPass*      fCachedStencilRenderPass;
+
+    // This is a handle to be used to quickly get a GrVkRenderPass that is compatible with
+    // this render target if its stencil buffer is ignored.
     GrVkResourceProvider::CompatibleRPHandle fCompatibleRPHandle;
+    // Same as above but taking the render target's stencil buffer into account
+    GrVkResourceProvider::CompatibleRPHandle fCompatibleStencilRPHandle;
 
     // If this render target wraps an external VkCommandBuffer, then this handle will be that
     // VkCommandBuffer and not VK_NULL_HANDLE. In this case the render target will not be backed by
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index 017310a..b6a058c 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -102,12 +102,13 @@
 // RenderPasses as needed that are compatible with the framebuffer.
 const GrVkRenderPass*
 GrVkResourceProvider::findCompatibleRenderPass(const GrVkRenderTarget& target,
-                                               CompatibleRPHandle* compatibleHandle) {
+                                               CompatibleRPHandle* compatibleHandle,
+                                               bool withStencil) {
     // Get attachment information from render target. This includes which attachments the render
     // target has (color, stencil) and the attachments format and sample count.
     GrVkRenderPass::AttachmentFlags attachmentFlags;
     GrVkRenderPass::AttachmentsDescriptor attachmentsDesc;
-    target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags);
+    target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags, withStencil);
 
     return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, compatibleHandle);
 }
@@ -164,11 +165,12 @@
                                                      GrVkRenderTarget* target,
                                                      const GrVkRenderPass::LoadStoreOps& colorOps,
                                                      const GrVkRenderPass::LoadStoreOps& stencilOps,
-                                                     CompatibleRPHandle* compatibleHandle) {
+                                                     CompatibleRPHandle* compatibleHandle,
+                                                     bool withStencil) {
     GrVkResourceProvider::CompatibleRPHandle tempRPHandle;
     GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle
                                                                            : &tempRPHandle;
-    *pRPHandle = target->compatibleRenderPassHandle();
+    *pRPHandle = target->compatibleRenderPassHandle(withStencil);
     if (!pRPHandle->isValid()) {
         return nullptr;
     }
diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h
index d4ef863..0ba90e7 100644
--- a/src/gpu/vk/GrVkResourceProvider.h
+++ b/src/gpu/vk/GrVkResourceProvider.h
@@ -57,7 +57,8 @@
     // non null it will be set to a handle that can be used in the furutre to quickly return a
     // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
     const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target,
-                                                   CompatibleRPHandle* compatibleHandle = nullptr);
+                                                   CompatibleRPHandle* compatibleHandle,
+                                                   bool withStencil);
     const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor*,
                                                    GrVkRenderPass::AttachmentFlags,
                                                    CompatibleRPHandle* compatibleHandle = nullptr);
@@ -73,7 +74,8 @@
     const GrVkRenderPass* findRenderPass(GrVkRenderTarget* target,
                                          const GrVkRenderPass::LoadStoreOps& colorOps,
                                          const GrVkRenderPass::LoadStoreOps& stencilOps,
-                                         CompatibleRPHandle* compatibleHandle = nullptr);
+                                         CompatibleRPHandle* compatibleHandle,
+                                         bool withStencil);
 
     // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
     // findCompatibleRenderPass.