关于vulkan依赖链的问题,如何解释Scope1st和Scope2nd int的定义

问题描述 投票:0回答:1

根据依赖链的定义:

• Let Ops1 and Ops2 be separate sets of operations. 
• Let Sync be a synchronization command.
• Let Scope1st and Scope2nd be the synchronization scopes of Sync. 
• Let ScopedOps1 be the intersection of sets Ops1 and Scope1st. 
• Let ScopedOps2 be the intersection of sets Ops2 and Scope2nd. 
• Submitting Ops1, Sync and Ops2 for execution, in that order, will result in execution dependency ExeDep between ScopedOps1 and ScopedOps2. 
• Execution dependency ExeDep guarantees that ScopedOps1 happen-before ScopedOps2. 

An execution dependency chain is a sequence of execution dependencies that form a happens-before
relation between the first dependency’s ScopedOps1 and the final dependency’s ScopedOps2. 
For each consecutive pair of execution dependencies, a chain exists if the intersection of Scope2nd in the first dependency and Scope1st in the second dependency is not an empty set.

我的问题是:Scope1st 和 Scope2nd 是“固定的”,还是“动态的”? 这里,“修复”意味着它们仅由 stageMasks 确定。另一方面,“动态”意味着它们取决于相关命令的实际记录方式。

为了让事情更清楚,我想玩一个简单的场景。

让我们关注一个特定的帧N。调用vkAcquireNextImage并成功获取图像IDX和信号量R后,R引用的信号操作被提交执行。我们将信号操作缩写为 sig_op

假设我们的渲染非常简单。命令缓冲区如下所示:

Begin();
vkBeginRenderPass();
Draw();
vkEndRenderPass();
End();

当这个命令缓冲区被提交到队列时,它形成一个批次。我们称之为 bat_N。并且bat_N将通过将等待阶段指定为Color_Output来等待信号量R从vkAcquireNextImage返回。

一旦队列提交,bat_N就会定义一个依赖D_R,根据信号量等待操作:

The first synchronization scope includes all semaphore signal operations that operate on
semaphores waited on in the same batch, and that happen-before the wait completes.
The second synchronization scope includes every command submitted in the same batch. In the
case of vkQueueSubmit, the second synchronization scope is limited to operations on the pipeline
stages determined by the destination stage mask specified by the corresponding element of
pWaitDstStageMask.
在 Draw() 中,

D_R的第一个范围应该是sig_op,第二个范围应该是color_opD_R可以确保sig_op发生在color_op之前,从而成功使color_op等待演示读取。到目前为止,一切都很好。

现在,为了将图像布局转换与从 vkAcquireNextImage 获取的图像同步,即使转换在图像读取完成后发生,应该引入一个 vkSubpassDependency,其中 srcStage 设置为 VK_SUBPASS_EXTERNAL。典型的设置可能如下所示:

    // Create a dependency to external events.
    // We need to wait for the WSI semaphore to signal.
    // Only pipeline stages which depend on COLOR_ATTACHMENT_OUTPUT_BIT will
    // actually wait for the semaphore, so we must also wait for that pipeline stage.
    VkSubpassDependency dependency = {0};
    dependency.srcSubpass          = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass          = 0;
    dependency.srcStageMask        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstStageMask        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

    // Since we changed the image layout, we need to make the memory visible to
    // color attachment to modify.
    dependency.srcAccessMask = 0;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

我们的目的是让布局转换等待sig_op。可以通过让D_S等待D_R来实现,这在逻辑上形成了依赖链。

现在我们根据 Scope1st 和 Scope2nd 解释为“固定”还是“动态”来分析是否可以建立链。

在我们的示例中,很明显第一个依赖项是 D_R,接下来的依赖项是 D_S

如果我们将它们视为“固定”方式,那么D_R的Scope2nd和D_S的Scope1st都包含STAGE_COLOR_ATTACHMENT_OUTPUT,交集不为空,因此依赖链在那里。

但是,我个人更喜欢将它们视为“动态”方式,因为规范中依赖关系的定义将它们声明为同步范围。并且根据vkSubpassDependency中同步范围的描述:

If srcSubpass is equal to VK_SUBPASS_EXTERNAL, the first synchronization scope 
includes commands that occur earlier in submission order than the vkCmdBeginRenderPass 
used to begin the render pass instance. Otherwise, the first set of commands 
includes all commands submitted as part of the subpass instance identified by srcSubpass 
and any load, store, or multisample resolve operations on attachments used in srcSubpass. 
In either case, the first synchronization scope is limited to operations on the pipeline stages 
determined by the source stage mask specified by srcStageMask

它给我一种感觉,最终进入同步范围的事物是基于所插入的依赖项的上下文的。 那么在我们的示例中,D_R中的Scope2nd应该是bat_N中的color_op。但是对于 D_S 中的 Scope1st,bat_N 中没有任何内容,因为 vkBeginRenderPass 是 bat_N 中的第一个命令,因此交集应该为空,并且这里不应该有链。

如果链不存在,是否只是意味着D_S等不及D_R?那么同步一定很糟糕吧?

vulkan
1个回答
0
投票

你似乎把事情搞得太复杂了。信号量的范围和子通道依赖性完全无关。它们是两个独立的同步操作。

信号量依赖性 = 在解决信号量依赖性之前,提交的命令缓冲区中的任何内容都无法继续(受 src 和 dst 阶段掩码影响)。它不关心它正在提交的命令缓冲区内的任何依赖关系(它甚至没有机制来了解它们)。

外部子通道依赖性 = 在队列中的先前工作得到解决之前,子通道中的任何内容都无法继续(受 src 和 dst 阶段掩码影响)。它不关心/了解信号量范围(它甚至没有机制来了解它们)。

© www.soinside.com 2019 - 2024. All rights reserved.