From 010b497cf6491bd3d4e103db3110b24de17d4a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Sun, 10 Dec 2023 11:03:54 +0100 Subject: [PATCH] winevulkan: Return VK_SUBOPTIMAL_KHR from vkQueuePresentKHR after resize. --- dlls/vulkan-1/tests/vulkan.c | 3 --- dlls/winevulkan/vulkan.c | 34 ++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 2 ++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index 716a524e796..71ad2c4cf34 100644 --- a/dlls/vulkan-1/tests/vulkan.c +++ b/dlls/vulkan-1/tests/vulkan.c @@ -762,11 +762,8 @@ static void test_win32_surface_swapchain_hwnd(VkDevice device, VkSwapchainKHR sw vr = vkQueuePresentKHR(queue, &present_info); if (expect_suboptimal) - { - todo_wine ok(vr == VK_SUBOPTIMAL_KHR || broken(vr == VK_ERROR_OUT_OF_DATE_KHR) /* Nvidia */, "Got unexpected vr %d.\n", vr); - } else if (IsWindow(hwnd)) ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr); else diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 21e5952caf4..5f513b96480 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -1624,6 +1624,12 @@ void wine_vkDestroySurfaceKHR(VkInstance handle, VkSurfaceKHR surface, free(object); } +static BOOL extents_equals(const VkExtent2D *extents, const RECT *rect) +{ + return extents->width == rect->right - rect->left && + extents->height == rect->bottom - rect->top; +} + VkResult wine_vkCreateSwapchainKHR(VkDevice device_handle, const VkSwapchainCreateInfoKHR *create_info, const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain_handle) { @@ -1661,6 +1667,9 @@ VkResult wine_vkCreateSwapchainKHR(VkDevice device_handle, const VkSwapchainCrea return res; } + object->surface = surface; + object->extents = create_info->imageExtent; + *swapchain_handle = wine_swapchain_to_handle(object); add_handle_mapping(instance, *swapchain_handle, object->host_swapchain, &object->wrapper_entry); return VK_SUCCESS; @@ -1704,6 +1713,31 @@ VkResult wine_vkQueuePresentKHR(VkQueue queue_handle, const VkPresentInfoKHR *pr res = device->funcs.p_vkQueuePresentKHR(queue->host_queue, &present_info_host); + for (i = 0; i < present_info->swapchainCount; i++) + { + struct wine_swapchain *swapchain = wine_swapchain_from_handle(present_info->pSwapchains[i]); + VkResult swapchain_res = present_info->pResults ? present_info->pResults[i] : res; + struct wine_surface *surface = swapchain->surface; + RECT client_rect; + + if (swapchain_res < VK_SUCCESS) continue; + if (!NtUserGetClientRect(surface->hwnd, &client_rect)) + { + WARN("Swapchain window %p is invalid, returning VK_ERROR_OUT_OF_DATE_KHR\n", surface->hwnd); + if (present_info->pResults) present_info->pResults[i] = VK_ERROR_OUT_OF_DATE_KHR; + if (res >= VK_SUCCESS) res = VK_ERROR_OUT_OF_DATE_KHR; + } + else if (swapchain_res != VK_SUCCESS) + WARN("Present returned status %d for swapchain %p\n", swapchain_res, swapchain); + else if (!extents_equals(&swapchain->extents, &client_rect)) + { + WARN("Swapchain size %dx%d does not match client rect %s, returning VK_SUBOPTIMAL_KHR\n", + swapchain->extents.width, swapchain->extents.height, wine_dbgstr_rect(&client_rect)); + if (present_info->pResults) present_info->pResults[i] = VK_SUBOPTIMAL_KHR; + if (res == VK_SUCCESS) res = VK_SUBOPTIMAL_KHR; + } + } + if (swapchains != swapchains_buffer) free(swapchains); if (TRACE_ON(fps)) diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index f5109aa6377..5e66a6c9670 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -253,7 +253,9 @@ static inline VkSurfaceKHR wine_surface_to_handle(struct wine_surface *surface) struct wine_swapchain { + struct wine_surface *surface; /* parent */ VkSwapchainKHR host_swapchain; + VkExtent2D extents; struct wrapper_entry wrapper_entry; };