RenderPass 依赖和(转换)内存屏障

RenderPass Dependency and (transition) memory barrier

我遇到了一个综合问题。

假设我有一个 TRANSFER_LAYOUT 布局的图像。那样的话,内存已经可用(不可见)。

假设我更新了一个统一缓冲区(通过 vkCmdCopyBuffer)。

现在假设我有一个 renderPass(带有 "empty frameBuffer",因此没有 colorAttachment 使事情更简单),它使用 SHADER_READ_OPTIMAL 布局中的先前图像和我们刚刚更新的统一缓冲区.图像和缓冲区都在片段着色器内部使用。

以下做法是否正确?

将图像转换为 SHADER_READ_LAYOUT

srcAccess = 0; // layers will say error : it must be TRANSFER_READ
dstAccess = 0; // The visibility will be made in the renderpass dependency (hower layers tells that it should be SHADER_READ I think)
srcPipe = TOP_OF_PIPE;
dstPipe = BOTTOM_OF_PIPE;

据我理解,这里使用不同于0的访问是没有意义的,因为TOP_OF_PIPEBOTTOM_OF_PIPE不访问内存。

在 VK_EXTERNAL_SUBPASS 的 renderpass 依赖项中:

srcAccess = TRANSFER_WRITE; // for the uniformBuffer
dstAccess = SHADER_READ; // for the uniform and the image
srcPipeline = TRANSFER; // For the uniformBuffer
dstPipeline = FRAGMENT_SHADER; // They are used here

这样一来,我们确信统一缓冲区不会有任何问题:由于 renderPass,数据既可用又可见。内存也应该对图像可见(也由于依赖性)。然而,这里写的过渡是发生在"not before"底层。因为我用的是FRAGMENT_STAGE里面的图片,是不是搞错了?还是 "end of the renderPass dependency" 表现得像底层?

此代码适用于 NVIDIA 和 AMD,但我不确定它是否真的正确

要完全理解同步,必须简单地阅读规范;特别是 Execution and Memory Dependencies 理论章节。让我们根据规范中写的内容来分析您的情况。

你有(只有)三个同步命令:S1(图像过渡到TRANSFER_LAYOUT和可用性操作), S2(图像过渡到SHADER_READ_LAYOUT),以及S3(渲染传递 VK_EXTERNAL 依赖)。

您的命令缓冲区是一个有序列表,例如:[Cmds0, S1 , Cmds1, S2, Cmds2, S3, Cmds3].

For S1 假设您正确地完成了依赖项的第一部分(即 src 部分)。您只是说您将图像 提供给

你还说你没有让它可见,所以我们假设dstAccess0 dstStage 可能是 BOTTOM_OF_PIPE.

S2 没有 执行依赖性 并且它没有 内存依赖性。仅布局过渡。规范中有一个 layout transition synchronization 例外说明布局转换在 提交顺序 中完全执行(即 隐式执行依赖性 是自动的添加)。我个人不太愿意依赖它(而且我不相信驱动程序会在第一次尝试时正确实施它)。但是让我们假设它是有效的,并假设图像将被正确地转换并在 可用(而不是 可见) S1.

S3是对非附件资源的外部subpass依赖,但the spec reassures usvkCmdPipelineBarrierVkMemoryBarrier.

S3 中依赖项的第二部分(即 dst)似乎符合您的需要。


TL;DR,到目前为止一切顺利。


S3 中依赖项的第一部分(即 dst)确实是有问题的部分。

非附件资源没有自动布局转换,所以我们不能像上面那样依赖那个拐杖。

一组命令A3是renderpass之前的所有命令。

同步范围A3S只是操作[= =22=] 管道阶段或任何逻辑上更早的阶段(即 TOP_OF_PIPE 到指定的 STAGE_TRANSFER)。

执行依赖A3'之间建立B3'。上面我们同意 B3' 一半的依赖关系是正确的。 A3' 一半是 A3 的交集和 A3S.

S2中的布局过渡是在srcPipe = TOP_OF_PIPEdstPipe = BOTTOM_OF_PIPE之间进行的,所以基本上可以任何地方。它可以晚于 BOTTOM_OF_PIPE(准确地说,在 S2[=156= 之后记录的命令发生在 BOTTOM_OF_PIPE 之前] 被执行)。 所以布局转换是 A3 的一部分,但不能保证它是 A 的一部分3S;所以 not 可以保证转换是交集 A3'.[=39 的一部分=]

这意味着无法保证到 SHADER_READ_LAYOUT 的布局转换发生在 STAGE_FRAGMENT_SHADER 中第一个子通道中的图像读取之前。

也没有正确的内存依赖性,因为它是根据A3'[=156定义的=] 也是。

编辑:不知何故错过了这个,这可能是问题所在:

Or is the "end of the renderPass dependency" behave like a bottom stage?

渲染过程的开始和结束没有任何表现。它只影响提交顺序。在存在 VK_EXTERNAL 依赖项的情况下,仅适用(当然还有任何其他先前的显式同步命令)。在 VkSubpassDependency 的有效使用部分的规范中描述了没有显式 VK_EXTERNAL 依赖的情况(基本上所有 available before TOP_OF_PIPE 的内存是使 整个第一个子通道可见以供附件使用)。