Sync device and add fence timeout for buffer copy

Wait for device idle before starting copy to avoid queue contention. Use
a 1s fence wait and handle VK_TIMEOUT with cleanup and logging.
This commit is contained in:
ubuntu1804 2025-11-10 22:35:51 +08:00
parent fafe481365
commit 90d770dd85
1 changed files with 16 additions and 3 deletions

View File

@ -1864,6 +1864,14 @@ bool VulkanRenderer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint64_t
return false;
}
// Wait for device to be idle to avoid queue contention
// This ensures no other operations are using the queue
VkResult idleResult = vkDeviceWaitIdle(m_device);
if (idleResult != VK_SUCCESS) {
logError("Failed to wait for device idle before buffer copy");
return false;
}
// Create a one-time command pool if not exists
if (m_transferCommandPool == VK_NULL_HANDLE) {
VkCommandPoolCreateInfo poolInfo = {};
@ -1945,9 +1953,14 @@ bool VulkanRenderer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint64_t
return false;
}
// Wait for the fence instead of the entire queue
result = vkWaitForFences(m_device, 1, &fence, VK_TRUE, UINT64_MAX);
if (result != VK_SUCCESS) {
// Wait for the fence with a reasonable timeout (1 second)
result = vkWaitForFences(m_device, 1, &fence, VK_TRUE, 1000000000); // 1 second in nanoseconds
if (result == VK_TIMEOUT) {
logError("Timeout waiting for fence after copy - queue may be busy");
vkDestroyFence(m_device, fence, nullptr);
vkFreeCommandBuffers(m_device, m_transferCommandPool, 1, &commandBuffer);
return false;
} else if (result != VK_SUCCESS) {
logError("Failed to wait for fence after copy");
vkDestroyFence(m_device, fence, nullptr);
vkFreeCommandBuffers(m_device, m_transferCommandPool, 1, &commandBuffer);