From 08f0fd8bd6ca4cd84d05a84f5f0dddad8a07cebd Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Thu, 22 Jan 2026 12:13:11 -0800 Subject: [PATCH] vulkan/wsi/display: Don't re-probe connectors in between hotplugs. The state we return is a single plane per connector, and (effectively) whether we're currently presenting on it. We already know what connectors we're presenting on, and there's no reason to re-probe for hotplugged connectors here to learn that they're not active -- vkGetPhysicalDeviceDisplayProperties2KHR() is what you'd need to do to get far more important information about the connector in the first place. Running dEQP-VK.wsi.direct_drm.maintenance1.present\* on my CFL goes from 5.5s to 4.4s due to not re-probing EDID over and over. Part-of: --- src/vulkan/wsi/wsi_common_display.c | 30 +++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c index 37eb40adb56..2b599ed9b9b 100644 --- a/src/vulkan/wsi/wsi_common_display.c +++ b/src/vulkan/wsi/wsi_common_display.c @@ -226,6 +226,10 @@ struct wsi_display { pthread_t hotplug_thread; struct list_head connectors; /* list of all discovered connectors */ + /* Flag that we've called wsi_get_connectors() with the current fd. + */ + bool get_connectors_current; + mtx_t connectors_mutex; /* A unique monotonically increasing value to associate with an individual * colorimetry outcome on the output. This is used to avoid propagating @@ -893,13 +897,18 @@ wsi_get_connectors(VkPhysicalDevice physicalDevice) struct wsi_display *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; - if (wsi->fd < 0) + mtx_lock(&wsi->connectors_mutex); + if (wsi->fd < 0 || wsi->get_connectors_current) { + mtx_unlock(&wsi->connectors_mutex); return VK_SUCCESS; + } drmModeResPtr mode_res = drmModeGetResources(wsi->fd); - if (!mode_res) + if (!mode_res) { + mtx_unlock(&wsi->connectors_mutex); return VK_ERROR_OUT_OF_HOST_MEMORY; + } /* Get current information */ for (int c = 0; c < mode_res->count_connectors; c++) { @@ -908,10 +917,14 @@ wsi_get_connectors(VkPhysicalDevice physicalDevice) mode_res->connectors[c]); if (!connector) { drmModeFreeResources(mode_res); + mtx_unlock(&wsi->connectors_mutex); return VK_ERROR_OUT_OF_HOST_MEMORY; } } + wsi->get_connectors_current = true; + mtx_unlock(&wsi->connectors_mutex); + drmModeFreeResources(mode_res); return VK_SUCCESS; } @@ -3509,6 +3522,9 @@ udev_event_listener_thread(void *data) * and wsi_display_wait_for_event. */ mtx_lock(&wsi->wait_mutex); + mtx_lock(&wsi->connectors_mutex); + wsi->get_connectors_current = false; + mtx_unlock(&wsi->connectors_mutex); u_cnd_monotonic_broadcast(&wsi->hotplug_cond); list_for_each_entry(struct wsi_display_fence, fence, &wsi_device->hotplug_fences, link) { @@ -3591,6 +3607,12 @@ wsi_display_init_wsi(struct wsi_device *wsi_device, goto fail_mutex; } + ret = mtx_init(&wsi->connectors_mutex, mtx_plain); + if (ret != thrd_success) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail_mutex2; + } + ret = u_cnd_monotonic_init(&wsi->wait_cond); if (ret != thrd_success) { result = VK_ERROR_OUT_OF_HOST_MEMORY; @@ -3618,6 +3640,8 @@ wsi_display_init_wsi(struct wsi_device *wsi_device, fail_hotplug_cond: u_cnd_monotonic_destroy(&wsi->wait_cond); fail_cond: + mtx_destroy(&wsi->connectors_mutex); +fail_mutex2: mtx_destroy(&wsi->wait_mutex); fail_mutex: vk_free(alloc, wsi); @@ -3643,6 +3667,7 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device, pthread_join(wsi->hotplug_thread, NULL); } + mtx_destroy(&wsi->connectors_mutex); mtx_destroy(&wsi->wait_mutex); u_cnd_monotonic_destroy(&wsi->wait_cond); u_cnd_monotonic_destroy(&wsi->hotplug_cond); @@ -3670,6 +3695,7 @@ wsi_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, if (wsi->fd != wsi->device_fd) close(wsi->fd); wsi->fd = wsi->device_fd; + wsi->get_connectors_current = false; } struct wsi_display_connector *connector =