Add support for finding/creating general GrVkRenderPass from the VkResourceProvider.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2035853002

Review-Url: https://codereview.chromium.org/2035853002
diff --git a/src/gpu/vk/GrVkRenderPass.cpp b/src/gpu/vk/GrVkRenderPass.cpp
index c56bafa..6a0f953 100644
--- a/src/gpu/vk/GrVkRenderPass.cpp
+++ b/src/gpu/vk/GrVkRenderPass.cpp
@@ -23,16 +23,16 @@
     SkAssertResult(GrSampleCountToVkSampleCount(desc.fSamples, &attachment->samples));
     switch (layout) {
         case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
-            attachment->loadOp = desc.fLoadOp;
-            attachment->storeOp = desc.fStoreOp;
+            attachment->loadOp = desc.fLoadStoreOps.fLoadOp;
+            attachment->storeOp = desc.fLoadStoreOps.fStoreOp;
             attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
             attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
             break;
         case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
             attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
             attachment->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-            attachment->stencilLoadOp = desc.fLoadOp;
-            attachment->stencilStoreOp = desc.fStoreOp;
+            attachment->stencilLoadOp = desc.fLoadStoreOps.fLoadOp;
+            attachment->stencilStoreOp = desc.fLoadStoreOps.fStoreOp;
             break;
         default:
             SkFAIL("Unexpected attachment layout");
@@ -43,15 +43,21 @@
 }
 
 void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target) {
-    // Get attachment information from render target. This includes which attachments the render
-    // target has (color, resolve, stencil) and the attachments format and sample count.
-    target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags);
+    static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD,
+                                                                 VK_ATTACHMENT_STORE_OP_STORE);
 
+    this->init(gpu, target, kBasicLoadStoreOps, kBasicLoadStoreOps, kBasicLoadStoreOps);
+}
+
+void GrVkRenderPass::init(const GrVkGpu* gpu,
+                          const LoadStoreOps& colorOp,
+                          const LoadStoreOps& resolveOp,
+                          const LoadStoreOps& stencilOp) {
     uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount;
     // Attachment descriptions to be set on the render pass
     SkTArray<VkAttachmentDescription> attachments(numAttachments);
     attachments.reset(numAttachments);
-    memset(attachments.begin(), 0, numAttachments*sizeof(VkAttachmentDescription));
+    memset(attachments.begin(), 0, numAttachments * sizeof(VkAttachmentDescription));
 
     // Refs to attachments on the render pass (as described by teh VkAttachmentDescription above),
     // that are used by the subpass.
@@ -70,6 +76,7 @@
     subpassDesc.pInputAttachments = nullptr;
     if (fAttachmentFlags & kColor_AttachmentFlag) {
         // set up color attachment
+        fAttachmentsDescriptor.fColor.fLoadStoreOps = colorOp;
         setup_vk_attachment_description(&attachments[currentAttachment],
                                         fAttachmentsDescriptor.fColor,
                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@@ -88,6 +95,7 @@
 
     if (fAttachmentFlags & kResolve_AttachmentFlag) {
         // set up resolve attachment
+        fAttachmentsDescriptor.fResolve.fLoadStoreOps = resolveOp;
         setup_vk_attachment_description(&attachments[currentAttachment],
                                         fAttachmentsDescriptor.fResolve,
                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@@ -102,6 +110,7 @@
 
     if (fAttachmentFlags & kStencil_AttachmentFlag) {
         // set up stencil attachment
+        fAttachmentsDescriptor.fStencil.fLoadStoreOps = stencilOp;
         setup_vk_attachment_description(&attachments[currentAttachment],
                                         fAttachmentsDescriptor.fStencil,
                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
@@ -138,6 +147,27 @@
                                                              &fRenderPass));
 }
 
+void GrVkRenderPass::init(const GrVkGpu* gpu,
+                          const GrVkRenderPass& compatibleRenderPass,
+                          const LoadStoreOps& colorOp,
+                          const LoadStoreOps& resolveOp,
+                          const LoadStoreOps& stencilOp) {
+    fAttachmentFlags = compatibleRenderPass.fAttachmentFlags;
+    fAttachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
+    this->init(gpu, colorOp, resolveOp, stencilOp);
+}
+
+void GrVkRenderPass::init(const GrVkGpu* gpu,
+                          const GrVkRenderTarget& target, 
+                          const LoadStoreOps& colorOp,
+                          const LoadStoreOps& resolveOp,
+                          const LoadStoreOps& stencilOp) {
+    // Get attachment information from render target. This includes which attachments the render
+    // target has (color, resolve, stencil) and the attachments format and sample count.
+    target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags);
+    this->init(gpu, colorOp, resolveOp, stencilOp);
+}
+
 void GrVkRenderPass::freeGPUData(const GrVkGpu* gpu) const {
     GR_VK_CALL(gpu->vkInterface(), DestroyRenderPass(gpu->device(), fRenderPass, nullptr));
 }
@@ -231,6 +261,27 @@
     return true;
 }
 
+bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps,
+                                       const LoadStoreOps& resolveOps,
+                                       const LoadStoreOps& stencilOps) const {
+    if (fAttachmentFlags & kColor_AttachmentFlag) {
+        if (fAttachmentsDescriptor.fColor.fLoadStoreOps != colorOps) {
+            return false;
+        }
+    }
+    if (fAttachmentFlags & kResolve_AttachmentFlag) {
+        if (fAttachmentsDescriptor.fResolve.fLoadStoreOps != resolveOps) {
+            return false;
+        }
+    }
+    if (fAttachmentFlags & kStencil_AttachmentFlag) {
+        if (fAttachmentsDescriptor.fStencil.fLoadStoreOps != stencilOps) {
+            return false;
+        }
+    }
+    return true;
+}
+
 void GrVkRenderPass::genKey(GrProcessorKeyBuilder* b) const {
     b->add32(fAttachmentFlags);
     if (fAttachmentFlags & kColor_AttachmentFlag) {
diff --git a/src/gpu/vk/GrVkRenderPass.h b/src/gpu/vk/GrVkRenderPass.h
index 082cccd..b4f4b2b 100644
--- a/src/gpu/vk/GrVkRenderPass.h
+++ b/src/gpu/vk/GrVkRenderPass.h
@@ -21,25 +21,51 @@
 class GrVkRenderPass : public GrVkResource {
 public:
     GrVkRenderPass() : INHERITED(), fRenderPass(VK_NULL_HANDLE) {}
+
+    struct LoadStoreOps {
+        VkAttachmentLoadOp  fLoadOp;
+        VkAttachmentStoreOp fStoreOp;
+
+        LoadStoreOps(VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp)
+            : fLoadOp(loadOp)
+            , fStoreOp(storeOp) {}
+
+        bool operator==(const LoadStoreOps& right) const {
+            return fLoadOp == right.fLoadOp && fStoreOp == right.fStoreOp;
+        }
+
+        bool operator!=(const LoadStoreOps& right) const {
+            return !(*this == right);
+        }
+    };
+
     void initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target);
+    void init(const GrVkGpu* gpu,
+              const GrVkRenderTarget& target,
+              const LoadStoreOps& colorOp,
+              const LoadStoreOps& resolveOp,
+              const LoadStoreOps& stencilOp);
+
+    void init(const GrVkGpu* gpu,
+              const GrVkRenderPass& compatibleRenderPass,
+              const LoadStoreOps& colorOp,
+              const LoadStoreOps& resolveOp,
+              const LoadStoreOps& stencilOp);
 
     struct AttachmentsDescriptor {
         struct AttachmentDesc {
             VkFormat fFormat;
             int fSamples;
-            VkAttachmentLoadOp fLoadOp;
-            VkAttachmentStoreOp fStoreOp;
+            LoadStoreOps fLoadStoreOps;
 
             AttachmentDesc()
                 : fFormat(VK_FORMAT_UNDEFINED)
                 , fSamples(0)
-                , fLoadOp(VK_ATTACHMENT_LOAD_OP_LOAD)
-                , fStoreOp(VK_ATTACHMENT_STORE_OP_STORE) {}
+                , fLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE) {}
             bool operator==(const AttachmentDesc& right) const {
                 return (fFormat == right.fFormat &&
                         fSamples == right.fSamples &&
-                        fLoadOp == right.fLoadOp &&
-                        fStoreOp == right.fStoreOp);
+                        fLoadStoreOps == right.fLoadStoreOps);
             }
             bool operator!=(const AttachmentDesc& right) const {
                 return !(*this == right);
@@ -84,6 +110,10 @@
     // basic RenderPasses that can be used when creating a VkFrameBuffer object.
     bool isCompatible(const GrVkRenderTarget& target) const;
 
+    bool equalLoadStoreOps(const LoadStoreOps& colorOps,
+                           const LoadStoreOps& resolveOps,
+                           const LoadStoreOps& stencilOps) const;
+
     VkRenderPass vkRenderPass() const { return fRenderPass; }
 
     void genKey(GrProcessorKeyBuilder* b) const;
@@ -91,6 +121,11 @@
 private:
     GrVkRenderPass(const GrVkRenderPass&);
 
+    void init(const GrVkGpu* gpu,
+              const LoadStoreOps& colorOps,
+              const LoadStoreOps& resolveOps,
+              const LoadStoreOps& stencilOps);
+
     void freeGPUData(const GrVkGpu* gpu) const override;
 
     VkRenderPass          fRenderPass;
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index 0467371..735f5cd 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -65,7 +65,6 @@
 
     GrBackendObject getRenderTargetHandle() const override;
 
-    // Returns the total number of attachments
     void getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
                                   GrVkRenderPass::AttachmentFlags* flags) const;
 
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index fdc9e90..cd3ba47 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -10,7 +10,6 @@
 #include "GrTextureParams.h"
 #include "GrVkCommandBuffer.h"
 #include "GrVkPipeline.h"
-#include "GrVkRenderPass.h"
 #include "GrVkSampler.h"
 #include "GrVkUtil.h"
 
@@ -134,6 +133,33 @@
     return renderPass;
 }
 
+const GrVkRenderPass* GrVkResourceProvider::findRenderPass(
+                                                     const GrVkRenderTarget& target,
+                                                     const GrVkRenderPass::LoadStoreOps& colorOps,
+                                                     const GrVkRenderPass::LoadStoreOps& resolveOps,
+                                                     const GrVkRenderPass::LoadStoreOps& stencilOps,
+                                                     CompatibleRPHandle* compatibleHandle) {
+    // This will get us the handle to (and possible create) the compatible set for the specific
+    // GrVkRenderPass we are looking for.
+    this->findCompatibleRenderPass(target, compatibleHandle);
+    return this->findRenderPass(*compatibleHandle, colorOps, resolveOps, stencilOps);
+}
+
+const GrVkRenderPass*
+GrVkResourceProvider::findRenderPass(const CompatibleRPHandle& compatibleHandle,
+                                     const GrVkRenderPass::LoadStoreOps& colorOps,
+                                     const GrVkRenderPass::LoadStoreOps& resolveOps,
+                                     const GrVkRenderPass::LoadStoreOps& stencilOps) {
+    SkASSERT(compatibleHandle.isValid() && compatibleHandle.toIndex() < fRenderPassArray.count());
+    CompatibleRenderPassSet& compatibleSet = fRenderPassArray[compatibleHandle.toIndex()];
+    const GrVkRenderPass* renderPass = compatibleSet.getRenderPass(fGpu,
+                                                                   colorOps,
+                                                                   resolveOps,
+                                                                   stencilOps);
+    renderPass->ref();
+    return renderPass;
+}
+
 GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool(
                                                             VkDescriptorType type, uint32_t count) {
     return new GrVkDescriptorPool(fGpu, type, count);
@@ -295,6 +321,24 @@
     return fRenderPasses[0]->isCompatible(target);
 }
 
+GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass(
+                                                   const GrVkGpu* gpu,
+                                                   const GrVkRenderPass::LoadStoreOps& colorOps,
+                                                   const GrVkRenderPass::LoadStoreOps& resolveOps,
+                                                   const GrVkRenderPass::LoadStoreOps& stencilOps) {
+    for (int i = 0; i < fRenderPasses.count(); ++i) {
+        int idx = (i + fLastReturnedIndex) % fRenderPasses.count();
+        if (fRenderPasses[idx]->equalLoadStoreOps(colorOps, resolveOps, stencilOps)) {
+            fLastReturnedIndex = idx;
+            return fRenderPasses[idx];
+        }
+    }
+    GrVkRenderPass* renderPass = fRenderPasses.push_back();
+    renderPass->init(gpu, *this->getCompatibleRenderPass(), colorOps, resolveOps, stencilOps);
+    fLastReturnedIndex = fRenderPasses.count() - 1;
+    return renderPass;
+}
+
 void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources(const GrVkGpu* gpu) {
     for (int i = 0; i < fRenderPasses.count(); ++i) {
         if (fRenderPasses[i]) {
diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h
index 5368a21..e754501 100644
--- a/src/gpu/vk/GrVkResourceProvider.h
+++ b/src/gpu/vk/GrVkResourceProvider.h
@@ -12,6 +12,7 @@
 #include "GrResourceHandle.h"
 #include "GrVkDescriptorPool.h"
 #include "GrVkPipelineState.h"
+#include "GrVkRenderPass.h"
 #include "GrVkResource.h"
 #include "GrVkUtil.h"
 #include "SkTArray.h"
@@ -27,7 +28,6 @@
 class GrVkCommandBuffer;
 class GrVkGpu;
 class GrVkPipeline;
-class GrVkRenderPass;
 class GrVkRenderTarget;
 class GrVkSampler;
 
@@ -59,21 +59,23 @@
     // findCompatibleRenderPass(GrVkRenderTarget&, CompatibleRPHandle*).
     const GrVkRenderPass* findCompatibleRenderPass(const CompatibleRPHandle& compatibleHandle);
 
-#if 0
-    // TODO:
+    // Finds or creates a render pass that matches the target and LoadStoreOps, increments the
+    // refcount, and returns. The caller can optionally pass in a pointer to a CompatibleRPHandle.
+    // If this is non null it will be set to a handle that can be used in the furutre to quickly
+    // return a GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
     const GrVkRenderPass* findRenderPass(const GrVkRenderTarget& target,
-                                         VkAttachmentLoadOp colorLoad,
-                                         VkAttachmentStoreOp colorStore,
-                                         VkAttachmentLoadOp stencilLoad,
-                                         VkAttachmentStoreOp stencilStore,
+                                         const GrVkRenderPass::LoadStoreOps& colorOps,
+                                         const GrVkRenderPass::LoadStoreOps& resolveOps,
+                                         const GrVkRenderPass::LoadStoreOps& stencilOps,
                                          CompatibleRPHandle* compatibleHandle = nullptr);
 
+    // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
+    // findCompatibleRenderPass.
     const GrVkRenderPass* findRenderPass(const CompatibleRPHandle& compatibleHandle,
-                                         VkAttachmentLoadOp colorLoad,
-                                         VkAttachmentStoreOp colorStore,
-                                         VkAttachmentLoadOp stencilLoad,
-                                         VkAttachmentStoreOp stencilStore);
-#endif
+                                         const GrVkRenderPass::LoadStoreOps& colorOps,
+                                         const GrVkRenderPass::LoadStoreOps& resolveOps,
+                                         const GrVkRenderPass::LoadStoreOps& stencilOps);
+
 
     GrVkCommandBuffer* createCommandBuffer();
     void checkCommandBuffers();
@@ -175,6 +177,11 @@
             return fRenderPasses[0];
         }
 
+        GrVkRenderPass* getRenderPass(const GrVkGpu* gpu,
+                                      const GrVkRenderPass::LoadStoreOps& colorOps,
+                                      const GrVkRenderPass::LoadStoreOps& resolveOps,
+                                      const GrVkRenderPass::LoadStoreOps& stencilOps);
+
         void releaseResources(const GrVkGpu* gpu);
         void abandonResources();