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

时间:2017-09-08 11:06:32

标签: c++ vulkan

我正面临一个全面的问题。

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

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

现在假设我有一个renderPass(带有一个“空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,数据都可用且可见。内存也应该对图像可见(也要归功于依赖性)。但是,转换是在这里写到“不在之前”的最后阶段。由于我在FRAGMENT_STAGE中使用图像,这是一个错误吗?或者“renderPass依赖的结尾”表现得像一个底层阶段?

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

1 个答案:

答案 0 :(得分:2)

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

您有(仅)三个同步命令: S 1 (图像过渡到TRANSFER_LAYOUT和可用性操作), S 2 (图片过渡到SHADER_READ_LAYOUT)和 S 3 (渲染传递VK_EXTERNAL依赖关系)。

您的命令缓冲区是一个有序列表,如:[ Cmds 0 S 1 Cmds 1 S 2 Cmds 2 S 3 Cmds 3 ]。

对于 S 1 ,我们假设你正确地完成了依赖关系的第一部分(即src部分)。您只是说您从中获取了图像。

您还说过可见,所以让我们假设dstAccess0dstStage可能是BOTTOM_OF_PIPE

S 2 没有执行依赖,并且它没有内存依赖。只有布局过渡。规范中有一个layout transition synchronization异常,表示布局转换是在提交顺序中完整执行的(即隐式执行依赖是自动添加的)。我个人不愿意依赖它(我不相信司机在第一次尝试时正确实现它)。但我们假设它是有效的,并假设图像将被正确转换并在 S (而不是可见 > 1

S 3 是非附件资源的外部子通道依赖关系,但the spec reassures usvkCmdPipelineBarrier的{​​{1}}没有区别{ {1}}。

S 3 中依赖关系的第二部分(即VkMemoryBarrier)似乎正确满足您的需求。

<小时/> TL; DR,到目前为止一直很好。

S 3 中依赖关系的第一部分(即dst)确实会有问题。

非附件资源没有自动布局转换,因此我们不能依赖上面的拐杖。

命令集 A 3 是renderpass之前的所有命令。

同步范围 3S 只是那些位于dst pipline阶段或任何逻辑上较早阶段的操作 (即srcStage到指定的TOP_OF_PIPE)。

执行依赖是在 A 3 ' B 3 '。上面我们同意 B 3 '一半的依赖是正确的。 A 3 '一半是 A 3 A 3S

S 2 中的布局转换是在STAGE_TRANSFERsrcPipe = TOP_OF_PIPE之间进行的,所以基本上可以在任何地方。它可以在dstPipe = BOTTOM_OF_PIPE中进行(确切地说,在执行 S 2 之后记录的BOTTOM_OF_PIPE命令之前发生)。 因此布局转换是 A 3 的一部分,但不能保证它是 A 3S 的一部分;所以要保证过渡是交叉点 A 3 '的一部分。

这意味着无法保证在BOTTOM_OF_PIPE的第一个子通道中的图像读取之前,布局过渡到SHADER_READ_LAYOUT

没有正确的内存依赖,因为它也是根据 A 3 '定义的。

编辑:不知怎的错过了,这可能是问题:

  

或者“renderPass依赖关系的结尾”表现得像一个底层阶段?

渲染过程的开始和结束不像任何东西。它只会影响提交订单。存在STAGE_FRAGMENT_SHADER依赖性时仅应用(当然还有任何其他先前的显式同步命令)。如果没有明确的VK_EXTERNAL依赖关系,那么VkSubpassDependency的有效用法部分的规范中也会有所描述(基本上所有可用的内存VK_EXTERNAL之前生成可见整个第一个子通道以供附件使用。)