Use fence to wait for buffer copy

Create a VkFence for the copy command, submit with that fence, wait with
vkWaitForFences instead of vkQueueWaitIdle, and destroy the fence after
completion. Ensure fence is destroyed and the command buffer is freed on
error paths.
This commit is contained in:
ubuntu1804 2025-11-10 22:31:35 +08:00
parent 098b00057d
commit fafe481365
1 changed files with 24 additions and 3 deletions

View File

@ -1918,24 +1918,45 @@ bool VulkanRenderer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint64_t
return false;
}
// Create a fence for synchronization
VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = 0;
VkFence fence;
result = vkCreateFence(m_device, &fenceInfo, nullptr, &fence);
if (result != VK_SUCCESS) {
logError("Failed to create fence for buffer copy");
vkFreeCommandBuffers(m_device, m_transferCommandPool, 1, &commandBuffer);
return false;
}
// Submit and wait
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
result = vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
result = vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, fence);
if (result != VK_SUCCESS) {
logError("Failed to submit copy command");
vkDestroyFence(m_device, fence, nullptr);
vkFreeCommandBuffers(m_device, m_transferCommandPool, 1, &commandBuffer);
return false;
}
result = vkQueueWaitIdle(m_graphicsQueue);
// Wait for the fence instead of the entire queue
result = vkWaitForFences(m_device, 1, &fence, VK_TRUE, UINT64_MAX);
if (result != VK_SUCCESS) {
logError("Failed to wait for queue idle after copy");
logError("Failed to wait for fence after copy");
vkDestroyFence(m_device, fence, nullptr);
vkFreeCommandBuffers(m_device, m_transferCommandPool, 1, &commandBuffer);
return false;
}
// Cleanup fence
vkDestroyFence(m_device, fence, nullptr);
// Free command buffer
vkFreeCommandBuffers(m_device, m_transferCommandPool, 1, &commandBuffer);