【发布时间】:2020-02-21 12:59:50
【问题描述】:
于是就有了这个官方例子https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples#combined-graphicspresent-queue:
/* Only need a dependency coming in to ensure that the first
layout transition happens at the right time.
Second external dependency is implied by having a different
finalLayout and subpass layout. */
VkSubpassDependency dependency = {
.srcSubpass = VK_SUBPASS_EXTERNAL,
.dstSubpass = 0,
// .srcStageMask needs to be a part of pWaitDstStageMask in the WSI semaphore.
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dependencyFlags = 0};
是否有人可以向我提供规范中的相关部分,以保证(构成推理链)在队列的等待信号量(图像获取)发出信号之前不会发生这种依赖布局转换?
特别是我找不到如何解释这种“从同一阶段到自身的依赖关系”。
要清楚。我在这里找到了很多似乎相关的地方。我已经阅读文档一个多月了,但我很难在其中找到连贯性。
例如,当(根据规范)可用性操作确实发生时?什么时候提交了相关的内存依赖操作(按提交顺序)?如果是,那么提交子通道依赖项的时间是什么时候?或者它是在源范围指令和目标范围指令之间的某个地方(如If srcSubpass is equal to VK_SUBPASS_EXTERNAL, the first synchronization scope includes commands that occur earlier in submission order than the vkCmdBeginRenderPass)。如果是,上面示例中的srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT 指的是什么指令?
在 krOoze 回答后编辑
我想我会写在这里。一是因为评论太长,二是因为我相信它可能对其他人有用。
我承认,我误解了规范中关于执行依赖链的部分。
所以总结一下。为了根据规范定义所讨论的机制,我们有以下内容:
-
等待信号量操作happens-before子通道依赖操作(这里我其实有点麻烦):
6.4.2。信号量等待*
信号量等待操作发生在执行依赖中的第一组操作之后,并且发生在执行依赖中的第二组操作之前。但是如何确定我们的子通道依赖操作在第二组中呢?它在同一批中,它没有定义关于子通道依赖的提交顺序(至少我看不到一个),并且信号量第二同步范围的定义没有帮助,因为我们的子通道依赖没有发生在 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT 管道阶段(这是 vkQueueSubmit 情况下第二个同步范围的限制)。更重要的是同步范围无论如何都没有定义第二组操作。这是一个独特的术语。但是我在这里发现了另外一个可能有用的语句(好吧,如果我们同意子通道依赖项是工作项的一部分):
4.3.5。队列提交
每个批次由三个不同的部分组成:- 零个或多个信号量等待在执行之前其余批次。
- 要执行零个或多个工作项。
- 零个或多个信号量在工作项目完成时发出信号。
并且我们需要确定这个顺序来构建执行依赖链:
-
等待信号量和subpass依赖构成一个执行依赖链根据:
6.1。执行和内存依赖
执行依赖链是执行依赖的序列,它在第一个依赖的 A' 和最终的依赖的 B' 之间形成发生前的关系。对于每一对连续的执行依赖,如果第一个依赖中的BS和第二个依赖中的AS的交集为不是空集。(详见 krOoze 的回答)
由此我们知道,我们的子通道依赖项的目标范围将发生信号量(信号操作在信号量等待操作的源范围内)。
现在我们应该可以使用布局转换规则了: -
布局转换发生在我们的子通道依赖的可用性操作之后:
7.1。渲染通道创建
对于 srcSubpass 等于 VK_SUBPASS_EXTERNAL 的所有依赖项,在可用性操作之后从 initialLayout 自动布局转换,其中 dstSubpass 使用将要转换的附件。老实说,我仍然缺少规范中信号量和可用性操作部分之间的顺序,但我认为可以假设。
(上述方法可行,因为可用性操作是内存依赖操作的一部分:执行内存依赖的操作会生成:
• 在依赖项的第一个访问范围和设备域的目标范围内具有所有写入的源范围的可用性操作。我们的第一个访问范围是空的,但它仍然是一个可用性操作,对吧?)
还有这样的说法:
但是,对于附件,子通道依赖项的工作方式更像是定义类似于上面的 VkMemoryBarrier 的 VkImageMemoryBarrier,队列系列索引设置为 VK_QUEUE_FAMILY_IGNORED,并且布局如下:
• oldLayout 的等价物是根据 srcSubpass 的子通道描述的附件布局。
• 与newLayout 等效的是根据dstSubpass 的子通道描述的附件布局。
...这带来了另一个分析范围,但我已经很头疼了。当我对上述想法进行一些审查时,我会非常乐意对此进行更多编辑。
*所有规范都来自“Vulkan® 1.2.132 - A Specification (with all registered Vulkan extensions)”
【问题讨论】:
标签: synchronization vulkan memory-model