等待围栏,但验证警告 "commandBuffer haven't completed"

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

我从 Vulkan 着手,试图创建一个最小的渲染器来玩。 一切似乎都工作正常,尽管我在记录命令缓冲区或销毁它们时遇到验证错误:

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...

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

使用VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT标志创建命令缓冲池,我的渲染函数如下:

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");
    }
}

我显然有错误或遗漏了什么,但我不知道是什么。 围观还不够吗?我是不是提交错了围栏?

您的栅栏由 _currentFrameIndex 索引,而您的命令缓冲区由 swapchainImageIndex 索引。因此,您等待的栅栏可能并不意味着给定的 cmdbuff 已完成。