From fafe4813650613cf5bc14eef6190efb93178f654 Mon Sep 17 00:00:00 2001 From: ubuntu1804 Date: Mon, 10 Nov 2025 22:31:35 +0800 Subject: [PATCH] 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. --- src/vulkanrenderer.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/vulkanrenderer.cpp b/src/vulkanrenderer.cpp index 44a2b3d..b4b6257 100644 --- a/src/vulkanrenderer.cpp +++ b/src/vulkanrenderer.cpp @@ -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);