Vulkan Cookbook 第三章 11 将命令缓冲区提交到队列

将命令缓冲区提交到队列

译者注:示例代码点击此处

我们记录了命令缓冲区,希望利用图形硬件的能力来处理准备好的操作。接下来做什么?我们需要将准备好的工作提交到选定的列队。

做好准备

在本文中,我们将使用自定义WaitSemaphoreInfo类型的变量。它的定义如下:


struct WaitSemaphoreInfo { 
  VkSemaphore           Semaphore; 
  VkPipelineStageFlags  WaitingStage; 
};

通过它,我们提供一个信号量的句柄,硬件在处理给定的命令缓冲区之前应该等待,并且我们还指定应该在哪个管道阶段进行等待。

怎么做...

1.获取应该提交工作的队列的句柄。使用句柄初始化名为queue的VkQueue类型变量。
2.创建一个名为wait_semaphore_handles的std::vector<VkSemaphore>类型变量。如果提交的命令应等待其他命令结束,在变量中存储给定队列应该等待的所有信号量的句柄。
3.创建一个名为wait_semaphore_stages的std::vector<VkPipelineStageFlags>类型变量。如果提交的命令应等待其他命令结束,则使用管道阶段初始化向量,在该阶段,队列应等待来自wait_semaphore_handles变量的相应信号量以发出信号。
4.准备名为command_buffers的std::vector<VkCommandBuffer>类型变量。存储应提交到所选队列的所有记录命令缓冲区的句柄。确保设备当前没有处理这些缓冲区,或者使用VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT标志记录这些命令缓冲区。
5.创建一个名为signal_semaphores的std::vector<VkSemaphore类型变量。在此向量中存储当在command_buffers变量中提交的所有命令缓冲区完成时应该发出信号的所有信号量的句柄。
6.创建一个名为fence的VkFence类型变量。如果在完成command_buffers变量中提交的所有命令缓冲区的处理时应发送围栏信号,请将此围栏的句柄储存在fence变量中。否则使用VK_NULL_HANDLE值初始化此变量。
7.创建名为submit_info的VkSubmitInfo类型的变量。使用一下值初始化其成员:
  ·sType为VK_STRUCTURE_TYPE_SUBMIT_INFO
  ·pNext为nullptr
  ·waitSemaphoreCount为wait_semaphore_handles向量中的元素数量
  ·pWaitSemaphores为指向wait_semaphore_handles向量的第一个元素的指针如果向量是空则为nullptr值。
  ·pWaitDstStageMask为指向wait_semaphore_stages向量的第一个元素的指针如果向量是空则为nullptr值。
  ·commandBufferCount提交的命令缓冲区数量(command_buffers向量中的元素数量)。
  ·pCommandBuffers为指向command_buffers向量的第一个元素的指针如果向量是空则为nullptr值。
  ·signalSemaphoreCount为signal_semaphores向量中的元素数量。
  ·pSignalSemaphores为指向signal_semaphores向量的第一个元素的指针如果向量是空则为nullptr值。
8.调用vkQueueSubmit( queue, 1, &submit_info, fence )并且提供提交工作的队列句柄、1值、指向submit_info变量的指针和fence变量。
9.通过检查返回值是否是VK_SUCCESS值,确保调用成功。

这个怎么运作...

当我们将命令缓冲区提交给设备的队列时,一旦提交到同一队列的之前命令处理完成,它们就会被执行。从应用程序的角度来看,我们不知道命令何时将被执行。它可能会立即开始或稍后开始。

当我们想要推迟处理提交的命令时,需要通过提供一个信号量列表来同步它们,给定队列应该在执行提交的命令缓冲区之前等待。

当我们提交命令缓冲区并提供信号量列表时,每个信号量都与一个通道阶段相关联。执行命令直到它们到达指定的管道阶段,它们暂停并等待信号量发出信号。

在提交期间,信号量和管道阶段位于单独的数组中。因此我们需要将自定义类型WaitSemaphoreInfo的元素向量拆分为两个独立的向量:

std::vector<VkSemaphore>          wait_semaphore_handles; 
std::vector<VkPipelineStageFlags> wait_semaphore_stages; 

for( auto & wait_semaphore_info : wait_semaphore_infos ) { 
  wait_semaphore_handles.emplace_back( wait_semaphore_info.Semaphore ); 
  wait_semaphore_stages.emplace_back( wait_semaphore_info.WaitingStage ); 
};

现在,我们已准备好接受提交。对于提交,命令缓冲区应该等待信号量、执行等待的管道阶段、命令缓冲区和用信号通知的另一个信号量列队,都是通过VkSubmitInfo类型变量指定的:

VkSubmitInfo submit_info = {
  VK_STRUCTURE_TYPE_SUBMIT_INFO,
  nullptr,
  static_cast<uint32_t>(wait_semaphore_infos.size()),   
  wait_semaphore_handles.size() > 0 ? &wait_semaphore_handles[0] : nullptr, 
  wait_semaphore_stages.size() > 0 ? &wait_semaphore_stages[0] : nullptr,   
  static_cast<uint32_t>(command_buffers.size()),
  command_buffers.size() > 0 ? &command_buffers[0] : nullptr,   
  static_cast<uint32_t>(signal_semaphores.size()), 
  signal_semaphores.size() > 0 ? &signal_semaphores[0] : nullptr
};

然后像这样提交这批数据:

VkResult result = vkQueueSubmit( queue, 1, &submit_info, fence ); 
if( VK_SUCCESS != result ) {
  std::cout << "Error occurred during command buffer submission." << std::endl;
  return false; 
}
return true;

当我们提交命令缓冲区时,设备将执行记录的命令并产生所需的结果,例如它将在屏幕上绘制3D场景。这里我们只提交一批命令缓冲区,但可以提交多个批次。

提示:出于性能原因,我们应尽可能少调用函数而每次调用尽可能多的提交批次。

如果已经提交了命令缓冲区并且它们的执行尚未结束,我们就不应该再提交它们,只有在使用VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT标志记录命令缓冲区时才能执行此操作,但出于性能原因,应该避免使用此标志。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值