From 030f3430ee79ad8a8f0df0bc075e8a589f1cf1f4 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 20 Nov 2024 13:02:19 +0000 Subject: [PATCH] Workaround AcquireNextImage being awful * Apparently the spec allows drivers to do extremely stupid things with swapchain images and return them even when it's not valid for you to use them yet because last frame's work to the image is still ongoing, which leads to a validation warning about using a semaphore when it might technically still be in flight. * To get around this because AcquireNextImage doesn't actually block until an image is ready inspite of having a timeout and being expected to return a usable image it doesn't, we use a manual fence to do what AcquireNextImage should be doing. --- util/test/demos/vk/vk_test.cpp | 19 ++++++++++++++++++- util/test/demos/vk/vk_test.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/util/test/demos/vk/vk_test.cpp b/util/test/demos/vk/vk_test.cpp index e8e910b10..0da4eaffb 100644 --- a/util/test/demos/vk/vk_test.cpp +++ b/util/test/demos/vk/vk_test.cpp @@ -1033,6 +1033,12 @@ void VulkanGraphicsTest::setName(VkSemaphore obj, const std::string &name) setName(VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)obj, name); } +template <> +void VulkanGraphicsTest::setName(VkFence obj, const std::string &name) +{ + setName(VK_OBJECT_TYPE_FENCE, (uint64_t)obj, name); +} + void VulkanGraphicsTest::setName(VkObjectType objType, uint64_t obj, const std::string &name) { if(vkSetDebugUtilsObjectNameEXT) @@ -1409,6 +1415,12 @@ VulkanWindow::VulkanWindow(VulkanGraphicsTest *test, GraphicsWindow *win) test->setName(renderStartSemaphore[i], title + " renderStartSemaphore" + std::to_string(i)); test->setName(renderEndSemaphore[i], title + " renderEndSemaphore" + std::to_string(i)); + + // create signalled so the first wait works + CHECK_VKR(vkCreateFence(m_Test->device, vkh::FenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT), + NULL, &imageFences[i])); + + test->setName(imageFences[i], title + " fence" + std::to_string(i)); } #if defined(WIN32) @@ -1467,6 +1479,7 @@ VulkanWindow::~VulkanWindow() { vkDestroySemaphore(m_Test->device, renderStartSemaphore[i], NULL); vkDestroySemaphore(m_Test->device, renderEndSemaphore[i], NULL); + vkDestroyFence(m_Test->device, imageFences[i], NULL); } if(surface) @@ -1597,8 +1610,12 @@ void VulkanWindow::Acquire() semIdx = (semIdx + 1) % ARRAY_COUNT(renderStartSemaphore); + // acquire next image stupidly does not properly block, do a manual block + vkWaitForFences(m_Test->device, 1, &imageFences[semIdx], VK_FALSE, UINT64_MAX); + vkResetFences(m_Test->device, 1, &imageFences[semIdx]); + VkResult vkr = vkAcquireNextImageKHR(m_Test->device, swap, UINT64_MAX, - renderStartSemaphore[semIdx], VK_NULL_HANDLE, &imgIndex); + renderStartSemaphore[semIdx], imageFences[semIdx], &imgIndex); if(vkr == VK_SUBOPTIMAL_KHR || vkr == VK_ERROR_OUT_OF_DATE_KHR) { diff --git a/util/test/demos/vk/vk_test.h b/util/test/demos/vk/vk_test.h index 0d6ed857b..4d7e4fe4e 100644 --- a/util/test/demos/vk/vk_test.h +++ b/util/test/demos/vk/vk_test.h @@ -184,6 +184,7 @@ private: uint32_t semIdx = 0; VkSemaphore renderStartSemaphore[4] = {}; VkSemaphore renderEndSemaphore[4] = {}; + VkFence imageFences[4] = {}; std::vector fbs; GraphicsWindow *m_Win;