这是关于基于屏障的同步 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
,Image
和StagingBuffer
. 或者实际上,只要应用程序运行良好,它就没有问题。但是验证层抱怨:
带有 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]
为更好地说明我的问题。(前面的例子导致了一些混乱,抱歉。)