前言:
适用于 Vulkan 管道屏障的大部分内容也适用于通用屏障和内存屏障,因此您可以从那里开始建立您的直觉。
我要指出的是,尽管该规范不是教程,但它相当清晰且可读。同步is也许最难的部分和规范中的描述反映了这一点。最重要的是,内存屏障对于大多数人来说都是新奇的(它们通常被高级语言编译器屏蔽掉这样的概念)。
需要的定义:
Pipeline是如何处理工作单元的抽象方案。有四种类型(尽管 Vulkan 没有告诉供应商如何做事,只要他们遵守规则):
- 主机访问伪管道(一级)
- 转移(一级)
- 计算(一级)
- 图形(有很多阶段,即 DI→VI→VS→TCS→TES→GS→EFT→FS→LFT→输出)
有特殊阶段 TOP(在完成任何操作之前)、BOTTOM(在所有操作完成之后)和 ALL(与设置了所有阶段的位字段相同)。
(行动)command是一个需要(一个或多个)通过管道的命令。它必须被记录到命令缓冲区(除了主机通过vkMapMemory()
).
命令缓冲区是一些命令序列(在recorded命令!)。和queue也是一个序列recorded命令(从提交的命令缓冲区连接)。
队列在执行命令的顺序上有一定的余地(只要保留用户设置的状态,它就可以重新排序命令)并且也可以重叠命令(例如,在完成上一个命令的 FS 之前执行下一个命令的 VS)。用户定义的同步原语设置了此余地的边界。 (还有一些隐含的保证——但最好不要依赖它们并过度同步,直到有信心为止)
我对解释管道障碍的看法:
(也许不幸的是)管道障碍合并了三个独立的方面——执行障碍、内存障碍和布局转换(如果是图像)。
The 执行障碍部分确保在屏障到达之前记录的所有命令执行至少指定的管道阶段(或多个阶段)srcStageMask
beforeBarrier 开始执行其指定阶段(或多个阶段)后记录的任何命令dstStageMask
.
它只处理执行依赖性,而不处理内存!这记忆屏障部分确保内存(缓存)被正确刷新并在两者之间的某个位置失效执行障碍依赖性(即在依赖命令和阶段之后以及依赖命令和阶段之前)。
您提供它是什么类型的内存依赖关系以及什么类型的源/消费者之间的依赖关系(因此驱动程序可以选择适当的操作而无需记住状态本身)。典型的写-读依赖关系(读-读和读-写不需要任何内存同步,写-写通常没有多大意义——为什么要覆盖一些数据而不先读取它们)。
在某些硬件上,内存中的不同数据布局可能是有利的(甚至是必要的)。在处理内存依赖性的同时,数据被重新排序以遵循新的指定布局。