【问题标题】:Cleanup of command buffers (and resources) after barrier-based synchronization; but the validation layers still complain基于屏障的同步后清理命令缓冲区(和资源);但验证层仍然抱怨
【发布时间】:2020-03-24 21:33:51
【问题描述】:

这是一个关于基于障碍的同步 w.r.t 的具体问题。命令缓冲区提交和清理命令缓冲区所需的资源(如使用的缓冲区和图像)。

让我们假设,一切都在一个队列中,并且有三帧在飞行中。

我执行以下操作:

Create Render-CmdBfr[0..2], Fence[0..2]
...
Create StagingBuffer
Create Image
Create Init-CmdBfr
Record `copy StagingBuffer to Image` into Init-CmdBuffer
Record `barrier ALL_COMMANDS ALL_COMMANDS MEMORY_WRITE MEMORY_READ` into Init-CmdBuffer
Submit Init-CmdBuffer without any semaphore or fence
...
// Frame #1
Submit Render-CmdBfr[0] -> signal Fence[0]
// Frame #2
Submit Render-CmdBfr[1] -> signal Fence[1]
// Frame #3
Submit Render-CmdBfr[2] -> signal Fence[2] 
// Frame #4
Wait for Fence[0] -> submit Render-CmdBfr[0] -> signal Fence[0] 
Delete Init-CmdBfr
Delete Image
Delete StagingBuffer
// Frame #5
Wait for Fence[1] -> submit Render-CmdBfr[1] -> signal Fence[1]     
// Frame #6
Wait for Fence[2] -> submit Render-CmdBfr[2] -> signal Fence[2] 
... continue forever ...

有问题的部分是我删除了Init-CmdBfrImageStagingBuffer。或者实际上,只要应用程序运行良好,它就没有问题。但是验证层抱怨:

带有 Id[0|VUID-vkFreeCommandBuffers-pCommandBuffers-00047] 的 Vk-callback 和 Message[尝试释放正在使用的 VkCommandBuffer 0x20e61cff060[]。 Vulkan 规范规定:pCommandBuffers 的所有元素不得处于挂起状态(https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkFreeCommandBuffers-pCommandBuffers-00047)]

还会出现更多消息,例如像下面这样:

带有 Id[0|VUID-vkDestroyBuffer-buffer-00922] 和 Message[Cannot free VkBuffer 0xe6bc0400000000a1[] 的 Vk-callback 正被命令缓冲区使用。 Vulkan 规范规定:所有直接或通过 VkBufferView 引用缓冲区的提交命令必须已完成执行 (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyBuffer-buffer-00922)]

规范规定,命令缓冲区只有在离开“待处理”状态时才能被删除。通过我的barrier ALL_COMMANDS ALL_COMMANDS MEMORY_WRITE MEMORY_READFence[0] 信号和等待的完整周期,我认为这必须在第4 帧中给出。

我的第一个问题是:我对这个假设是否正确?还有,我的这种做法好吗?

我的第二个问题是:如果我是对的并且我的方法没问题,我该如何防止验证层抱怨?

我认为,验证层只是不知道障碍并抱怨,因为可能是我没有创建障碍。事实上,当我在Init-CmdBfr(即Submit Init-CmdBuffer and signal Init-Semaphore)的提交中添加信号量时,验证层不再抱怨了。但在我看来,信号量实际上是不必要的。没有它可以吗?

更新:

将所有Semaphore[i] 替换为Fence[i] 以更好地说明我的问题。 (前面的例子造成了一些混乱,抱歉。)

【问题讨论】:

  • "在没有任何信号量或栅栏的情况下提交 Init-CmdBuffer" 你怎么知道什么时候完成?
  • 通过使用屏障,我知道Init-CmdBfr 的所有命令必须在Render-CmdBfr[0] 开始执行之前完成(在同一个队列上)。我知道Render-CmdBfr[0] 何时完成,因为它发出信号量的信号。至少我认为它是这样工作的,但我可能是错的。
  • "通过使用屏障" 屏障与后续命令同步,而不是与队列外进程同步。这就是信号量的用途。
  • 是的,但在我上面描述的示例中,它不是一个完全有效的隐式同步依赖项吗? Init-CmdBfr -> 屏障 -> Render-CmdBfr[0] -> 信号量 -> 安全删除 Init-CmdBfr
  • 我的意思是,障碍是没有意义的。关于销毁命令缓冲区的有效性,它没有提供任何有用的同步。

标签: vulkan validation-layers


【解决方案1】:

障碍定义了命令的执行顺序。它们对命令 buffers 的完成状态没有影响。在您的示例中,即使 Render-CmdBfr 已开始执行,Init-CmdBfr 仍可能处于“待处理”状态。障碍不会改变这一点。

只有当规范说明它已经完成时,一个命令缓冲区才被认为已经完成。并且规范仅规定了两种机制来表示 CB 何时完成:

  1. 作为栅栏信号的一部分提交的队列提交操作

  2. 它所属的批次发出信号量。

那是。如果您需要知道 CB 是否已完成,那么您必须使用这两种机制之一来检测这一点。并且(二进制)信号量不能被 CPU 等待,除非你将它们转换成互斥体或其他东西。所以你的选择是时间线信号量或栅栏。

【讨论】:

  • ad 1:我认为你可以通过提交顺序,或者通过交换链图像推断CB已经执行完毕。但是,是的,在某些时候必须有一个等待等待的栅栏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 2023-03-16
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多