Pass Context to VertexArray and Framebuffer syncstate.

This will enable more Vulkan-friendly idioms like clearing the
vulkan pipeline caches correctly on GL state changes immediately
because we have access to the ContextVk.

BUG=angleproject:1898

Change-Id: I16c848d8abdde8e26a38d384e565cec8548a66d0
Reviewed-on: https://chromium-review.googlesource.com/459079
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/FramebufferImpl.h b/src/libANGLE/renderer/FramebufferImpl.h
index dceef5f..67b2d95 100644
--- a/src/libANGLE/renderer/FramebufferImpl.h
+++ b/src/libANGLE/renderer/FramebufferImpl.h
@@ -73,7 +73,8 @@
 
     virtual bool checkStatus() const = 0;
 
-    virtual void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
+    virtual void syncState(ContextImpl *contextImpl,
+                           const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
 
     virtual gl::Error getSamplePosition(size_t index, GLfloat *xy) const = 0;
 
diff --git a/src/libANGLE/renderer/FramebufferImpl_mock.h b/src/libANGLE/renderer/FramebufferImpl_mock.h
index 7fc62e4..7ca7754 100644
--- a/src/libANGLE/renderer/FramebufferImpl_mock.h
+++ b/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -46,7 +46,7 @@
 
     MOCK_CONST_METHOD0(checkStatus, bool());
 
-    MOCK_METHOD1(syncState, void(const gl::Framebuffer::DirtyBits &));
+    MOCK_METHOD2(syncState, void(ContextImpl *, const gl::Framebuffer::DirtyBits &));
 
     MOCK_METHOD0(destructor, void());
 };
diff --git a/src/libANGLE/renderer/VertexArrayImpl.h b/src/libANGLE/renderer/VertexArrayImpl.h
index b1be369..a933ba2 100644
--- a/src/libANGLE/renderer/VertexArrayImpl.h
+++ b/src/libANGLE/renderer/VertexArrayImpl.h
@@ -15,13 +15,14 @@
 
 namespace rx
 {
+class ContextImpl;
 
 class VertexArrayImpl : angle::NonCopyable
 {
   public:
     VertexArrayImpl(const gl::VertexArrayState &data) : mData(data) {}
     virtual ~VertexArrayImpl() { }
-    virtual void syncState(const gl::VertexArray::DirtyBits &dirtyBits) {}
+    virtual void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) {}
   protected:
     const gl::VertexArrayState &mData;
 };
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index 3b4d080..4ef149d 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -296,7 +296,8 @@
     return true;
 }
 
-void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+void FramebufferD3D::syncState(ContextImpl *contextImpl,
+                               const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     bool invalidateColorAttachmentCache = false;
 
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/libANGLE/renderer/d3d/FramebufferD3D.h
index 16d4971..c6eab56 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.h
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -95,7 +95,7 @@
 
     bool checkStatus() const override;
 
-    void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     const gl::AttachmentList &getColorAttachmentsForRender() const;
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index eeda40a..5a51f14 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -377,7 +377,7 @@
                              &mDepthStencilRenderTargetDirty);
 }
 
-void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+void Framebuffer11::syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     mRenderer->getStateManager()->invalidateRenderTarget();
 
@@ -410,7 +410,7 @@
     // We should not have dirtied any additional state during our sync.
     ASSERT(!mInternalDirtyBits.any());
 
-    FramebufferD3D::syncState(dirtyBits);
+    FramebufferD3D::syncState(contextImpl, dirtyBits);
 }
 
 void Framebuffer11::signal(SignalToken token)
@@ -439,9 +439,9 @@
     return mInternalDirtyBits.any();
 }
 
-void Framebuffer11::syncInternalState()
+void Framebuffer11::syncInternalState(ContextImpl *contextImpl)
 {
-    syncState(gl::Framebuffer::DirtyBits());
+    syncState(contextImpl, gl::Framebuffer::DirtyBits());
 }
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
index e75fc29..2178ce7 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -30,7 +30,7 @@
     // Invalidate the cached swizzles of all bound texture attachments.
     gl::Error markAttachmentsDirty() const;
 
-    void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     const RenderTargetArray &getCachedColorRenderTargets() const
     {
@@ -42,7 +42,7 @@
     }
 
     bool hasAnyInternalDirtyBit() const;
-    void syncInternalState();
+    void syncInternalState(ContextImpl *contextImpl);
 
     void signal(angle::SignalToken token) override;
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 2449734..82a1199 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -1592,15 +1592,16 @@
     return gl::NoError();
 }
 
-gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode)
+gl::Error Renderer11::updateState(ContextImpl *contextImpl, GLenum drawMode)
 {
+    const auto &data    = contextImpl->getContextState();
     const auto &glState = data.getState();
 
     // Applies the render target surface, depth stencil surface, viewport rectangle and
     // scissor rectangle to the renderer
     gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
-    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->complete(data));
-    ANGLE_TRY(applyRenderTarget(framebuffer));
+    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
+    ANGLE_TRY(mStateManager.syncFramebuffer(contextImpl, framebuffer));
 
     // Set the present path state
     auto firstColorAttachment        = framebuffer->getFirstColorbuffer();
@@ -1703,11 +1704,6 @@
     return count >= minCount;
 }
 
-gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
-{
-    return mStateManager.syncFramebuffer(framebuffer);
-}
-
 gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
                                         GLenum mode,
                                         GLint first,
@@ -4664,7 +4660,7 @@
         return gl::NoError();
     }
 
-    ANGLE_TRY(updateState(data, mode));
+    ANGLE_TRY(updateState(context, mode));
 
     TranslatedIndexData indexInfo;
     indexInfo.indexRange = indexRange;
@@ -4712,7 +4708,7 @@
         return gl::NoError();
     }
 
-    ANGLE_TRY(updateState(data, mode));
+    ANGLE_TRY(updateState(context, mode));
     ANGLE_TRY(applyTransformFeedbackBuffers(data));
     ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
     ANGLE_TRY(applyTextures(context, data));
@@ -4747,7 +4743,7 @@
 
     ANGLE_TRY(generateSwizzles(data));
     applyPrimitiveType(mode, 0, usesPointSize);
-    ANGLE_TRY(updateState(data, mode));
+    ANGLE_TRY(updateState(context, mode));
     ANGLE_TRY(applyTransformFeedbackBuffers(data));
     ASSERT(!glState.isTransformFeedbackActiveUnpaused());
     ANGLE_TRY(applyTextures(context, data));
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index 92a6606..5a22348 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -145,10 +145,9 @@
                                 const std::vector<GLint> &vertexUniformBuffers,
                                 const std::vector<GLint> &fragmentUniformBuffers) override;
 
-    gl::Error updateState(const gl::ContextState &data, GLenum drawMode);
+    gl::Error updateState(ContextImpl *contextImpl, GLenum drawMode);
 
     bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
-    gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer);
     gl::Error applyUniforms(const ProgramD3D &programD3D,
                             GLenum drawMode,
                             const std::vector<D3DUniform *> &uniformArray) override;
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index acd3a43..224e0fb 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -980,7 +980,7 @@
     mCurrentValueAttribs.clear();
 }
 
-gl::Error StateManager11::syncFramebuffer(gl::Framebuffer *framebuffer)
+gl::Error StateManager11::syncFramebuffer(ContextImpl *contextImpl, gl::Framebuffer *framebuffer)
 {
     Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
     ANGLE_TRY(framebuffer11->markAttachmentsDirty());
@@ -988,7 +988,7 @@
     if (framebuffer11->hasAnyInternalDirtyBit())
     {
         ASSERT(framebuffer->id() != 0);
-        framebuffer11->syncInternalState();
+        framebuffer11->syncInternalState(contextImpl);
     }
 
     if (!mRenderTargetIsDirty)
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
index 184c947..8de838b 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -77,7 +77,7 @@
                            ID3D11ShaderResourceView *srv);
     gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
 
-    gl::Error syncFramebuffer(gl::Framebuffer *framebuffer);
+    gl::Error syncFramebuffer(ContextImpl *contextImpl, gl::Framebuffer *framebuffer);
 
     void invalidateRenderTarget();
     void invalidateBoundViews();
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index 1db9cd8..d5768d6 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -40,7 +40,7 @@
     }
 }
 
-void VertexArray11::syncState(const gl::VertexArray::DirtyBits &dirtyBits)
+void VertexArray11::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits)
 {
     for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
     {
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
index ced2c65..6dc682a 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -23,7 +23,7 @@
     VertexArray11(const gl::VertexArrayState &data);
     ~VertexArray11() override;
 
-    void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) override;
     // This will flush any pending attrib updates and then check the dynamic attribs mask.
     bool hasDynamicAttrib(const gl::State &state);
     gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index a1735f8..54d43e7 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -1000,7 +1000,7 @@
     // Applies the render target surface, depth stencil surface, viewport rectangle and
     // scissor rectangle to the renderer
     gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
-    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->complete(data));
+    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
 
     ANGLE_TRY(applyRenderTarget(context, framebuffer));
 
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index b5b5bb0..7c41638 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -407,7 +407,7 @@
     return (status == GL_FRAMEBUFFER_COMPLETE);
 }
 
-void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits)
+void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::DirtyBits &dirtyBits)
 {
     // Don't need to sync state for the default FBO.
     if (mIsDefault)
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.h b/src/libANGLE/renderer/gl/FramebufferGL.h
index 847e67d..31d13d6 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.h
+++ b/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -80,7 +80,7 @@
 
     bool checkStatus() const override;
 
-    void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     GLuint getFramebufferID() const;
     bool isDefault() const;
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index e077fcc..51faf86 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -524,7 +524,7 @@
     }
 }
 
-void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits)
+void VertexArrayGL::syncState(ContextImpl *contextImpl, const VertexArray::DirtyBits &dirtyBits)
 {
     for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
     {
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/libANGLE/renderer/gl/VertexArrayGL.h
index 282f27c..a114bd1 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.h
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.h
@@ -41,7 +41,7 @@
     GLuint getVertexArrayID() const;
     GLuint getAppliedElementArrayBufferID() const;
 
-    void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) override;
 
   private:
     gl::Error syncDrawState(const gl::AttributesMask &activeAttributesMask,
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/libANGLE/renderer/null/FramebufferNULL.cpp
index d0deef6..fe97b66 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.cpp
+++ b/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -128,7 +128,8 @@
     return true;
 }
 
-void FramebufferNULL::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+void FramebufferNULL::syncState(ContextImpl *contextImpl,
+                                const gl::Framebuffer::DirtyBits &dirtyBits)
 {
 }
 
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.h b/src/libANGLE/renderer/null/FramebufferNULL.h
index a97e1ea..cd48c25 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.h
+++ b/src/libANGLE/renderer/null/FramebufferNULL.h
@@ -62,7 +62,7 @@
 
     bool checkStatus() const override;
 
-    void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
 };
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 9c60c1f..2e52a54 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -78,22 +78,12 @@
 }
 
 FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
-    : FramebufferImpl(state),
-      mBackbuffer(nullptr),
-      mRenderPass(),
-      mFramebuffer(),
-      mDirtyRenderPass(true),
-      mDirtyFramebuffer(true)
+    : FramebufferImpl(state), mBackbuffer(nullptr), mRenderPass(), mFramebuffer()
 {
 }
 
 FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
-    : FramebufferImpl(state),
-      mBackbuffer(backbuffer),
-      mRenderPass(),
-      mFramebuffer(),
-      mDirtyRenderPass(true),
-      mDirtyFramebuffer(true)
+    : FramebufferImpl(state), mBackbuffer(backbuffer), mRenderPass(), mFramebuffer()
 {
 }
 
@@ -348,16 +338,20 @@
     return bool();
 }
 
-void FramebufferVk::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+void FramebufferVk::syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits)
 {
+    auto contextVk = GetAs<ContextVk>(contextImpl);
+
+    ASSERT(dirtyBits.any());
+
     // TODO(jmadill): Smarter update.
-    mDirtyRenderPass  = true;
-    mDirtyFramebuffer = true;
+    mRenderPass.destroy(contextVk->getDevice());
+    mFramebuffer.destroy(contextVk->getDevice());
 }
 
 gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
 {
-    if (mRenderPass.valid() && !mDirtyRenderPass)
+    if (mRenderPass.valid())
     {
         return &mRenderPass;
     }
@@ -461,15 +455,13 @@
 
     mRenderPass.retain(device, std::move(renderPass));
 
-    mDirtyRenderPass = false;
-
     return &mRenderPass;
 }
 
 gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice device)
 {
     // If we've already created our cached Framebuffer, return it.
-    if (mFramebuffer.valid() && !mDirtyFramebuffer)
+    if (mFramebuffer.valid())
     {
         return &mFramebuffer;
     }
@@ -532,8 +524,6 @@
 
     mFramebuffer.retain(device, std::move(framebuffer));
 
-    mDirtyFramebuffer = false;
-
     return &mFramebuffer;
 }
 
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h
index ece24e5..95e04c2 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.h
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -75,7 +75,7 @@
 
     bool checkStatus() const override;
 
-    void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+    void syncState(ContextImpl *contextImpl, const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
 
@@ -96,8 +96,6 @@
 
     vk::RenderPass mRenderPass;
     vk::Framebuffer mFramebuffer;
-    bool mDirtyRenderPass;
-    bool mDirtyFramebuffer;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 9f639b9..5e59fb2 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -11,6 +11,8 @@
 
 #include "common/debug.h"
 
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+
 namespace rx
 {
 
@@ -22,4 +24,9 @@
 {
 }
 
+void VertexArrayVk::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits)
+{
+    ASSERT(dirtyBits.any());
+}
+
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
index 9340d27..7592bc0 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -20,6 +20,8 @@
   public:
     VertexArrayVk(const gl::VertexArrayState &data);
     ~VertexArrayVk() override;
+
+    void syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) override;
 };
 
 }  // namespace rx