Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why vkWaitForFences must be called before vkAcquireNextImageKHR #387

Open
InchChou opened this issue Jul 15, 2024 · 1 comment
Open

Why vkWaitForFences must be called before vkAcquireNextImageKHR #387

InchChou opened this issue Jul 15, 2024 · 1 comment

Comments

@InchChou
Copy link

Hello everyone, I was reading the Rendering and presentation and Frames in flight chapter, I have some questions about this code.

        vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX);
        vkResetFences(device, 1, &inFlightFence);

        uint32_t imageIndex;
        vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);

It makes me confused.

At the start of the frame, we want to wait until the previous frame has finished, so that the command buffer and semaphores are
available to use. To do that, we call vkWaitForFences:

As it said, we need to wait command buffers are available to use. But what does “semaphores are available to use" mean? I've checked the spec of Vulkan, it's said that binary semaphore has only two states: signaled and unsignaled. When it's signeled, it's available to unsignal, and vise versa.

After operation B begins executing, semaphore S is automatically reset back to being unsignaled, allowing it to be used again.

As quoted above, when the commands in presentQueue begin executing, imageAvailableSemaphore is automatically reset back to being unsignaled, so it's available for vkAcquireNextImageKHR in my opinion. So the only purpose of vkWaitForFences is to wait for the command buffer to be available.

According to this, vkWaitForFences can be placed anywhere before recordCommandBuffer. But that's not the case.

In both sections of the code, I tried putting vkWaitForFences after vkAcquireNextImageKHR and before recordCommandBuffer:

        uint32_t imageIndex;
        vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
        vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
        vkResetFences(device, 1, &inFlightFences[currentFrame]);
        vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
        recordCommandBuffer(commandBuffers[currentFrame], imageIndex);

When I run it, the validation layer reports an error:

validation layer: Validation Error: [ VUID-vkAcquireNextImageKHR-semaphore-01779 ] Object 0: handle = 0xd175b40000000013, type = VK_OBJECT_TYPE_SEMAPHORE; | MessageID = 0x5717e75b | vkAcquireNextImageKHR():  Semaphore must not have any pending operations. The Vulkan spec states: If semaphore is not VK_NULL_HANDLE it must not have any uncompleted signal or wait operations pending (https://vulkan.lunarg.com/doc/view/1.3.275.0/windows/1.3-extensions/vkspec.html#VUID-vkAcquireNextImageKHR-semaphore-01779)

Can someone help me with this question? Is there something I am not understanding correctly?

@charles-lunarg
Copy link
Contributor

vkAcquireNextImageKHR is different than vkQueueSubmit. With vkQueueSubmit:

VUID-vkQueueSubmit-pSignalSemaphores-00067
Each binary semaphore element of the pSignalSemaphores member of any element of pSubmits must be unsignaled when the semaphore signal operation it defines is executed on the device

That means that you can call vkQueueSubmit when the signal semaphores are "currently" signalled, just so long as they become unsignalled by the time this vkQueueSubmit should signal them.

Whereas with vkAcquireNextImageKHR:
If semaphore is not VK_NULL_HANDLE, it must be unsignaled

So when you call vkAcquireNextImageKHR, the semaphore must be unsignalled no matter what, and just about the only way to do that is to wait for the fence of the frame that used that semaphore as a wait semaphore to complete (ie, the previous frame's submission).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants