Vulkan: Optimize ContextVk::setupDraw.

This improves performance significantly in the Vulkan CPU overhead
test.

Bug: angleproject:2786
Change-Id: I911bc66a6b2d11dd3848ffa90927b314aeadfc24
Reviewed-on: https://chromium-review.googlesource.com/1194301
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 491b699..72ce9a8 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -354,6 +354,8 @@
 
     bool hasAttachedShader() const;
 
+    const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
+
   private:
     friend class MemoryProgramCache;
     friend class Program;
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index 7cff59d..e3152d2 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -257,21 +257,16 @@
                                    const DirtyBits &dirtyBitsMask,
                                    vk::CommandBuffer **commandBufferOut)
 {
+    // Set any dirty bits that depend on draw call parameters or other objects.
     if (drawCallParams.mode() != mCurrentDrawMode)
     {
         invalidateCurrentPipeline();
         mCurrentDrawMode = drawCallParams.mode();
     }
 
-    const gl::State &state       = mState.getState();
-    const gl::Program *programGL = state.getProgram();
-
-    vk::RecordingMode mode;
-    ANGLE_TRY(mDrawFramebuffer->getCommandBufferForDraw(this, commandBufferOut, &mode));
-
-    // Set any dirty bits that depend on draw call parameters or other objects.
-    if (mode == vk::RecordingMode::Start)
+    if (!mDrawFramebuffer->appendToStartedRenderPass(mRenderer, commandBufferOut))
     {
+        ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, commandBufferOut));
         mDirtyBits |= mNewCommandBufferDirtyBits;
     }
 
@@ -317,7 +312,7 @@
 
                 // TODO(jmadill): Should probably merge this for loop with programVk's descriptor
                 // update.
-                for (size_t textureIndex : programGL->getActiveSamplersMask())
+                for (size_t textureIndex : mProgram->getState().getActiveSamplersMask())
                 {
                     // Ensure any writes to the textures are flushed before we read from them.
                     TextureVk *textureVk = mActiveTextures[textureIndex];
@@ -348,7 +343,7 @@
             case DIRTY_BIT_VERTEX_BUFFERS:
             {
                 BindNonNullVertexBufferRanges(*commandBufferOut,
-                                              programGL->getActiveAttribLocationsMask(),
+                                              mProgram->getState().getActiveAttribLocationsMask(),
                                               mProgram->getState().getMaxActiveAttribLocation(),
                                               mVertexArray->getCurrentArrayBufferHandles(),
                                               mVertexArray->getCurrentArrayBufferOffsets());
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 0b72091..e1ad661 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -1087,6 +1087,12 @@
         return angle::Result::Continue();
     }
 
+    return startNewRenderPass(contextVk, commandBufferOut);
+}
+
+angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
+                                                vk::CommandBuffer **commandBufferOut)
+{
     vk::Framebuffer *framebuffer = nullptr;
     ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));
 
@@ -1120,7 +1126,6 @@
     gl::Rectangle renderArea =
         gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height);
 
-    *modeOut = vk::RecordingMode::Start;
     return beginRenderPass(contextVk, *framebuffer, renderArea, mRenderPassDesc.value(),
                            attachmentClearValues, commandBufferOut);
 }
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h
index 133eb73..059f96a 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.h
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -90,9 +90,6 @@
                                 GLfloat *xy) const override;
     RenderTargetVk *getDepthStencilRenderTarget() const;
     const vk::RenderPassDesc &getRenderPassDesc();
-    angle::Result getCommandBufferForDraw(ContextVk *contextVk,
-                                          vk::CommandBuffer **commandBufferOut,
-                                          vk::RecordingMode *modeOut);
 
     // Internal helper function for readPixels operations.
     angle::Result readPixelsImpl(ContextVk *contextVk,
@@ -107,11 +104,21 @@
     gl::DrawBufferMask getEmulatedAlphaAttachmentMask();
     RenderTargetVk *getColorReadRenderTarget() const;
 
+    // This will clear the current write operation if it is complete.
+    using CommandGraphResource::appendToStartedRenderPass;
+
+    angle::Result startNewRenderPass(ContextVk *context, vk::CommandBuffer **commandBufferOut);
+
   private:
     FramebufferVk(RendererVk *renderer,
                   const gl::FramebufferState &state,
                   WindowSurfaceVk *backbuffer);
 
+    // Helper for appendToStarted/else startNewRenderPass.
+    angle::Result getCommandBufferForDraw(ContextVk *contextVk,
+                                          vk::CommandBuffer **commandBufferOut,
+                                          vk::RecordingMode *modeOut);
+
     // The 'in' rectangles must be clipped to the scissor and FBO. The clipping is done in 'blit'.
     void blitWithCommand(vk::CommandBuffer *commandBuffer,
                          const gl::Rectangle &readRectIn,