Make GrGpuCommandBuffer infer its render target from first draw

This is a temporary workaround to allow removal of GrBatch::renderTarget().

Change-Id: Ic14710a369802064cf6446e8191a98ea3595556d
Reviewed-on: https://skia-review.googlesource.com/5342
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 674e8e4..9fab21d 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -210,11 +210,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
-            GrRenderTarget* target,
             const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
             const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
-    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
-    return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo);
+    return new GrVkGpuCommandBuffer(this, colorInfo, stencilInfo);
 }
 
 void GrVkGpu::submitCommandBuffer(SyncQueue sync) {
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index dd1eaa1..fce0100 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -102,7 +102,6 @@
     void clearStencil(GrRenderTarget* target) override;
 
     GrGpuCommandBuffer* createCommandBuffer(
-            GrRenderTarget* target,
             const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
             const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
 
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 9b70c0b..7725e8e 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -53,21 +53,28 @@
 }
 
 GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
-                                           GrVkRenderTarget* target,
                                            const LoadAndStoreInfo& colorInfo,
                                            const LoadAndStoreInfo& stencilInfo)
     : fGpu(gpu)
-    , fRenderTarget(target) {
-    VkAttachmentLoadOp vkLoadOp;
-    VkAttachmentStoreOp vkStoreOp;
+    , fRenderTarget(nullptr)
+    , fClearColor(GrColor4f::FromGrColor(colorInfo.fClearColor)){
 
-    get_vk_load_store_ops(colorInfo, &vkLoadOp, &vkStoreOp);
-    GrVkRenderPass::LoadStoreOps vkColorOps(vkLoadOp, vkStoreOp);
+    get_vk_load_store_ops(colorInfo, &fVkColorLoadOp, &fVkColorStoreOp);
 
-    get_vk_load_store_ops(stencilInfo, &vkLoadOp, &vkStoreOp);
-    GrVkRenderPass::LoadStoreOps vkStencilOps(vkLoadOp, vkStoreOp);
+    get_vk_load_store_ops(stencilInfo, &fVkStencilLoadOp, &fVkStencilStoreOp);
+
+    fCurrentCmdBuffer = -1;
+}
+
+void GrVkGpuCommandBuffer::init(GrVkRenderTarget* target) {
+    SkASSERT(!fRenderTarget);
+    fRenderTarget = target;
+
+    GrVkRenderPass::LoadStoreOps vkColorOps(fVkColorLoadOp, fVkColorStoreOp);
+    GrVkRenderPass::LoadStoreOps vkStencilOps(fVkStencilLoadOp, fVkStencilStoreOp);
 
     CommandBufferInfo& cbInfo = fCommandBufferInfos.push_back();
+    SkASSERT(fCommandBufferInfos.count() == 1);
     fCurrentCmdBuffer = 0;
 
     const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target->compatibleRenderPassHandle();
@@ -81,16 +88,20 @@
                                                                      vkStencilOps);
     }
 
-    GrColorToRGBAFloat(colorInfo.fClearColor, cbInfo.fColorClearValue.color.float32);
+    cbInfo.fColorClearValue.color.float32[0] = fClearColor.fRGBA[0];
+    cbInfo.fColorClearValue.color.float32[1] = fClearColor.fRGBA[1];
+    cbInfo.fColorClearValue.color.float32[2] = fClearColor.fRGBA[2];
+    cbInfo.fColorClearValue.color.float32[3] = fClearColor.fRGBA[3];
 
     cbInfo.fBounds.setEmpty();
     cbInfo.fIsEmpty = true;
     cbInfo.fStartsWithClear = false;
 
-    cbInfo.fCommandBuffer = gpu->resourceProvider().findOrCreateSecondaryCommandBuffer();
-    cbInfo.fCommandBuffer->begin(gpu, target->framebuffer(), cbInfo.fRenderPass);
+    cbInfo.fCommandBuffer = fGpu->resourceProvider().findOrCreateSecondaryCommandBuffer();
+    cbInfo.fCommandBuffer->begin(fGpu, target->framebuffer(), cbInfo.fRenderPass);
 }
 
+
 GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() {
     for (int i = 0; i < fCommandBufferInfos.count(); ++i) {
         CommandBufferInfo& cbInfo = fCommandBufferInfos[i];
@@ -103,10 +114,15 @@
 GrRenderTarget* GrVkGpuCommandBuffer::renderTarget() { return fRenderTarget; }
 
 void GrVkGpuCommandBuffer::end() {
-    fCommandBufferInfos[fCurrentCmdBuffer].fCommandBuffer->end(fGpu);
+    if (fCurrentCmdBuffer >= 0) {
+        fCommandBufferInfos[fCurrentCmdBuffer].fCommandBuffer->end(fGpu);
+    }
 }
 
 void GrVkGpuCommandBuffer::onSubmit() {
+    if (!fRenderTarget) {
+        return;
+    }
     // Change layout of our render target so it can be used as the color attachment. Currently
     // we don't attach the resolve to the framebuffer so no need to change its layout.
     GrVkImage* targetImage = fRenderTarget->msaaImage() ? fRenderTarget->msaaImage()
@@ -162,7 +178,13 @@
     }
 }
 
-void GrVkGpuCommandBuffer::discard() {
+void GrVkGpuCommandBuffer::discard(GrRenderTarget* rt) {
+    GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
+    if (!fRenderTarget) {
+        this->init(target);
+    }
+    SkASSERT(target == fRenderTarget);
+
     CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdBuffer];
     if (cbInfo.fIsEmpty) {
         // We will change the render pass to do a clear load instead
@@ -192,10 +214,16 @@
     }
 }
 
-void GrVkGpuCommandBuffer::onClearStencilClip(const GrFixedClip& clip,
+void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* rt, const GrFixedClip& clip,
                                               bool insideStencilMask) {
     SkASSERT(!clip.hasWindowRectangles());
 
+    GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
+    if (!fRenderTarget) {
+        this->init(target);
+    }
+    SkASSERT(target == fRenderTarget);
+
     CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdBuffer];
 
     GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
@@ -253,10 +281,16 @@
     }
 }
 
-void GrVkGpuCommandBuffer::onClear(const GrFixedClip& clip, GrColor color) {
+void GrVkGpuCommandBuffer::onClear(GrRenderTarget* rt, const GrFixedClip& clip, GrColor color) {
     // parent class should never let us get here with no RT
     SkASSERT(!clip.hasWindowRectangles());
 
+    GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(rt);
+    if (!fRenderTarget) {
+        this->init(target);
+    }
+    SkASSERT(target == fRenderTarget);
+
     CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdBuffer];
 
     VkClearColorValue vkColor;
@@ -462,6 +496,12 @@
                                   const GrMesh* meshes,
                                   int meshCount,
                                   const SkRect& bounds) {
+    GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(pipeline.getRenderTarget());
+    if (!fRenderTarget) {
+        this->init(target);
+    }
+    SkASSERT(target == fRenderTarget);
+
     if (!meshCount) {
         return;
     }
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index 160e4ca..9c6f03d 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -24,7 +24,6 @@
 class GrVkGpuCommandBuffer : public GrGpuCommandBuffer {
 public:
     GrVkGpuCommandBuffer(GrVkGpu* gpu,
-                         GrVkRenderTarget*,
                          const LoadAndStoreInfo& colorInfo,
                          const LoadAndStoreInfo& stencilInfo);
 
@@ -32,11 +31,14 @@
 
     void end() override;
 
-    void discard() override;
+    void discard(GrRenderTarget*) override;
 
     void inlineUpload(GrBatchFlushState* state, GrDrawBatch::DeferredUploadFn& upload) override;
 
 private:
+    // Performs lazy initialization on the first operation seen by the command buffer.
+    void init(GrVkRenderTarget* rt);
+
     GrGpu* gpu() override;
     GrRenderTarget* renderTarget() override;
 
@@ -55,9 +57,9 @@
                 int meshCount,
                 const SkRect& bounds) override;
 
-    void onClear(const GrFixedClip&, GrColor color) override;
+    void onClear(GrRenderTarget*, const GrFixedClip&, GrColor color) override;
 
-    void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override;
+    void onClearStencilClip(GrRenderTarget*, const GrFixedClip&, bool insideStencilMask) override;
 
     void addAdditionalCommandBuffer();
 
@@ -85,6 +87,11 @@
 
     GrVkGpu*                    fGpu;
     GrVkRenderTarget*           fRenderTarget;
+    VkAttachmentLoadOp          fVkColorLoadOp;
+    VkAttachmentStoreOp         fVkColorStoreOp;
+    VkAttachmentLoadOp          fVkStencilLoadOp;
+    VkAttachmentStoreOp         fVkStencilStoreOp;
+    GrColor4f                   fClearColor;
 
     typedef GrGpuCommandBuffer INHERITED;
 };