指定子过程之间的依赖关系
译者注:示例代码点击此处
当给定子过程中的操作依赖于同一渲染过程中较早的子过程中的操作结果时,我们需要指定子过程依赖性。 如果渲染过程中记录的操作与之前执行的操作之间存在依赖关系,或者在渲染过程之后执行的操作与渲染过程中执行的操作之间存在依赖关系,则也需要这样做。 也可以在单个子过程中定义依赖关系。
提示:定义子过程依赖关系与设置内存屏障类似。
怎么做...
创建一个类型为std::vector<VkSubpassDependency>的变量,命名为subpass_dependencies。 subpass_dependencies中设置每个依赖项为其成员使用以下值:
·在srcsubass的第二组(“消费”)操作(或渲染过程之前的命令的VK_SUBPASS_EXTERNAL值)之前完成(“生产”)操作的子类的索引。
·dstSubpass为子操作的索引,其操作取决于前一组命令(或渲染过程后操作的VK_SUBPASS_EXTERNAL值)
·srcStageMask为生成“消费”命令读取的结果的管道阶段集
·dstStageMask是一组依赖于“生产”命令生成的数据的管道阶段。
· srcAccessMask为“生产”命令发生的内存操作类型
·dstAccessMask为将在“消费”命令中执行的内存操作类型
·对于dependencyFlags,如果依赖项由region定义,则使用VK_DEPENDENCY_BY_REGION_BIT值 - 这意味着在执行从同一区域读取数据的操作之前,必须完成为给定内存区域生成数据的操作; 如果未指定此标志,则依赖项为全局,这意味着必须在执行“消费”命令之前生成整个映像的数据。
这个怎么运作...
指定子过程之间(或渲染过程之前或之后的子过程和命令之间)的依赖关系与设置图像存储器屏障非常相似,并且具有类似的用途。 当我们想要指定来自一个子过程(或渲染过程之后的命令)的命令取决于在另一个子过程中执行的操作的结果(或在渲染过程之前执行的命令)时,我们不需要为布局转换设置依赖关系 - 这些依赖关系是根据为渲染过程附件和子过程描述提供的信息自动执行的。 更重要的是,当我们为不同的子过程指定不同的附件布局时,但在两个子过程中,给定的附件仅用于读取,我们也不需要指定依赖项。
当我们想要在渲染过程中设置图像内存障碍时,还需要子过程依赖性。 如果没有指定所谓的“自我依赖”(源和目标子过程具有相同的索引),我们就不能这样做。 但是,如果我们为给定的子过程定义这样的依赖关系,可以在其中记录一个内存屏障。 在其他情况下,源子过程索引必须低于目标子过程索引(不包括VK_SUBPASS_EXTERNAL值)。
接下来是一个例子,我们在两个子过程之间准备一个依赖关系 - 第一个将几何绘制成颜色和深度附件,第二个使用颜色数据进行后处理(它从颜色附件中读取):
std::vector<VkSubpassDependency> subpass_dependencies
{
0,
1,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT
}
};
在第一和第二子过程(具有值0和1的索引)之间设置上述依赖性。 写入颜色附件在COLOR_ATTACHMENT_OUTPUT阶段执行。 后处理在fragment shader中完成,此阶段被定义为“消费”阶段。 当我们绘制几何图形时,执行对颜色附件的写入(具有COLOR_ATTACHMENT_WRITE值的访问掩码)。 然后将颜色附件用作输入附件,并在后处理子过程中从中读取(因此我们使用值为INPUT_ATTACHMENT_READ的访问掩码)。 由于我们不需要从图像的其他部分读取数据,我们可以通过区域指定依赖性(片段在第一个子过程中的给定坐标处存储颜色值,并且在下一个子过程相同坐标中通过片段读取相同的值)。 当我们这样做时,我们不应该假设区域大于单个像素,因为区域的大小在各种硬件平台上可能是不同的。