Vulkan:调整窗口大小后重新创建交换链时出现图像错误

问题描述

所以我试图通过重新创建交换链及其图像视图以及所有这些来处理窗口大小调整。这是我正在使用的方法

void VxRenderer::recreateSwapchain() {
    device.waitIdle();

    for (uint32_t i = 0; i < swapchainImageCount; ++i) {
        vkDestroyFramebuffer(device,framebuffers[i],nullptr);
        vkDestroyImageView(device,swapchainImageViews[i],nullptr);
    }

    vkResetCommandPool(device,commandPool,0);
    vkDestroyPipeline(device,pipeline,nullptr);
    vkDestroySwapchainKHR(device,swapchain,nullptr);

    createSwapchain();
    getSwapchainImages();
    createSwapchainImageViews();
    createFramebuffers();
    createGraphicsPipeline();
    recordCommandBuffers();
}

问题是有时我在调整大小时遇到​​这个错误

Validation Error: [ VUID-VkPresentInfoKHR-pImageIndices-01296 ] Object 0: handle = 0x1d7260c6cc8,type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0xc7aabc16 | vkQueuePresentKHR(): pSwapchains[0] images
passed to present must be in layout VK_IMAGE_LAYOUT_PRESENT_SRC_KHR or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
but is in VK_IMAGE_LAYOUT_UNDEFINED. The Vulkan spec states: Each element of pImageIndices must be the
index of a presentable image acquired from the swapchain specified by the corresponding element of the
pSwapchains array,and the presented image subresource must be in the VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
layout at the time the operation is executed on a VkDevice
(https://github.com/KhronosGroup/Vulkan-Docs/search?q=)VUID-VkPresentInfoKHR-pImageIndices-01296)

它说问题来自pImageIndices结构中VkPresentInfoKHR中的元素,我写成:

uint32_t imageIndex;
VkResult result =
        vkAcquireNextimageKHR(device,UINT64_MAX,imageAcquiredSemaphores[currentimage],VK_NULL_HANDLE,&imageIndex);

if (result == VK_ERROR_OUT_OF_DATE_KHR) {
    recreateSwapchain();
    return;
}

...

VkPresentInfoKHR presentInfo;
presentInfo.sType              = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pNext              = nullptr;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores    = &renderFinishedSemaphores[currentimage];
presentInfo.swapchainCount     = 1;
presentInfo.pSwapchains        = &swapchain;
presentInfo.pImageIndices      = &imageIndex;
presentInfo.pResults           = nullptr;

解决方法

您需要将您的图像从未定义的布局转换为可呈现的图像格式,具体取决于您使用它的具体操作。例如,如果您将其用作着色器中的纹理,则它需要位于 SHADER_READ_ONLY_OPTIMAL 布局中。

您可以通过多种方式执行此操作,其中之一是您可以 image memory barrier 到临时队列的 submit。并且您绝对需要在重新创建交换链后执行此操作,因为您的整个上下文都因窗口大小调整操作而无效。