From cf8b11fc6ce5618117bb48aca108ea448438a926 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 4 Nov 2016 15:42:48 -0700 Subject: vulkan/wsi: Report the correct min/maxImageCount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the Vulkan spec 1.0.32 section 29.6 docs for vkAcquireNextImageKHR: "Let n be the total number of images in the swapchain, m be the value of VkSurfaceCapabilitiesKHR::minImageCount, and a be the number of presentable images that the application has currently acquired (i.e. images acquired with vkAcquireNextImageKHR, but not yet presented with vkQueuePresentKHR). vkAcquireNextImageKHR can always succeed if a ≤ n - m at the time vkAcquireNextImageKHR is called. vkAcquireNextImageKHR should not be called if a > n - m with a timeout of UINT64_MAX; in such a case, vkAcquireNextImageKHR may block indefinitely." With minImageCount == 2 (as it was previously, the client is allowed to acquire all but one image withoutblocking. If we really need 4 images for mailbox mode + pageflipping, then we need to request a minimum of 4 images up-front. This is a bit unfortunate because it means we will always consume 4 images. In the future, we may be able to optimize this a bit by waiting until the server starts to flip and returning OUT_OF_DATE to get the client to re-allocate with more images or something like that. Signed-off-by: Jason Ekstrand Reviewed-by: Dave Airlie Cc: "13.0" (cherry picked from commit 4fa0ca80eeeac813affcbb0129ed61f1534d8df0) --- src/vulkan/wsi/wsi_common_x11.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src/vulkan/wsi/wsi_common_x11.c') diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 2280651..de71b19 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -371,8 +371,16 @@ x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface, VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; } + /* For true mailbox mode, we need at least 4 images: + * 1) One to scan out from + * 2) One to have queued for scan-out + * 3) One to be currently held by the X server + * 4) One to render to + */ caps->minImageCount = 2; - caps->maxImageCount = 4; + /* There is no real maximum */ + caps->maxImageCount = 0; + caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; caps->maxImageArrayLayers = 1; @@ -737,16 +745,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); - int num_images = pCreateInfo->minImageCount; - - /* For true mailbox mode, we need at least 4 images: - * 1) One to scan out from - * 2) One to have queued for scan-out - * 3) One to be currently held by the Wayland compositor - * 4) One to render to - */ - if (pCreateInfo->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) - num_images = MAX2(num_images, 4); + const unsigned num_images = pCreateInfo->minImageCount; size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); chain = vk_alloc(pAllocator, size, 8, -- cgit v1.1 From a3f628ca25fc64022a27287f18e8c7fbe20c7e56 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 15 Nov 2016 21:18:50 +0000 Subject: wsi: fix VK_INCOMPLETE for vkGetSwapchainImagesKHR This fixes the x11 and wayland backends to not assert: dEQP-VK.wsi.xcb.swapchain.get_images.incomplete Reviewed-by: Jason Ekstrand Cc: "13.0" Signed-off-by: Dave Airlie (cherry picked from commit 253fa25d09b77e18f736b97da07d57be0e6c4200) --- src/vulkan/wsi/wsi_common_x11.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/vulkan/wsi/wsi_common_x11.c') diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index de71b19..73bd03c 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -498,19 +498,25 @@ x11_get_images(struct wsi_swapchain *anv_chain, uint32_t* pCount, VkImage *pSwapchainImages) { struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; + uint32_t ret_count; + VkResult result; if (pSwapchainImages == NULL) { *pCount = chain->image_count; return VK_SUCCESS; } - assert(chain->image_count <= *pCount); - for (uint32_t i = 0; i < chain->image_count; i++) - pSwapchainImages[i] = chain->images[i].image; + result = VK_SUCCESS; + ret_count = chain->image_count; + if (chain->image_count > *pCount) { + ret_count = *pCount; + result = VK_INCOMPLETE; + } - *pCount = chain->image_count; + for (uint32_t i = 0; i < ret_count; i++) + pSwapchainImages[i] = chain->images[i].image; - return VK_SUCCESS; + return result; } static VkResult -- cgit v1.1 From 28c6c8d09e6bb468bfc53a57e12e579411c30941 Mon Sep 17 00:00:00 2001 From: Eduardo Lima Mitev Date: Tue, 25 Oct 2016 10:20:12 +0200 Subject: vulkan/wsi/x11: Fix behavior of vkGetPhysicalDeviceSurfaceFormatsKHR x11_surface_get_formats() is currently asserting that the number of elements in pSurfaceFormats must be greater than or equal to the number of formats available. This is buggy because pSurfaceFormatsCount elements are later copied from the internal formats' array, so if pSurfaceFormatCount is greater, it will overflow it. On top of that, this assertion violates the spec. From the Vulkan 1.0 (revision 32, with KHR extensions), page 579 of the PDF: "If pSurfaceFormats is NULL, then the number of format pairs supported for the given surface is returned in pSurfaceFormatCount. Otherwise, pSurfaceFormatCount must point to a variable set by the user to the number of elements in the pSurfaceFormats array, and on return the variable is overwritten with the number of structures actually written to pSurfaceFormats. If the value of pSurfaceFormatCount is less than the number of format pairs supported, at most pSurfaceFormatCount structures will be written. If pSurfaceFormatCount is smaller than the number of format pairs supported for the given surface, VK_INCOMPLETE will be returned instead of VK_SUCCESS to indicate that not all the available values were returned." So, the correct behavior is: if pSurfaceFormatCount is greater than the internal number of formats, it is clamped to that many formats. But if it is lesser than that, then pSurfaceFormatCount elements are copied, and the call returns VK_INCOMPLETE. Reviewed-by: Dave Airlie (cherry picked from commit 750d8cad72a532d977df10ffbbdd1902bd06f50b) Nominated-by: Emil Velikov Squashed with commit: vulkan/wsi/x11: Smplify implementation of vkGetPhysicalDeviceSurfaceFormatsKHR This patch simplifies x11_surface_get_formats(). It is actually just a readability improvement over the patch I provided earlier this week (750d8cad72). Reviewed-by: Eric Engestrom (cherry picked from commit 129da274261b6e79f459e24428591f137bf92ed1) --- src/vulkan/wsi/wsi_common_x11.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vulkan/wsi/wsi_common_x11.c') diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 73bd03c..6b7e133 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -404,11 +404,11 @@ x11_surface_get_formats(VkIcdSurfaceBase *surface, return VK_SUCCESS; } - assert(*pSurfaceFormatCount >= ARRAY_SIZE(formats)); + *pSurfaceFormatCount = MIN2(*pSurfaceFormatCount, ARRAY_SIZE(formats)); typed_memcpy(pSurfaceFormats, formats, *pSurfaceFormatCount); - *pSurfaceFormatCount = ARRAY_SIZE(formats); - return VK_SUCCESS; + return *pSurfaceFormatCount < ARRAY_SIZE(formats) ? + VK_INCOMPLETE : VK_SUCCESS; } static VkResult -- cgit v1.1 From f7b58a378ca94cf1c2637d640ce5b9fb8f8519a6 Mon Sep 17 00:00:00 2001 From: Eduardo Lima Mitev Date: Fri, 28 Oct 2016 14:34:39 +0200 Subject: vulkan/wsi/x11: Fix behavior of vkGetPhysicalDeviceSurfacePresentModesKHR x11_surface_get_present_modes() is currently asserting that the number of elements in pPresentModeCount must be greater than or equal to the number of present modes available. This is buggy because pPresentModeCount elements are later copied from the internal modes' array, so if pPresentModeCount is greater, it will overflow it. On top of that, this assertion violates the spec. From the Vulkan 1.0 (revision 32, with KHR extensions), page 581 of the PDF: "If the value of pPresentModeCount is less than the number of presentation modes supported, at most pPresentModeCount values will be written. If pPresentModeCount is smaller than the number of presentation modes supported for the given surface, VK_INCOMPLETE will be returned instead of VK_SUCCESS to indicate that not all the available values were returned." So, the correct behavior is: if pPresentModeCount is greater than the internal number of formats, it is clamped to that many present modes. But if it is lesser than that, then pPresentModeCount elements are copied, and the call returns VK_INCOMPLETE. This fix is similar (but simpler and more readable) than the one I provided in 750d8cad72a for vkGetPhysicalDeviceSurfaceFormatsKHR, which was suffering from the same problem. Reviewed-by: Eric Engestrom (cherry picked from commit b677b99db5c48ffd1eeef538b962080ac5fd65d9) Nominated-by: Emil Velikov --- src/vulkan/wsi/wsi_common_x11.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vulkan/wsi/wsi_common_x11.c') diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 6b7e133..09718eb 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -421,11 +421,11 @@ x11_surface_get_present_modes(VkIcdSurfaceBase *surface, return VK_SUCCESS; } - assert(*pPresentModeCount >= ARRAY_SIZE(present_modes)); + *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes)); typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); - *pPresentModeCount = ARRAY_SIZE(present_modes); - return VK_SUCCESS; + return *pPresentModeCount < ARRAY_SIZE(present_modes) ? + VK_INCOMPLETE : VK_SUCCESS; } VkResult wsi_create_xcb_surface(const VkAllocationCallbacks *pAllocator, -- cgit v1.1