我试图理解 VkSubpassDependency 结构的规范。
VkSubpassDependency 结构的链接位于规范页面上
让我很困惑的部分是(srcSubpass,dstSubpass)和(srcStageMask,dstStageMask)之间的关系。
srcSubpass 等于 dstSubpass 的情况与管道屏障相同,不会对我提出任何问题。然而,其他案件则颇值得商榷。
规范说:
如果srcSubpass等于VK_SUBPASS_EXTERNAL,则第一个同步范围包括按提交顺序早于用于开始渲染通道实例的 vkCmdBeginRenderPass 发生的命令。否则,第一组命令包括作为srcSubpass标识的子通道实例的一部分提交的所有命令以及对srcSubpass中使用的附件的任何加载、存储或多采样解析操作。在任何一种情况下,第一个同步范围仅限于由srcStageMask指定的源阶段掩码确定的管道阶段上的操作。
通过使用同步依赖项中规范给出的同步范围的定义,我以这种方式解释规范:
在这种情况下,我解释为依赖关系按以下方式工作:srcSubpass在管道阶段上自由执行,直到到达srcStageMask参数中给出的阶段,并停止,直到dstSubpass到达dstStageMask中描述的阶段。
在这种情况下,我对确定第一个同步范围感到困惑。
因为srcSubpass等于VK_SUBPASS_EXTERNAL,所以第一个同步范围包括在提交顺序中早于用于开始渲染通道实例的 vkCmdBeginRenderPass (如规范所述)的命令。因为外部命令可能与管道阶段没有任何交互,所以它使得srcStageMask的解释相当模糊。因为与管道阶段相关的任何内容都可能不在渲染过程之外:规范中是否有以下行:“在任何一种情况下,第一个同步范围仅限于由 srcStageMask 指定的源阶段掩码确定的管道阶段上的操作。” 指的是dstSubpass内的管道阶段,并将第一个同步范围扩展到dstSubpass中的srcStageMask阶段?
你基本上是在回答你的问题。我认为问题是你对管道阶段有错误的直觉。
考虑一下您已提交到队列的所有命令。每个命令都位于某个管道阶段中的任何点,并且所有命令独立地通过管道进行(我应该说是异步的)。将管道视为一个游戏板,并将命令视为该板上的钉子。其他一切都应该随着新的直觉而开始变得有意义。
管道屏障\子通道依赖性引入了依赖性。结果是,在目标范围中的任何命令被允许开始srcStageMask
其执行阶段之前,源范围中的所有命令都必须至少完成dstStageMask
其执行阶段。
srcSubpass == dstSubpass
是一种特殊情况,除了声明子通道自相关之外什么也不做。它所做的只是允许您稍后vkCmdPipelineBarrier
在 Subpass 录音中使用。它的工作原理与普通的 Pipeline Barrier 类似,只是它仅限于该子通道内的命令,并且不允许更改图像布局。
srcSubpass < dstSubpass
case 引入了这两个子通道之间的依赖关系。中记录的命令srcSubpass
是源范围, 中的命令dstSubpass
是目标范围。srcStage
即,在目标子通道中的任何命令被允许开始执行之前,源子通道中的所有命令必须至少到达dstStage
。
VK_SUBPASS_EXTERNAL
指渲染通道实例的外部。
即,如果srcSubpass == VK_SUBPASS_EXTERNAL
,则源范围是之前记录的所有命令vkCmdBeginRenderPass
以及提交顺序中较早的任何内容。因此,这个子通道依赖关系会说渲染通道实例之前的所有命令都必须至少到达其srcStage
执行阶段,然后才能dstSubpass
进入其dstStage
阶段。
如果dstSubpass == VK_SUBPASS_EXTERNAL
那么目标范围是之后记录的所有命令(以及提交顺序vkCmdEndRenderPass
中稍后记录的命令)。因此,这个子通道依赖关系会说,在渲染通道实例之后的任何命令进入其执行阶段之前,子通道中记录的所有命令都必须至少到达其执行阶段。srcSubpass
srcStage
dstStage