你将在本章所学到的内容
- 如何在主机与设备之间进行同步
- 如何在 同一 设备上 不同 队列中同步作业
- 如何在流水线中的不同点上同步所执行的作业
Vulkan被设计为在一个设备上含有多个队列中进行异步、并行地运行作业,并且与主机一起协同,以保持物理资源始终在使用状态且繁忙。在你应用程序中各种不同的点处(时间与代码位置),你需要保持主机与设备各种不同部分的同步状态。在本章,我们将为此目的会讨论对Vulkan应用程序可用的几种同步原语。
Vulkan中的同步通过对各种不同的同步原语的使用加以实现。Vulkan中有几种类型的同步原语并且它们意为在一个应用程序中的不同用途。三种主要类型的同步原语是:
- 栅栏(Fences):当主机需要等待设备完成由一次提交所表示的大量作业的执行之时,使用该同步原语,通常需要操作系统的辅助。
- 事件(Events):表示一个细粒度的同步原语,它可以接受来自主机或设备端的信号。当由设备端发起信号时,它可以在命令缓存之间接受信号,并且它可以在流水线中的一些特定点处被设备等待。
事件是一种同步原语,它可以用于在提交到同一个队列的其中两个命令之间插入一个细粒度的依赖,或是在一个队列与主机之间插入。事件不能在提交到不同队列中的命令之间插入依赖。事件具有两个状态——发出信号的(signaled)和未发出信号的(unsignaled)。一个应用程序可以在主机端亦或在设备上对一个事件发出信号(signal,即状态变为 signaled)或不发信号(unsignal,即状态变为 unsignaled)。可以让一个设备在执行后续操作之前等待一个事件变为 signaled。不存在某种命令使得主机端可等待一个事件变为 signaled,不过一个事件可以被查询。 - 信号量(Semaphores):用于在一单个设备上跨不同队列控制资源所有权的同步原语。它们可以被用于同步执行在不同队列上的作业,而这些作业可以异步执行。
栅栏(Fences)
栅栏是一种中等量级的同步原语,它一般需要操作系统的帮助进行实现。栅栏被放置到与操作系统进行交互的命令,诸如 vkQueueSubmit()
,并且当这些命令所发起的作业完成时,该栅栏将会接受到信号。
因为栅栏通常对应于由操作系统提供的本地的同步原语,一般当主机端的线程等待栅栏时,将该线程置为睡眠状态是有可能的,而这可以用于省电。然而此同步原语的意图是为那些可能会花费一些时间进行等待的操作,比如,等待一些命令缓存执行完成;或是等待将一个已完成的帧呈现给用户。
要创建一个新的栅栏对象,调用 vkCreateFence()
,其原型为:
// Provided by VK_VERSION_1_0
VkResult vkCreateFence(
VkDevice device,
const VkFenceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
网友评论