0

这是关于基于屏障的同步 wrt 命令缓冲区提交和清理命令缓冲区所需的资源(如使用的缓冲区和图像)的具体问题。

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

我执行以下操作:

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-CmdBfr,ImageStagingBuffer. 或者实际上,只要应用程序运行良好,它就没有问题。但是验证层抱怨:

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

还会出现更多消息,例如:

Vk-callback with Id[0|VUID-vkDestroyBuffer-buffer-00922] 和 Message[Cannot free VkBuffer 0xe6bc0400000000a1[] 正在被命令缓冲区使用。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_READ的完整周期,我认为这必须在第 4 帧中给出。Fence[0]

我的第一个问题是:我对这个假设是否正确?而且,我的这种方法可以吗?

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

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

更新:

全部Semaphore[i]替换Fence[i]为更好地说明我的问题。(前面的例子导致了一些混乱,抱歉。)

4

1 回答 1

1

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

仅当规范说明命令缓冲区已完成执行时,才认为命令缓冲区已完成执行。并且该规范仅规定了两种机制来表示 aa CB 何时完成:

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

  2. 它是信号量的一部分的批次。

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

于 2020-03-25T19:41:57.333 回答