From: Louis-Francis Ratté-Boulianne <l...@collabora.com> When it is detected that a window could have been flipped but has been copied because of suboptimal format/modifier. The Vulkan client should then re-create the swapchain.
Signed-off-by: Louis-Francis Ratté-Boulianne <l...@collabora.com> Reviewed-by: Daniel Stone <dani...@collabora.com> Signed-off-by: Daniel Stone <dani...@collabora.com> --- src/vulkan/wsi/wsi_common_x11.c | 69 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 213a597a430..6b96feb6e58 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -130,6 +130,8 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc, { xcb_query_extension_cookie_t dri3_cookie, pres_cookie, amd_cookie, nv_cookie; xcb_query_extension_reply_t *dri3_reply, *pres_reply, *amd_reply, *nv_reply; + bool has_dri3_v1_1 = false; + bool has_present_v1_1 = false; struct wsi_x11_connection *wsi_conn = vk_alloc(alloc, sizeof(*wsi_conn), 8, @@ -138,7 +140,7 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc, return NULL; dri3_cookie = xcb_query_extension(conn, 4, "DRI3"); - pres_cookie = xcb_query_extension(conn, 7, "PRESENT"); + pres_cookie = xcb_query_extension(conn, 7, "Present"); /* We try to be nice to users and emit a warning if they try to use a * Vulkan application on a system without DRI3 enabled. However, this ends @@ -173,13 +175,27 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc, ver_cookie = xcb_dri3_query_version(conn, 1, 1); ver_reply = xcb_dri3_query_version_reply(conn, ver_cookie, NULL); - wsi_conn->has_dri3_modifiers = + has_dri3_v1_1 = (ver_reply->major_version > 1 || ver_reply->minor_version >= 1); free(ver_reply); } #endif wsi_conn->has_present = pres_reply->present != 0; +#if XCB_PRESENT_MAJOR_VERSION > 1 || XCB_PRESENT_MINOR_VERSION >= 1 + if (wsi_conn->has_present) { + xcb_present_query_version_cookie_t ver_cookie; + xcb_present_query_version_reply_t *ver_reply; + + ver_cookie = xcb_present_query_version(conn, 1, 1); + ver_reply = xcb_present_query_version_reply(conn, ver_cookie, NULL); + has_present_v1_1 = + (ver_reply->major_version > 1 || ver_reply->minor_version >= 1); + free(ver_reply); + } +#endif + + wsi_conn->has_dri3_modifiers = has_dri3_v1_1 && has_present_v1_1; wsi_conn->is_proprietary_x11 = false; if (amd_reply && amd_reply->present) wsi_conn->is_proprietary_x11 = true; @@ -651,6 +667,7 @@ struct x11_swapchain { bool threaded; VkResult status; + xcb_present_complete_mode_t last_present_mode; struct wsi_queue present_queue; struct wsi_queue acquire_queue; pthread_t queue_manager; @@ -684,6 +701,14 @@ x11_swapchain_result(struct x11_swapchain *chain, VkResult result) if (result == VK_TIMEOUT || result == VK_NOT_READY) return result; + /* Suboptimal isn't an error, but is a status which sticks to the swapchain + * and is always returned rather than success. + */ + if (result == VK_SUBOPTIMAL_KHR) { + chain->status = result; + return result; + } + /* No changes, so return the last status. */ return chain->status; } @@ -732,7 +757,28 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, xcb_present_complete_notify_event_t *complete = (void *) event; if (complete->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) chain->last_present_msc = complete->msc; - break; + + VkResult result = VK_SUCCESS; + + /* The winsys is now trying to flip directly and cannot due to our + * configuration. Request the user reallocate. + */ +#if XCB_PRESENT_MAJOR_VERSION > 1 || XCB_PRESENT_MINOR_VERSION >= 1 + if (complete->mode == XCB_PRESENT_COMPLETE_MODE_SUBOPTIMAL_COPY && + chain->last_present_mode != XCB_PRESENT_COMPLETE_MODE_SUBOPTIMAL_COPY) + result = VK_SUBOPTIMAL_KHR; +#endif + + /* When we go from flipping to copying, the odds are very likely that + * we could reallocate in a more optimal way if we didn't have to care + * about scanout, so we always do this. + */ + if (complete->mode == XCB_PRESENT_COMPLETE_MODE_COPY && + chain->last_present_mode == XCB_PRESENT_COMPLETE_MODE_FLIP) + result = VK_SUBOPTIMAL_KHR; + + chain->last_present_mode = complete->mode; + return result; } default: @@ -876,6 +922,11 @@ x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index, if (chain->base.present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) options |= XCB_PRESENT_OPTION_ASYNC; +#if XCB_PRESENT_MAJOR_VERSION > 1 || XCB_PRESENT_MINOR_VERSION >= 1 + if (chain->has_dri3_modifiers) + options |= XCB_PRESENT_OPTION_SUBOPTIMAL; +#endif + xshmfence_reset(image->shm_fence); ++chain->send_sbc; @@ -1276,6 +1327,18 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, chain->status = VK_SUCCESS; chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers; + /* If we are reallocating from an old swapchain, then we inherit its + * last completion mode, to ensure we don't get into reallocation + * cycles. If we are starting anew, we set 'COPY', as that is the only + * mode which provokes reallocation when anything changes, to make + * sure we have the most optimal allocation. + */ + struct x11_swapchain *old_chain = (void *) pCreateInfo->oldSwapchain; + if (old_chain) + chain->last_present_mode = old_chain->last_present_mode; + else + chain->last_present_mode = XCB_PRESENT_COMPLETE_MODE_COPY; + if (!wsi_x11_check_dri3_compatible(conn, local_fd)) chain->base.use_prime_blit = true; -- 2.14.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev