I'm currently working on a Vulkan project that uses compute shaders instead of the traditional graphics pipeline to render images.
I've been loosely following https://vulkan-tutorial.com/Drawing_a_triangle for guidance regarding the swapchain. My "drawFrame" equivalent follows the exact same steps, just with different commands in the command buffers.
I'm using a small 2-image swapchain of which images are acquired and passed to a descriptor set. A compute shader then renders to that image, the layout is transitioned and I call vkQueuePresent.
My approach works absolutely fine after startup - images are rendered as expected.
The problem occurs once I try resizing my GLFW window. This operation requires me to rebuild my swapchain as discussed in the tutorial above.
After resizing, vkAcquireNextImageKHR only returns an image index of 0, never 1.
This results in my frames dropping to 1 fps, as my timeout for the rendering fence is 1 second.
IF i then manually set the swapchain image index to 1, if the previous and next index are both 0, it renders absolutely fine again!
BUT, this does return an expected validation error regarding the VkImage used:
VUID-VkPresentInfoKHR-pImageIndices-01296(ERROR / SPEC): msgNum: -945112042 - Validation Error: [ VUID-VkPresentInfoKHR-pImageIndices-01296 ] Object 0: handle = 0xf22ab70000004831, type = VK_OBJECT_TYPE_SWAPCHAIN_KHR; | MessageID = 0xc7aabc16 |
vkQueuePresentKHR: pSwapchains[0] image at index 1 was not acquired from the swapchain.
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)
Now, obviously simply overwriting the image index provided by vkAcquireNextImageKHR is not supposed to be done.
So does anyone here have a clue why vkAcquireNextImageKHR could be only returning image index 0 after recreating the swapchain?
The size remains 2 after resizing, I checked that.
This is what i'm doing to acquire the next swapchain image right now...
uint32_t prev = *get_swapchain_image_index();
VkResult result = vkAcquireNextImageKHR(
*get_hardware(),
*get_swapchain(),
1 SECOND,
*get_gpu_image_available( (int) swapchain_frame ),
VK_NULL_HANDLE,
get_swapchain_image_index()
);
if (prev == *get_swapchain_image_index()) set_swapchain_image_index(1);
if (result == VK_ERROR_OUT_OF_DATE_KHR) recreate_swapchain();
else throw_error(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR,
"\n"
"ERROR: Acquisition of current frame's swapchain image failed.\n"
" The returned result is '" + get_result_string(result) + "'."
);
Just for clarifications, although the naming should be self-explanatory:
get_swapchain_image_index is a simple getter / setter for a field in a struct in a different file.
get_hardware returns the VkDevice used by the application
get_swapchain returns the VkSwapchainKHR used by the application
get_gpu_image_available returns a semaphore signalled when this specific swapchain image is available