From abc464f3a9de89de9806ec6354022d892f76c09e Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Tue, 4 Oct 2022 17:43:24 -0300 Subject: [PATCH] vulkan/wsi/wayland: introduce struct wsi_wl_surface In the following commits we add dma-buf feedback support. In order to do that, we need to keep the feedback tied to the lifetime of the surface, instead of tied to the lifetime of the chain. Why do we need this change? The reason is per-surface feedback and swapchain re-creation. If we receive feedback and return SUBOPTIMAL to the client in the next acquireNextImage() call, it may re-create the swapchain. If it doesn't pass us the oldSwapchain, we won't have access to the surface feedback data (as it was tied to the oldSwapchain). We could bind again to the surface feedback, but compositors may have a transient state when we bind to surface feedback, and send a non-optimal batch of dma-buf feedback which is updated when the drawing loop starts. So we would re-create the chain with this non-optimal batch, and after a few moments receive new feedback. This could potentially lead into an allocation loop, so it is not safe. Tying the feedback to the lifetime of the VkSurface we don't have to re-bind to the surface dma-buf feedback every time that the swapchain is re-created, avoiding this dangerous allocation loop described above. So add struct wsi_wl_surface in order to add support for dma-buf feedback. For now it is just the stub, but in the next commits we start making use of that. Reviewed-by: Simon Ser Signed-off-by: Leandro Ribeiro Part-of: --- src/vulkan/wsi/wsi_common.c | 7 +++++++ src/vulkan/wsi/wsi_common_private.h | 4 ++++ src/vulkan/wsi/wsi_common_wayland.c | 24 +++++++++++++++++++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c index 480cefec934..4d2ddd962a0 100644 --- a/src/vulkan/wsi/wsi_common.c +++ b/src/vulkan/wsi/wsi_common.c @@ -257,6 +257,13 @@ wsi_DestroySurfaceKHR(VkInstance _instance, if (!surface) return; +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND) { + wsi_wl_surface_destroy(surface, _instance, pAllocator); + return; + } +#endif + vk_free2(&instance->alloc, pAllocator, surface); } diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h index 3bc79597b82..fe3e85556b8 100644 --- a/src/vulkan/wsi/wsi_common_private.h +++ b/src/vulkan/wsi/wsi_common_private.h @@ -168,6 +168,10 @@ struct wsi_swapchain { bool wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd); +void +wsi_wl_surface_destroy(VkIcdSurfaceBase *icd_surface, VkInstance _instance, + const VkAllocationCallbacks *pAllocator); + VkResult wsi_swapchain_init(const struct wsi_device *wsi, struct wsi_swapchain *chain, diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index 70ae7f20ab8..9677b74c7e3 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -101,6 +101,10 @@ enum wsi_wl_buffer_type { WSI_WL_BUFFER_SHM_MEMCPY, }; +struct wsi_wl_surface { + VkIcdSurfaceWayland base; +}; + struct wsi_wl_swapchain { struct wsi_swapchain base; @@ -921,6 +925,17 @@ wsi_wl_surface_get_present_rectangles(VkIcdSurfaceBase *surface, return vk_outarray_status(&out); } +void +wsi_wl_surface_destroy(VkIcdSurfaceBase *icd_surface, VkInstance _instance, + const VkAllocationCallbacks *pAllocator) +{ + VK_FROM_HANDLE(vk_instance, instance, _instance); + struct wsi_wl_surface *wsi_wl_surface = + wl_container_of((VkIcdSurfaceWayland *)icd_surface, wsi_wl_surface, base); + + vk_free2(&instance->alloc, pAllocator, wsi_wl_surface); +} + VKAPI_ATTR VkResult VKAPI_CALL wsi_CreateWaylandSurfaceKHR(VkInstance _instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, @@ -928,15 +943,18 @@ wsi_CreateWaylandSurfaceKHR(VkInstance _instance, VkSurfaceKHR *pSurface) { VK_FROM_HANDLE(vk_instance, instance, _instance); + struct wsi_wl_surface *wsi_wl_surface; VkIcdSurfaceWayland *surface; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR); - surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (surface == NULL) + wsi_wl_surface = vk_zalloc2(&instance->alloc, pAllocator, sizeof *wsi_wl_surface, + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (wsi_wl_surface == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY; + surface = &wsi_wl_surface->base; + surface->base.platform = VK_ICD_WSI_PLATFORM_WAYLAND; surface->display = pCreateInfo->display; surface->surface = pCreateInfo->surface;