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 ¤tSubmitSerial);
+ // 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;