如何检测哪个交换链已过时?

How to detect which swapchain is out of date?

我有多个交换链,其中一个已经过时了。

if (swapchain_count) {
    VkPresentInfoKHR present_info = {
        VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
        NULL,
        0,
        NULL,
        swapchain_count,
        swapchain_array,
        swapchain_index_array,
        NULL,
    };

    vkQueuePresentKHR(queue, &present_info);
}

vkQueuePresentKHR 返回 VK_ERROR_OUT_OF_DATE_KHR

如何确定哪个交换链已过时?

If I ignore the error returned by vkQueuePresentKHR,
the next vkAcquireNextImageKHR of the swapchain in error will return VK_ERROR_OUT_OF_DATE_KHR.
And the following log is generated:

VUID-vkAcquireNextImageKHR-swapchain-01802(ERROR / SPEC): msgNum: 1050126472 - Validation Error:
[ VUID-vkAcquireNextImageKHR-swapchain-01802 ] Object 0:
handle = 0x948acd0000000008, type = VK_OBJECT_TYPE_SWAPCHAIN_KHR;
| MessageID = 0x3e97a888 | vkAcquireNextImageKHR:
Application has already previously acquired 1 image from swapchain.
Only 1 is available to be acquired using a timeout of UINT64_MAX
(given the swapchain has 2, and VkSurfaceCapabilitiesKHR::minImageCount is 2).
The Vulkan spec states: If the number of currently acquired images is greater than the difference between
the number of images in swapchain and the value of VkSurfaceCapabilitiesKHR::minImageCount as returned
by a call to vkGetPhysicalDeviceSurfaceCapabilities2KHR with the surface used to create swapchain,
timeout must not be UINT64_MAX

我不认为有一种方法可以使用 vkQueuePresentKHR 找到哪个交换链没有数据,但是你怎么能做这样的事情,
如果 vkQueuePresentKHR 的结果是 VK_ERROR_OUT_OF_DATE_KHR,您可以使用 vkGetSwapchainStatusKHR 检查它们中的每一个,并检查需要重新创建哪个交换链。

是的,这可能会很慢,因为您必须遍历整个交换链数组才能找到那个交换链。

另一种方式是规范规定:Link

VK_ERROR_OUT_OF_DATE_KHR A surface has changed in such a way that it is no longer compatible with the swapchain, and further presentation requests using the swapchain will fail. Applications must query the new surface properties and recreate their swapchain if they wish to continue presenting to the surface.

这意味着您可以跟踪哪个表面 (window) 已更改并重新创建其依赖项(交换链,可能是物理设备和逻辑设备)并在它抛出该错误之前更新数组。

过时的交换链是您传递给获取调用的交换链。交换链中的哪个 image 已过时很简单:全部。当交换链过期时,该链中的所有图像都无法获取或呈现。

当交换链过期时,您必须为表面创建一个新的交换链,然后使用它。

VkPresentInfoKHR结构有一个pResults字段:如果非NULL,pResults中的每个条目将被设置为VkResult,用于呈现与中相同索引对应的交换链pSwapchains.

// Provided by VK_KHR_swapchain
typedef struct VkPresentInfoKHR {
    VkStructureType          sType;
    const void*              pNext;
    uint32_t                 waitSemaphoreCount;
    const VkSemaphore*       pWaitSemaphores;
    uint32_t                 swapchainCount;
    const VkSwapchainKHR*    pSwapchains;
    const uint32_t*          pImageIndices;
    VkResult*                pResults;
} VkPresentInfoKHR;

在代码中,您将 pResults 设置为 NULL

尝试将 pResults 设置为 VkResult 的数组。

if (swapchain_count) {
    VkResult swapchain_result_array = new VkResult[swapchain_count];

    VkPresentInfoKHR present_info = {
        VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
        NULL,
        0,
        NULL,
        swapchain_count,
        swapchain_array,
        swapchain_index_array,
        swapchain_result_array, // <-- the result array goes here
    };

    vkQueuePresentKHR(queue, &present_info);

    // handle the swapchain_result_array here
}