Vulkan Fence 已被另一个提交使用
Vulkan Fence already in use by another submission
我正在尝试使用 Vulkan 和 C++ 创建游戏。我已经到了使用多个带线程的命令缓冲区的部分 - 或者我想如果我做对了。
现在,我遇到了栅栏问题。控制台-我添加了一个验证层-说 "Fence 0x21 is already in use by another submission."
其他功能我没用过fence
下面的代码是绘制函数。我在循环中调用这个函数。
update_ubo (); // this function just writes uniform data on the uniform buffer in the local device.
uint32_t image_index = 0;
VkResult result = vkAcquireNextImageKHR (device, swapchain, numeric_limits <uint64_t>::max (), semaphore_image_avail, fence, &image_index);
// I hope I'm using multithreading correctly.
// all command buffers recorded in record_commandbuffers function are secondary command buffers.
#pragma omp parallel for num_threads(thread::hardware_concurrency ())
for (int64_t i = 0 ; i < (int64_t) vkthreads.size () ; i ++)
record_commandbuffers (vkthreads [i], framebuffers [image_index]);
VkCommandBufferBeginInfo cmdbuf_info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
nullptr,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
nullptr
};
VkRenderPassBeginInfo renderpass_begin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
nullptr,
renderpass,
framebuffers [image_index],
{
{ 0, 0 },
swapchain_extent
},
1,
&clear_value
};
vkBeginCommandBuffer (pcmdbuf, &cmdbuf_info);
vkCmdBeginRenderPass (pcmdbuf, &renderpass_begin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
for (size_t i = 0 ; i < vkthreads.size () ; i ++)
vkCmdExecuteCommands (pcmdbuf, (uint32_t) vkthreads [i].cmdbufs.size (), vkthreads [i].cmdbufs.data ());
vkCmdEndRenderPass (pcmdbuf);
vkEndCommandBuffer (pcmdbuf);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
window_changed ();
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
throw exception ("Could not acquire next images.");
VkPipelineStageFlags pipeline_flags [] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
VkSubmitInfo submit_info = {
VK_STRUCTURE_TYPE_SUBMIT_INFO,
nullptr,
1,
&semaphore_image_avail,
pipeline_flags,
1,
&pcmdbuf,
1,
&semaphore_render_finished
};
if (vkQueueSubmit (graphics_queue, 1, &submit_info, fence))
throw exception ("Could not submit information into the graphics queue.");
while (vkWaitForFences (device, 1, &fence, VK_TRUE, (uint64_t)100000000) == VK_TIMEOUT)
;
vkResetFences (device, 1, &fence);
VkSwapchainKHR swapchains [] = { swapchain };
VkPresentInfoKHR present_info = {
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
nullptr,
1,
&semaphore_render_finished,
1,
swapchains,
&image_index,
nullptr
};
result = vkQueuePresentKHR (present_queue, &present_info);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
window_changed ();
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
throw exception ("Could not presnet the queue.");
P.S。当我添加多线程时,FPS 显着下降(2000 fps 到 210 fps,在调试版本中),并且 CPU 使用率显着上升,这是预期的。我应该关心 FPS 吗?
您将同一个栅栏传递给 AcquireNextImage 和 QueueSubmit,而无需在两者之间等待。您只需要将它传递给 QueueSubmit,因为信号量会处理任何需要的同步。只需将 VK_NULL_HANDLE 传递给 acquireNexImage。
由于线程开销而支付每帧 5 毫秒的巨大成本似乎有点陡峭我预计由于调度程序需要一两毫秒,尽管这取决于您实际上是如何进行多线程处理的。但只要 60 fps 下每帧的总时间保持在 16 毫秒以下,就没什么大不了的。
我正在尝试使用 Vulkan 和 C++ 创建游戏。我已经到了使用多个带线程的命令缓冲区的部分 - 或者我想如果我做对了。
现在,我遇到了栅栏问题。控制台-我添加了一个验证层-说 "Fence 0x21 is already in use by another submission."
其他功能我没用过fence
下面的代码是绘制函数。我在循环中调用这个函数。
update_ubo (); // this function just writes uniform data on the uniform buffer in the local device.
uint32_t image_index = 0;
VkResult result = vkAcquireNextImageKHR (device, swapchain, numeric_limits <uint64_t>::max (), semaphore_image_avail, fence, &image_index);
// I hope I'm using multithreading correctly.
// all command buffers recorded in record_commandbuffers function are secondary command buffers.
#pragma omp parallel for num_threads(thread::hardware_concurrency ())
for (int64_t i = 0 ; i < (int64_t) vkthreads.size () ; i ++)
record_commandbuffers (vkthreads [i], framebuffers [image_index]);
VkCommandBufferBeginInfo cmdbuf_info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
nullptr,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
nullptr
};
VkRenderPassBeginInfo renderpass_begin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
nullptr,
renderpass,
framebuffers [image_index],
{
{ 0, 0 },
swapchain_extent
},
1,
&clear_value
};
vkBeginCommandBuffer (pcmdbuf, &cmdbuf_info);
vkCmdBeginRenderPass (pcmdbuf, &renderpass_begin, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
for (size_t i = 0 ; i < vkthreads.size () ; i ++)
vkCmdExecuteCommands (pcmdbuf, (uint32_t) vkthreads [i].cmdbufs.size (), vkthreads [i].cmdbufs.data ());
vkCmdEndRenderPass (pcmdbuf);
vkEndCommandBuffer (pcmdbuf);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
window_changed ();
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
throw exception ("Could not acquire next images.");
VkPipelineStageFlags pipeline_flags [] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
VkSubmitInfo submit_info = {
VK_STRUCTURE_TYPE_SUBMIT_INFO,
nullptr,
1,
&semaphore_image_avail,
pipeline_flags,
1,
&pcmdbuf,
1,
&semaphore_render_finished
};
if (vkQueueSubmit (graphics_queue, 1, &submit_info, fence))
throw exception ("Could not submit information into the graphics queue.");
while (vkWaitForFences (device, 1, &fence, VK_TRUE, (uint64_t)100000000) == VK_TIMEOUT)
;
vkResetFences (device, 1, &fence);
VkSwapchainKHR swapchains [] = { swapchain };
VkPresentInfoKHR present_info = {
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
nullptr,
1,
&semaphore_render_finished,
1,
swapchains,
&image_index,
nullptr
};
result = vkQueuePresentKHR (present_queue, &present_info);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
window_changed ();
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
throw exception ("Could not presnet the queue.");
P.S。当我添加多线程时,FPS 显着下降(2000 fps 到 210 fps,在调试版本中),并且 CPU 使用率显着上升,这是预期的。我应该关心 FPS 吗?
您将同一个栅栏传递给 AcquireNextImage 和 QueueSubmit,而无需在两者之间等待。您只需要将它传递给 QueueSubmit,因为信号量会处理任何需要的同步。只需将 VK_NULL_HANDLE 传递给 acquireNexImage。
由于线程开销而支付每帧 5 毫秒的巨大成本似乎有点陡峭我预计由于调度程序需要一两毫秒,尽管这取决于您实际上是如何进行多线程处理的。但只要 60 fps 下每帧的总时间保持在 16 毫秒以下,就没什么大不了的。