Vulkan将命令缓冲区提交给队列

Vulkan将命令缓冲区提交给队列
前面介绍了将命令记录到命令缓冲区的方式,目的是利用图形硬件的能力处理这些准备好的操作。接下来,我们需要将已经准备好的作业提交给选定的队列。

准备工作

本例将使用自定义数据WaitSemaphoreInfo类型,下面是该类型的定义。

Vulkan将命令缓冲区提交给队列
我们通过该类型的变量存储信号的句柄,使硬件在指定命令缓冲区被执行完之前等待,我们还通过该类型的变量设定应进行等待的管线阶段。

具体处理过程

(1)获取用于提交作业的队列的句柄,将该句柄存储到一个VkQueue类型的变量中,将该变量命名为queue。
(2)创建一个std::vector<VkSemaphore>类型的变量,将其命名为wait_semaphore_handles。如果已提交的命令应该等待其他命令被执行完,在该变量中存储信号的句柄,那么这些信号用于指明在执行完已提交的命令缓冲区前,指定队列应等待。
(3)创建一个std::vector<VkPipelineStageFlags>类型的变量,将其命名为wait_semaphore_stages。如果已提交的命令应该等待其他命令被执行完,就将队列应等待wait_semaphore_handles变量中相应信号的状态变为已发出,并将所处的管线阶段赋予wait_semaphore_stages变量。
(4)创建一个std::vector<VkCommandBuffer>类型的变量,将其命名为command_buffers。将应提交给选定队列的所有已记录命令缓冲区的句柄存储在该变量中,确保这些命令缓冲区中没有一个正在被设备处理,以及是通过VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT标志记录的。
(5)创建一个std::vector<VkSemaphore>类型的变量,将其命名为signal_semaphores。该vector容器变量用于存储信号句柄,这些信号用于指明存储在command_buffers变量中的所有命令缓冲区是否已经被执行完,如果所有命令缓冲区都被执行完了,这些信号的状态就会变为已发出。
(6)创建一个VkFence类型的变量,将其命名为fence。如果当command_buffers变量中存储的所有命令缓冲区都被执行完时,栅栏的状态切换为已发出,就将该栅栏的句柄存储到fence变量中;否则,就将VK_NULL_HANDLE赋予该变量。
(7)创建一个VkSubmitInfo类型的变量,将其命名为submit_info。使用下列值初始化该变量中的各个成员。
● 将VK_STRUCTURE_TYPE_SUBMIT_INFO赋予sType成员。
● 将nullptr赋予pNext成员。
● 将vector容器wait_semaphore_handles变量中含有元素的数量赋予waitSemaphoreCount成员。
● 如果vector容器wait_semaphore_handles变量是空的,就将nullptr赋予pWaitSemaphores成员;否则,就将指向vector容器wait_semaphore_handles变量中第一个元素的指针赋予pWaitSemaphores成员。
● 如果vector容器wait_semaphore_stages变量是空的,就将nullptr赋予pWaitDstStageMask成员;否则,就将指向vector容器wait_semaphore_stages变量中第一个元素的指针赋予pWaitDstStageMask成员。
● 将commandBufferCount成员的值设置为已提交命令缓冲区的数量(vector容器command_buffers变量含有元素的数量)。
● 如果vector容器command_buffers变量是空的,就将nullptr赋予pCommandBuffers成员;否则,就将指向vector容器command_buffers变量中第一个元素的指针赋予pCommandBuffers成员。
● 将signalSemaphoreCount成员的值设置为vector容器signal_semaphores变量中含有元素的数量。
● 如果vector容器signal_semaphores变量是空的,就将nullptr赋予pSignalSemaphores成员;否则,就将指向vector容器signal_semaphores变量中第一个元素的指针赋予pSignalSemaphores成员。
(8)调用vkQueueSubmit(queue,1,&submit_info,fence)函数。将第一个参数设置为用于提交作业的句柄;将第二个参数设置为1;将第三个参数设置为指向submit_info变量的指针;将第四个参数设置为fence变量。
(9)通过查明该函数调用操作返回值等于VK_SUCCESS,确认该函数调用操作成功完成。

具体运行情况

当将命令缓冲区提交到设备的队列中时,一旦队列中之前提交的命令被处理完,这些命令缓冲区就会立刻被执行。从应用程序的观点看,它不知道这些命令缓冲区被执行的确切时间。这些命令缓冲区可能会立刻被执行,也可能会等待一段时间后再被处理。
当想要延缓执行已提交的命令时,需要使用信号列表,指明在已提交的命令缓冲区被执行完之前,指定队列应该等待,从而实现同步化。
当提交了命令并创建信号列表后,每个信号会与一个管线阶段关联起来。当到达指定的管线阶段时,相应信号的状态就会切换为已发出,原来处于暂停和等待状态的对应命令就会被执行。
在提交命令的过程中,信号和管线都存储在独立的数组中。因此,我们需要将元素类型为WaitSemaphoreInfo的vector容器,拆分为两个独立的vector容器。

Vulkan将命令缓冲区提交给队列
这样就可以执行常规的提交操作了。为了执行提交操作,命令缓冲区等待的信号、执行处于等待状态的命令的管线阶段、命令缓冲区和应该切换为已发出状态的信号列表,都通过一个VkSubmitInfo类型的变量设定。

Vulkan将命令缓冲区提交给队列
使用下列代码可以提交这批命令缓存区。

Vulkan将命令缓冲区提交给队列
当提交命令缓冲区时,设备会执行已记录的命令并生成我们想要的结果,如在屏幕上绘制3D场景。
本例仅提交了一批命令缓冲区,实际上可以提交多批命令缓冲区。

TIP为了提高性能,应通过尽可能少的函数调用操作,提供尽可能多的命令缓冲区。

不应提交那些已经被提交且还未被处理完的命令缓冲区。只有当命令缓冲区是通过VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT标志分配的时,才能这样做。然而,为了提高性能,应避免使用VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT标志。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!

 

Vulkan实战