Asaf Sitner
Asaf Sitner

Reputation: 629

Waiting on fence, but validation warns about "commandBuffer haven't completed"

I'm starting out with Vulkan, trying to create a minimal renderer to play around with. Everything seems to work fine, though I'm getting a validation error when recording command buffers, or destroying them:

VUID-vkBeginCommandBuffer-commandBuffer-00049(ERROR / SPEC): ...Calling vkBeginCommandBuffer() on active VkCommandBuffer 0x1b5ad3f2020[] before it has completed. You must check command buffer fence before this call...

and

VUID-vkDestroyCommandPool-commandPool-00041(ERROR / SPEC): ...Attempt to destroy command pool with VkCommandBuffer 0x1b5ad3fb1e0[] which is in use...

The command buffer pool is created with the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT flag, and my render function is as follows:

void VulkanRenderer::Draw(std::vector<Mesh*>* meshes)
{
    static const uint64_t wait_timeout = std::numeric_limits<uint64_t>::max();

    // wait for GPU
    vkWaitForFences(_logicalDevice, 1, &_drawFences[_currentFrameIndex], VK_TRUE, wait_timeout);
    vkResetFences(_logicalDevice, 1, &_drawFences[_currentFrameIndex]);

    uint32_t swapchainImageIndex;
    const VkResult result = vkAcquireNextImageKHR(_logicalDevice, _swapchain, wait_timeout, _imageAvailableSemaphores[_currentFrameIndex], VK_NULL_HANDLE, &swapchainImageIndex);
    if (result != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to acquire next swapchain image");
    }

    RecordCommands(swapchainImageIndex, meshes);
    SubmitToGraphicsQueue(swapchainImageIndex);
    PresentGraphicsQueue(swapchainImageIndex);

    // advance to next frame
    _currentFrameIndex = (_currentFrameIndex + 1) % MAX_FRAME_DRAWS;
}

void VulkanRenderer::RecordCommands(const uint32_t swapchainImageIndex, std::vector<Mesh*>* meshes)
{
    VkCommandBuffer currentBuffer = _graphicsCommandBuffers[swapchainImageIndex];

    // define command buffer recording start
    VkCommandBufferBeginInfo commandBufferBeginInfo = {};
    commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    commandBufferBeginInfo.pNext = nullptr;
    commandBufferBeginInfo.pInheritanceInfo = nullptr;

    // start recording commands into command buffer
    VkResult result = vkBeginCommandBuffer(currentBuffer, &commandBufferBeginInfo);
    if (result != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to begin command buffer recording");
    }

    // commands recorded here...

    // stop recording commands into command buffer
    result = vkEndCommandBuffer(currentBuffer);
    if (result != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to end command buffer recording");
    }
}

void VulkanRenderer::SubmitToGraphicsQueue(const uint32_t swapchainImageIndex)
{
    // define semaphore wait stages
    std::vector<VkPipelineStageFlags> semaphoreWaits = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };

    // define graphics queue submission
    VkSubmitInfo graphicsQueueSubmitInfo = {};
    graphicsQueueSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    graphicsQueueSubmitInfo.pNext = nullptr;
    graphicsQueueSubmitInfo.waitSemaphoreCount = 1;
    graphicsQueueSubmitInfo.pWaitSemaphores = &_imageAvailableSemaphores[_currentFrameIndex];
    graphicsQueueSubmitInfo.pWaitDstStageMask = semaphoreWaits.data();
    graphicsQueueSubmitInfo.commandBufferCount = 1;
    graphicsQueueSubmitInfo.pCommandBuffers = &_graphicsCommandBuffers[swapchainImageIndex];
    graphicsQueueSubmitInfo.signalSemaphoreCount = 1;
    graphicsQueueSubmitInfo.pSignalSemaphores = &_renderFinishedSemaphores[_currentFrameIndex];

    // submit graphics queue
    const VkResult result = vkQueueSubmit(_graphicsQueue, 1, &graphicsQueueSubmitInfo, _drawFences[_currentFrameIndex]);
    if (result != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to submit graphics queue");
    }
}

void VulkanRenderer::PresentGraphicsQueue(uint32_t swapchainImageIndex)
{
    // define graphics queue presentation
    VkPresentInfoKHR graphicsQueuePresentInfo = {};
    graphicsQueuePresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    graphicsQueuePresentInfo.pNext = nullptr;
    graphicsQueuePresentInfo.waitSemaphoreCount = 1;
    graphicsQueuePresentInfo.pWaitSemaphores = &_renderFinishedSemaphores[_currentFrameIndex];
    graphicsQueuePresentInfo.swapchainCount = 1;
    graphicsQueuePresentInfo.pSwapchains = &_swapchain;
    graphicsQueuePresentInfo.pImageIndices = &swapchainImageIndex;
    graphicsQueuePresentInfo.pResults = nullptr;

    // present graphics queue
    const VkResult result = vkQueuePresentKHR(_presentationQueue, &graphicsQueuePresentInfo);
    if (result != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to present graphics queue");
    }
}

I clearly have a mistake or am missing something there, but I can't figure out what. Is it not enough to wait on the fence? Am I submitting the wrong fence?

Upvotes: 1

Views: 1327

Answers (1)

krOoze
krOoze

Reputation: 13276

Your fences are indexed by _currentFrameIndex, while your command buffers are indexed by swapchainImageIndex. Therefore the fence you wait on potentially does not imply the given cmdbuff is completed.

Upvotes: 2

Related Questions