#Problem with double/triple buffering

16 messages · Page 1 of 1 (latest)

misty swan
#

I want to use a max frames in flight variable to control whether it uses double or triple buffering and I don't know when to use it instead of pSwapchainImageCount from vkGetSwapchainImagesKHR, if I replace it with the maximum frames in flight for the maximum frame index then it the triangle flickers every 3 frames and it says Validation Error: [ VUID-VkPresentInfoKHR-pImageIndices-01296 ] Object 0: handle = 0x6190000645d0, 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) (swapchainImageCount was 3 and maximum frames in flight was 2). Currently I'm using pSwapchainImageCount for the amount of command buffers, semaphores (x2), fences, the maximum frame index, recording commands to each command buffer, the amount of VkImageView pViews, and the amount of frame buffers.

silent hinge
#
  • double/triple buffering is controlled by the present mode: e.g. FIFO for double buffering, and MAILBOX for triple buffering
  • frames-in-flight is independent of double/triple buffering, and is controlled by you: it is the number of command pools/buffers, fences, etc

the validation error you posted usually means that you mixed the above two up

misty swan
#

why does setting it to 2 cause that error

silent hinge
#

consider for instance this piece of code:

appContext.commandBuffers.resize(appContext.swapchainImageCount);
    appContext.semaphoresImageAvailable.resize(appContext.swapchainImageCount);
    appContext.semaphoresRenderFinished.resize(appContext.swapchainImageCount);
    appContext.fencesInFlight.resize(appContext.swapchainImageCount);

You are creating swapchainImageCount instances of command buffer, semaphores, and fences, whereas you should be creating framesInFlight of each instead. It looks like you are pre-recording your command buffers and using your swapchainImageIndex as both swapchainImageIndex as frameInFlightIndex

#

So your code will fail miserably if the presentation engine doesn't give you the swapchain image you expect in vkAcquireSwapchainImageKHR

misty swan
#

if i replace swapchainImageCount with framesInFlight and use FIFO then it still flickers and says that error

silent hinge
#

Your code has more than 1 issue, so validation will keep yelling until all of them are fixed. First of all, I would recommend to not prerecord all command buffers. But, if you insist, you will probably need 1 prerecording per swapchain image index per frame in flight, instead of just 1 per swapchain image index.

misty swan
#

why is prerecording bad

silent hinge
#

Because you can only do it under very specific circumstances, and you need to put in considerable effort to determine when you should rerecord them (e.g. after swapchain resize). Once you add more logic, it will only become more and more complex. (In your simple example, you already need to have 1 prerecord per swapchain image per frame in flight, and you barely got started.)

There is 1 exception, which is when you have GPU driven rendering. In this case, it's not very complex to prerecord, but you don't gain anything because recording command buffers in GPU driven rendering is vey cheap.

misty swan
#

if i recreate it every frame then it still says the error

silent hinge
#

Rerecording every frame is just step 1 of the solution. The next step is making sure that you are using the swapchain image indices and frame-in-flight indices right. Can you show the new frame loop?

misty swan
#
VK_CHECK(vkWaitForFences(appContext.logicalDevice, 1, &appContext.fencesInFlight[frameIndex], VK_TRUE, -1));
VK_CHECK(vkResetFences(appContext.logicalDevice, 1, &appContext.fencesInFlight[frameIndex]));

VkResult result = vkAcquireNextImageKHR(appContext.logicalDevice, appContext.swapchain, -1, appContext.semaphoresImageAvailable[frameIndex], nullptr, &imageIndex);
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
    std::cerr << "Vulkan result: " << result << '\n'; 
}

VK_CHECK(vkResetCommandBuffer(appContext.commandBuffers[frameIndex],  0));
VK_CHECK(vkBeginCommandBuffer(appContext.commandBuffers[frameIndex], &commandBufferBeginInfo));
renderPassBeginInfo.framebuffer = appContext.swapchainFrameBuffers[frameIndex];
vkCmdBeginRenderPass(appContext.commandBuffers[frameIndex], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(appContext.commandBuffers[frameIndex], 0, 1, &pipelineViewport);
vkCmdSetScissor(appContext.commandBuffers[frameIndex], 0, 1, &pipelineScissor);
vkCmdBindPipeline(appContext.commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, appContext.pipeline);
vkCmdDraw(appContext.commandBuffers[frameIndex], 3, 1, 0, 0);
vkCmdEndRenderPass(appContext.commandBuffers[frameIndex]);
VK_CHECK(vkEndCommandBuffer(appContext.commandBuffers[frameIndex]));

renderSubmitInfo.pWaitSemaphores = &appContext.semaphoresImageAvailable[frameIndex];
renderSubmitInfo.pCommandBuffers = &appContext.commandBuffers[frameIndex];
renderSubmitInfo.pSignalSemaphores = &appContext.semaphoresRenderFinished[frameIndex];
VK_CHECK(vkQueueSubmit(appContext.graphicsQueue, 1, &renderSubmitInfo, appContext.fencesInFlight[frameIndex]));

renderPresentInfo.pWaitSemaphores = &appContext.semaphoresRenderFinished[frameIndex];
VK_CHECK(vkQueuePresentKHR(appContext.graphicsQueue, &renderPresentInfo));

frameIndex = (frameIndex + 1) % appContext.MAX_FRAMES_IN_FLIGHT;```
silent hinge
#
renderPassBeginInfo.framebuffer = appContext.swapchainFrameBuffers[frameIndex];

this should be the swapchain image index

#

everything else looks correct to me