同步两个命令缓冲区
译者注:示例代码点击此处
我们知道如何准备工作并将其提交给队列。也知道如何创建信号量。在此节内容中。我们将了解如何使用信号量来同步两个命令缓冲区。更具体地说,我们将学习如何推迟命令缓冲区的处理,直到完成另一个命令缓冲区的处理后再开始。
做好准备
在本章中,我们将使用在提交命令缓冲区引入的WaitSemaphoreInfo结构,它的定义是:
struct WaitSemaphoreInfo {
VkSemaphore Semaphore;
VkPipelineStageFlags WaitingStage;
};
怎么做...
1.获取将提交第一批命令缓冲区的队列句柄。将此句柄储存在名为first_queue的VkQueue类型变量中。
2.创建在第一批命令缓冲区的处理完成时应发出信号的信号量(请参阅创建信号量内容)。将信号量储存在名为synchronizing_semaphores的std::vector<WaitSemaphoreInfo>类型变量中。准备第二批命令缓冲区等待每个信号量的阶段列表,这些阶段包含在synchronizing_semaphores向量中。
3.准备第一批命令缓冲区并将它们提交到first_queue变量表示的队列。在信号量列表中包含synchronizing_semaphores向量以发出信号(请参阅将将命令缓冲区提交到队列内容)。
4.获取队列的句柄,第二批命令缓冲区将提交到该队列。将此句柄存储在名为second_queue的VkQueue类型的变量中。
5.准备第二批命令缓冲区并将它们提交到队列,由second_queue变量表示,在信号量和阶段列表中包含来自synchronizing_semaphores向量的信号量和阶段以等待(请参阅将命令缓冲区提交到队列内容)。
这个怎么运作...
在这节内容中,我们提交了两批命令缓冲区。当第一批由硬件处理并完成时,它会发信号通知信号量列表中包含的所有信号量。我们只接受信号量的句柄,因为在信号量发出信号的过程中不需要管道阶段。
std::vector<VkSemaphore> first_signal_semaphores;
for( auto & semaphore_info : synchronizing_semaphores ) {
first_signal_semaphores.emplace_back( semaphore_info.Semaphore );
}
// 译者注:等待first_wait_semaphore_infos来信号后执行first_command_buffers,然后发送信号到first_signal_semaphores。
if( !SubmitCommandBuffersToQueue( first_queue, first_wait_semaphore_infos, first_command_buffers, first_signal_semaphores, VK_NULL_HANDLE ) ) {
return false;
}
接下来,我们采用这些相同的信号量,并在提交第二批命令缓冲区时使用它们。这次使用句柄和管道阶段。第二批将等待指定管道阶段的所有提供的信号量。着意味着提交的命令缓冲区的某些部分可能会开始处理,但是当它们到达提供的阶段时,处理暂停,如下图所示:
if( !SubmitCommandBuffersToQueue( second_queue, synchronizing_semaphores, second_command_buffers, second_signal_semaphores, second_fence ) ) {
return false;
}
return true;
//译者注:等待上次调用SubmitCommandBuffersToQueue函数发送到first_wait_semaphore_infos的信号,synchronizing_semaphores函数里的信号量和first_wait_semaphore_infos是同一批,
//但是synchronizing_semaphores里还包含了阶段参数。等到适合的阶段到来和收到所有信号之后,会执行特定的缓冲区命令,执行完毕后会继续发送信号到second_signal_semaphores中所有的信号量上,
//注意这些同步都是在设备上离线进行的,只有围栏second_fence才是应用程序提交命令缓冲区到队列时做同步用的,但是在这里second_fence只是一个演示她打了个酱油没有起到实际作用。
这显示了如何同步从第一逻辑设备提交到不同队列的多个命令缓冲区的工作。来自第二次提交的命令缓冲区的处理将被推迟,直到第一批中的所有命令都完成为止。