swapchain: avoid redundant disconnect/connect for new surface
Platform API contract ensures VkSurfaceKHR is created with a new or
disconnected ANativeWindow. Then the first swapchain created against the
new surface can skip the disconnect/connect of the native window, which
saves 2 binder IPC calls.
In theory, the same can be skipped until the first successful present
call. We dirty the bit at the end of swapchain creation to avoid extra
external synchronization.
Bug: 275176234
Bug: 265763295
Test: no deadlock against ANGLE eglCreateWindowSurface
Change-Id: Ic2d09e4547e0ec7e910863c77a4657d52e9366fd
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 922a44f..5965953 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -227,6 +227,10 @@
android::sp<ANativeWindow> window;
VkSwapchainKHR swapchain_handle;
uint64_t consumer_usage;
+
+ // Indicate whether this surface has been used by a swapchain, no matter the
+ // swapchain is still current or has been destroyed.
+ bool used_by_swapchain;
};
VkSurfaceKHR HandleFromSurface(Surface* surface) {
@@ -601,6 +605,7 @@
surface->window = pCreateInfo->window;
surface->swapchain_handle = VK_NULL_HANDLE;
+ surface->used_by_swapchain = false;
int err = native_window_get_consumer_usage(surface->window.get(),
&surface->consumer_usage);
if (err != android::OK) {
@@ -1394,14 +1399,20 @@
// orphans the previous buffers, getting us back to the state where we can
// dequeue all buffers.
//
+ // This is not necessary if the surface was never used previously.
+ //
// TODO(http://b/134186185) recycle swapchain images more efficiently
ANativeWindow* window = surface.window.get();
- err = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
- ALOGW_IF(err != android::OK, "native_window_api_disconnect failed: %s (%d)",
- strerror(-err), err);
- err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)",
- strerror(-err), err);
+ if (surface.used_by_swapchain) {
+ err = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ ALOGW_IF(err != android::OK,
+ "native_window_api_disconnect failed: %s (%d)", strerror(-err),
+ err);
+ err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ ALOGW_IF(err != android::OK,
+ "native_window_api_connect failed: %s (%d)", strerror(-err),
+ err);
+ }
err =
window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1});
@@ -1787,6 +1798,7 @@
android::GraphicsEnv::getInstance().setTargetStats(
android::GpuStatsInfo::Stats::CREATED_VULKAN_SWAPCHAIN);
+ surface.used_by_swapchain = true;
surface.swapchain_handle = HandleFromSwapchain(swapchain);
*swapchain_handle = surface.swapchain_handle;
return VK_SUCCESS;