等待围栏,但验证警告 "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 已完成。
我从 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 已完成。