Vulkan: Store reference to context command buffer.

This frees us from checking the FB every draw. Slightly reduces time
spent in all draw methods. Improvement seen on the draw call overhead
tests. Scores went from 28.17 ns/draw to 26.76 ns/draw on my machine.

In a future improvement we could make this command buffer a dirty bit.
Currently it's a bit slower to call a handler function due to the
dispatch table. Likely we could optimize this by reverting back to a
dirty bit switch and inlining the handler functions. That is left for
future work.

Vulkan is happy enough to run multiple RenderPasses and bind different
Pipelines in the same command buffer. But ANGLE defers RenderPass init
until we submit our work. Thus we can only support one RenderPass per
secondary buffer.

Test: angle_perftests DrawCall*/vulkan_null
Bug: angleproject:3014
Change-Id: I89fd0d9e0822400a5c5a16acb5a9c400a0e71ab5
Reviewed-on: https://chromium-review.googlesource.com/c/1393905
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/CommandGraph.h b/src/libANGLE/renderer/vulkan/CommandGraph.h
index 40d0a7e..840f6bd 100644
--- a/src/libANGLE/renderer/vulkan/CommandGraph.h
+++ b/src/libANGLE/renderer/vulkan/CommandGraph.h
@@ -42,6 +42,21 @@
     WriteTimestamp,
 };
 
+// Receives notifications when a command buffer is no longer able to record. Can be used with
+// inheritance. Faster than using an interface class since it has inlined methods. Could be used
+// with composition by adding a getCommandBuffer method.
+class CommandBufferOwner
+{
+  public:
+    CommandBufferOwner() = default;
+    virtual ~CommandBufferOwner() {}
+
+    ANGLE_INLINE void onCommandBufferFinished() { mCommandBuffer = nullptr; }
+
+  protected:
+    vk::CommandBuffer *mCommandBuffer = nullptr;
+};
+
 // Only used internally in the command graph. Kept in the header for better inlining performance.
 class CommandGraphNode final : angle::NonCopyable
 {
@@ -119,8 +134,22 @@
         mGlobalMemoryBarrierDstAccess |= dstAccess;
     }
 
+    // This can only be set for RenderPass nodes. Each RenderPass node can have at most one owner.
+    void setCommandBufferOwner(CommandBufferOwner *owner)
+    {
+        ASSERT(mCommandBufferOwner == nullptr);
+        mCommandBufferOwner = owner;
+    }
+
   private:
-    void setHasChildren() { mHasChildren = true; }
+    ANGLE_INLINE void setHasChildren()
+    {
+        mHasChildren = true;
+        if (mCommandBufferOwner)
+        {
+            mCommandBufferOwner->onCommandBufferFinished();
+        }
+    }
 
     // Used for testing only.
     bool isChildOf(CommandGraphNode *parent);
@@ -158,6 +187,9 @@
     // For global memory barriers.
     VkFlags mGlobalMemoryBarrierSrcAccess;
     VkFlags mGlobalMemoryBarrierDstAccess;
+
+    // Command buffer notifications.
+    CommandBufferOwner *mCommandBufferOwner;
 };
 
 // This is a helper class for back-end objects used in Vk command buffers. It records a serial
@@ -227,7 +259,7 @@
 
     // Begins a command buffer on the current graph node for in-RenderPass rendering.
     // Called from FramebufferVk::startNewRenderPass and UtilsVk functions.
-    angle::Result beginRenderPass(Context *context,
+    angle::Result beginRenderPass(ContextVk *contextVk,
                                   const Framebuffer &framebuffer,
                                   const gl::Rectangle &renderArea,
                                   const RenderPassDesc &renderPassDesc,