Vulkan编程指南翻译 第三章 队列和命令 第5节 命令的提交

2017-02-28

3.5  命令的提交

我们需要向一个设备的队列提交命令缓冲区,才能执行它,需要调用vkQueueSubmit(),原型如下:

VkResult vkQueueSubmit (

VkQueue  queue,

uint32_t  submitCount,

const VkSubmitInfo*  pSubmits,

VkFence  fence);

这个命令可以把命令提交到一个或者多个命令缓冲区来执行它。queue参数指定了命令缓冲区发送的目标设备队列。对队列的访问必须要在外部保持同步。所有的命令缓冲区都是从pool中分配而来的,pool必须参照一个队列集来创建。队列集是通过传给vkCreateCommandPool() 函数的VkCommandPoolCreateInfo类型的queueFamilyIndex成员指定的,queue类型必须是类型集合中的一种。

submitCount指定了提交的个数,pSubmits是一个数组,描述了每一个提交的信息。每一个提交都通过一个VkSubmitInfo类型的数据表示,其原型如下:

typedef struct VkSubmitInfo {

VkStructureType  sType;

const void*  pNext;

uint32_t  waitSemaphoreCount;

const VkSemaphore*  pWaitSemaphores;

const VkPipelineStageFlags*  pWaitDstStageMask;

uint32_t  commandBufferCount;

const VkCommandBuffer*  pCommandBuffers;

uint32_t  signalSemaphoreCount;

const VkSemaphore*  pSignalSemaphores;

} VkSubmitInfo;

sType域可以被设置为VK_STRUCTURE_TYPE_SUBMIT_INFO,pNext应当被设置为nullptr。每一个VkSubmitInfo数据结构都可以代表多个将要被执行的命令缓冲区。

每一个命令缓冲区集合都被包裹进一个信号集合中,在执行前将一直等着这个信号,且在完成后通知一个或多个信号。一个信号是一种类型的同步原语,它允许被不同队列执行的工作能够被正确的预定和协调。我们将在第十一章“同步”中讲解信号量和其他同步原语。这里,我不再使用这些域了,所以,waitSemaphoreCount 、signalSemaphoreCount可被置为0,pWaitSemaphores, pWaitDstStageMask, 和 pSignalSemaphores可被置为nullptr。

我们想要执行的命令缓冲区被放置在一个数组中,其地址通过pCommandBuffers参数传递。需要被执行的命令缓冲区的个数(亦即pCommandBuffers数组的大小)是通过commandBufferCount指定的。在vkQueueSubmit()被调用后的某个时刻,命令缓冲区中的命令开始被执行了。被提交到同一设备中不同队列的命令(或者不同设备的不同队列)可被并行执行。一旦命令缓冲区被scheduled妥当,vkQueueSubmit()就返回了,可能比真正执行的时刻早很多。

vkQueueSubmit()函数的fence参数,是一个fence对象的handle,可用来等待命令的完成。Fence是我们将在第十一章讲到的同步原语中的一个。现在,我们仅把fence置为VK_NULL_HANDLE。直到我们越过围栏时,我们都可调用vkQueueWaitIdle()来等待提交给队列的任务被完成,其原型如下:

 

VkResult vkQueueWaitIdle (

VkQueue queue);

唯一的参数queue,就是需要等待的队列。当vkQueueWaitIdle()返回时,所有提交到队列的命令都保证完成了。等待一个设备上所有队列的所有命令完成,一个快捷的方式是调用vkDeviceWaitIdle()。其原型如下:

VkResult vkDeviceWaitIdle (

VkDevice device);

调用vkQueueWaitIdle() 或者 vkDeviceWaitIdle(),是很不被推荐的,因为他们把任何工作都刷新到队列或设备上,这是非常重量级的工作。在性能要求严苛应用程序中,不应该使用该调用。适合使用的场景有:关闭应用,重新初始化线程管理,内存管理等子系统,这些情形下无论如何都会有一个持续的暂停。

 

总结

本章向你介绍了命令缓冲区,应用程序和Vulkan设备通过command交流的机制。我们介绍了首个Vulkan命令并展示了如何要求设备执行任务。

讨论了如何把命令缓冲区,通过提交到队列发送到Vulkan设备以被执行。你看到如何保证所有的工作都被提交到队列或者设备如何保证完成了执行工作。即使我们粗略的讲到了一些主题,如一个命令缓冲区如何调用另一个,精细力度的管理CPU和GPU设备上队列之间的同步,这些话题将在后续的章节涉及到。

如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)