vkCmdPipelineBarrier关于渲染通道同步范围的说明

时间:2019-10-25 16:19:39

标签: synchronization vulkan

在对vulkan spec感到困惑之前,我看到了vkCmdPipelineBarrier的以下更新说明:

  

如果vkCmdPipelineBarrier记录在渲染过程实例之外,   第一个同步范围包括发生的所有命令   提交顺序较早。 如果记录了vkCmdPipelineBarrier   在渲染通道实例中,第一个同步作用域   仅包含提交顺序较早的命令   相同的子通道。在任何一种情况下,第一个同步范围是   限于源确定的流水线阶段的操作   srcStageMask指定的舞台遮罩。

     

如果vkCmdPipelineBarrier记录在渲染过程实例之外,则第二个同步范围将包括所有   稍后按提交顺序进行。 如果记录了vkCmdPipelineBarrier   在渲染通道实例中,第二个同步范围   仅包括以后提交顺序中出现的命令   相同的子通道。在任何一种情况下,第二个同步范围是   仅限于由   dstStageMask指定的目标阶段掩码。

如果我理解正确,这些说法是:

  • 第一个同步作用域是用于(源)之前可以考虑进行同步的可能的命令

  • 第二个同步范围是用于(目标)之后进行同步的可能命令

唯一改变的是,当在渲染通道中使用管道屏障时,其他子通道中的命令都不会被考虑用于任何同步范围。

让我感到困惑的是它的措辞方式使我认为,甚至在渲染传递之前的先前命令也没有被考虑用于第一个同步范围。 (与之后的第二秒相同)

这些同步示例正确吗?

如果在渲染通道之外,我会执行以下操作:

1. transfer;
2. computeDispatch;
3. beginRenderPass;
...
endRenderPass;

pipelineBarrier(...);

4. computeDispatch;
5. beginRenderPass;
...
endRenderPass;

命令1、2和3将在流水线屏障中考虑之前进行同步,即位于第一同步范围内,而命令4和5将在其后考虑第二同步范围。

如果我有以下命令列表:

1. transfer;
2. computeDispatch;
3. beginRenderPass;
   3.1 next subpass;
       3.1.1 bindPipeline;
       3.1.2 bindDescriptor;
       3.1.3 bindVertexBuffer;

       pipelineBarrier(...);

       3.1.4 bindIndexBuffer;
       3.1.5 drawIndexed;
endRenderPass;

4. computeDispatch;
5. beginRenderPass;
...
endRenderPass;

命令1、2、3.1.1、3.1.2和3.1.3在第一个同步范围内,而3.1.4和3.1.5、4、5在第二个同步范围内。

最后,加粗的文字部分是说,如果我执行以下操作:

1. transfer;
2. computeDispatch;
3. beginRenderPass;
   3.1 first subpass;
       3.1.1 bindPipeline;
       3.1.2 bindDescriptors;
       3.1.3 bindVertexBuffer;
       3.1.4 draw;
   3.2 next subpass;
       3.2.1 bindPipeline;
       3.2.2 bindDescriptor;
       3.2.3 bindVertexBuffer;

       pipelineBarrier(...);

       3.2.4 bindIndexBuffer;
       3.2.5 drawIndexed;
   3.3 next subpass;
       3.3.1 bindPipeline;
       3.3.2 bindDescriptors;
       3.3.4 draw;
endRenderPass;

4. computeDispatch;
5. beginRenderPass;
...
endRenderPass;

命令1,2、3.2.1、3.2.2和3.2.3将在第一个同步范围内,而命令3.2.4、3.2.5、4和5将在第二个同步范围内正确?换句话说,在渲染过程中使用的流水线屏障的同步范围是否不考虑其他子过程?只有当前的子通行证?

1 个答案:

答案 0 :(得分:3)

  

我感到困惑的是它的措辞方式使我认为,甚至在渲染传递之前的先前命令也没有被考虑用于第一个同步作用域。

不考虑它们。 直接

子通道中的流水线屏障将在子通道中的命令之间创建依赖关系。子通道依赖关系会在子通道之间创建依赖关系。外部子通道依赖关系会在渲染过程之前/之后在子过程与命令之间创建依赖关系。

如果子通道1在子通道0完成之前无法开始执行(因此它们之间存在依赖性),则子通道1中的任何命令都可以假定子通道0已完成。这包括障碍。因此,这使得依赖项 transitive ;子通道1中的障碍物后面的东西可以假定子通道0已经完成,因为子通道1中的一切都可以进行该假设。同样,子通道中的命令(例如障碍)将取决于子通道直接或间接依赖的任何外部依赖项。

现在,由于依赖关系是基于特定阶段的,因此仅当依赖关系链中包含实际上相互依赖的阶段时,传递性才适用。