Vulkan: SurfaceVk should only wait for GPU work that uses it

Right now when we destroy swapchain, we call mRenderer->finish() to
finish everything, even though the work is unrelated to this surface.
This CL changes it to only wait for ResourceUse of all images in the
swapChain.

Bug: b/267806287
Change-Id: I33d136ad50961fbf5fbb200ff0f89f1dbf23585d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4220723
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Charlie Lao <cclao@google.com>
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 6c54532..8b35420 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -5221,15 +5221,6 @@
     return mCommandQueue.waitForResourceUseToFinishWithUserTimeout(context, use, timeout, result);
 }
 
-angle::Result RendererVk::finish(vk::Context *context)
-{
-    if (isAsyncCommandQueueEnabled())
-    {
-        ANGLE_TRY(mCommandProcessor.waitForAllWorkToBeSubmitted(context));
-    }
-    return mCommandQueue.waitIdle(context, getMaxFenceWaitTimeNs());
-}
-
 angle::Result RendererVk::flushWaitSemaphores(
     vk::ProtectionType protectionType,
     std::vector<VkSemaphore> &&waitSemaphores,
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.h b/src/libANGLE/renderer/vulkan/RendererVk.h
index 1f761b9..e3f7210 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.h
+++ b/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -634,7 +634,6 @@
                                                             const vk::ResourceUse &use,
                                                             uint64_t timeout,
                                                             VkResult *result);
-    angle::Result finish(vk::Context *context);
     angle::Result checkCompletedCommands(vk::Context *context);
 
     angle::Result flushWaitSemaphores(vk::ProtectionType protectionType,
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index c769eca..42c00a0 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -895,9 +895,8 @@
     VkInstance instance  = renderer->getInstance();
 
     // flush the pipe.
-    (void)renderer->finish(displayVk);
-
     (void)renderer->waitForPresentToBeSubmitted(&mSwapchainStatus);
+    (void)finish(displayVk);
 
     if (mLockBufferHelper.valid())
     {
@@ -965,6 +964,10 @@
     DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
 
     angle::Result result = contextVk->onSurfaceUnMakeCurrent(this);
+    // Even though all swap chain images are tracked individually, the semaphores are not tracked by
+    // ResourceUse. This propagates context's queue serial to surface when it detaches from context
+    // so that surface will always wait until context is finished.
+    mUse.setQueueSerial(contextVk->getLastSubmittedQueueSerial());
 
     return angle::ToEGL(result, displayVk, EGL_BAD_CURRENT_SURFACE);
 }
@@ -1295,7 +1298,7 @@
     static constexpr size_t kMaxOldSwapchains = 5;
     if (mOldSwapchains.size() > kMaxOldSwapchains)
     {
-        ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
+        ANGLE_TRY(finish(contextVk));
         for (SwapchainCleanupData &oldSwapchain : mOldSwapchains)
         {
             oldSwapchain.destroy(contextVk->getDevice(), &mPresentSemaphoreRecycler);
@@ -1499,7 +1502,7 @@
     // that case as a workaround.
     if (lastSwapchain && renderer->getFeatures().waitIdleBeforeSwapchainRecreation.enabled)
     {
-        ANGLE_TRY(renderer->finish(context));
+        ANGLE_TRY(finish(context));
     }
 
     // TODO: Once EGL_SWAP_BEHAVIOR_PRESERVED_BIT is supported, the contents of the old swapchain
@@ -1723,6 +1726,20 @@
     mSwapchainImages.clear();
 }
 
+angle::Result WindowSurfaceVk::finish(vk::Context *context)
+{
+    RendererVk *renderer = context->getRenderer();
+
+    mUse.merge(mDepthStencilImage.getResourceUse());
+    mUse.merge(mColorImageMS.getResourceUse());
+    for (SwapchainImage &swapchainImage : mSwapchainImages)
+    {
+        mUse.merge(swapchainImage.image.getResourceUse());
+    }
+
+    return renderer->finishResourceUse(context, mUse);
+}
+
 void WindowSurfaceVk::destroySwapChainImages(DisplayVk *displayVk)
 {
     RendererVk *renderer = displayVk->getRenderer();
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.h b/src/libANGLE/renderer/vulkan/SurfaceVk.h
index 9e3393b..aaf4b98 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.h
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -21,7 +21,7 @@
 {
 class RendererVk;
 
-class SurfaceVk : public SurfaceImpl, public angle::ObserverInterface
+class SurfaceVk : public SurfaceImpl, public angle::ObserverInterface, public vk::Resource
 {
   public:
     angle::Result getAttachmentRenderTarget(const gl::Context *context,
@@ -378,6 +378,9 @@
     // not ahead of the frame being rendered by *one* frame.
     angle::Result throttleCPU(ContextVk *contextVk, const QueueSerial &currentSubmitSerial);
 
+    // Finish all GPU operations on the surface
+    angle::Result finish(vk::Context *context);
+
     void updateOverlay(ContextVk *contextVk) const;
     bool overlayHasEnabledWidget(ContextVk *contextVk) const;
     angle::Result drawOverlay(ContextVk *contextVk, impl::SwapchainImage *image) const;