Synchronization 对于屏障';目的,在单个vkQueueSubmit调用中?

Synchronization 对于屏障';目的,在单个vkQueueSubmit调用中?,synchronization,memory-barriers,vulkan,Synchronization,Memory Barriers,Vulkan,Vulkan规范(1.0.27)规定(在第6.5节管道屏障中): pMemoryBarriers、pBufferMemoryBarriers和pImageMemoryBarriers数组的每个元素都指定了内存依赖项的两部分,如上所述。[……] 如果在渲染过程实例外部调用vkCmdPipelineBarrier,则第一组命令是提交到队列并记录在命令缓冲区中的所有先前命令,第二组命令是记录在命令缓冲区中并提交到队列的所有后续命令 (这个措辞很有趣;如果按字面解释,它似乎是说屏障只在一个命令缓冲区内命

Vulkan规范(1.0.27)规定(在第6.5节管道屏障中):

pMemoryBarriers、pBufferMemoryBarriers和pImageMemoryBarriers数组的每个元素都指定了内存依赖项的两部分,如上所述。[……]

如果在渲染过程实例外部调用vkCmdPipelineBarrier,则第一组命令是提交到队列并记录在命令缓冲区中的所有先前命令,第二组命令是记录在命令缓冲区中并提交到队列的所有后续命令

(这个措辞很有趣;如果按字面解释,它似乎是说屏障只在一个命令缓冲区内命令命令,留下“提交到队列”部分可能是多余的;但如果解释得更模糊一点,它的目的似乎是说屏障在其命令缓冲区内和队列内命令。其他堆栈溢出页面向我指出以下内容,这似乎证实了后一种解释:)

那么,我的问题是。假设您有四个命令缓冲区分两批提交,一批两个,全部在一个
vkQueueSubmit
command中提交:

VkSubmitInfo nextSubmitInfo;
nextSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
nextSubmitInfo.pNext = nullptr;
nextSubmitInfo.waitSemaphoreCount = 0;
nextSubmitInfo.pWaitDstStageMask = nullptr;
nextSubmitInfo.pWaitSemaphores = nullptr;
nextSubmitInfo.signalSemaphoreCount = 0;
nextSubmitInfo.pSignalSemaphores = nullptr;

std::vector<VkCommandBuffer> commandBuffersAB{commandBufferA, commandBufferB};
std::vector<VkCommandBuffer> commandBuffersCD{commandBufferC, commandBufferD};

std::vector<VkSubmitInfo> submitInfo;

nextSubmitInfo.commandBufferCount = commandBuffersAB.size();
nextSubmitInfo.pCommandBuffers = commandBuffersAB.data();
submitInfo.emplace_back(nextSubmitInfo);

nextSubmitInfo.commandBufferCount = commandBuffersCD.size();
nextSubmitInfo.pCommandBuffers = commandBuffersCD.data();
submitInfo.emplace_back(nextSubmitInfo);

df.vkQueueSubmit(queue, submitInfo.size(), submitInfo.data(), VK_NULL_HANDLE);
VkSubmitInfo-nextSubmitInfo;
nextSubmitInfo.sType=VK\u结构\u类型\u提交\u信息;
nextSubmitInfo.pNext=nullptr;
nextSubmitInfo.waitSemaphoreCount=0;
nextSubmitInfo.pWaitDstStageMask=nullptr;
nextSubmitInfo.pWaitSemaphores=nullptr;
nextSubmitInfo.signalSemaphoreCount=0;
nextSubmitInfo.pSignalSemaphores=nullptr;
向量commandBuffersAB{commandBufferA,commandBufferB};
std::vector commandBuffersCD{commandBufferC,commandBufferD};
std::矢量子信息;
nextSubmitInfo.commandBufferCount=commandBuffersAB.size();
nextSubmitInfo.pCommandBuffers=commandBuffersAB.data();
下一步部署(下一步部署);
nextSubmitInfo.commandBufferCount=commandBuffersCD.size();
nextSubmitInfo.pCommandBuffers=commandBuffersCD.data();
下一步部署(下一步部署);
df.vkQueueSubmit(队列,submitInfo.size(),submitInfo.data(),VK_NULL_句柄);
假设四个命令缓冲区中的每一个都包括一个屏障和一些动作命令(根据规范,这些命令是“执行动作的命令(例如绘制/调度)”)。因此,我倾向于天真地认为屏障会认为命令缓冲区是按字母顺序提交的,因此它们的第一个和第二个“一半”将包括(可能包括其他内容)以下内容:

| barrier | first half | second half | |---------------------|----------------------------|----------------------------| | barrier in buffer A | A0 | A1, B0, B1, C0, C1, D0, D1 | | barrier in buffer B | A0, A1, B0 | B1, C0, C1, D0, D1 | | barrier in buffer C | A0, A1, B0, B1, C0 | C1, D0, D1 | | barrier in buffer D | A0, A1, B0, B1, C0, C1, D0 | D1 | |屏障|上半场|下半场| |---------------------|----------------------------|----------------------------| |缓冲区A | A0 | A1、B0、B1、C0、C1、D0、D1中的屏障| |缓冲器B | A0、A1、B0 | B1、C0、C1、D0、D1中的安全栅| |缓冲区C | A0、A1、B0、B1、C0 | C1、D0、D1中的屏障| |缓冲器D | A0、A1、B0、B1、C0、C1、D0 | D1中的安全栅| 其中,对于缓冲器X,X0是记录在屏障之前X中的动作命令集,X1是记录在屏障之后的动作命令集;因此,命令集的运行方式如下所示:

A0; then A1 and B0; then B1 and C0; then C1 and D0; then D1 A0;然后 A1和B0;然后 B1和C0;然后 C1和D0;然后 D1 --表中每一行的所有命令都不按特定顺序执行,除非它们自己的特殊功能可能需要


是这样吗?或者,这是否仅适用于在四个不同的
vkQueueSubmit
命令中提交命令缓冲区A-D?(或者它甚至不适用?

根据Vulkan规范1.0.35版,命令缓冲区边界对操作之间的排序没有任何影响:

相同或不同批次或提交的主命令缓冲区之间以及主命令缓冲区和辅助命令缓冲区之间的命令缓冲区边界都不会引入任何隐式排序约束。换句话说 换句话说,在任何信号量或围栏操作之间提交一组命令缓冲区(可包括执行辅助命令缓冲区)执行记录的命令,就好像它们都已记录到单个主命令缓冲区中一样,但当前状态在每个边界上重置。显式排序约束可以用事件和管道屏障表示

因此,CBs是主/辅、在相同/不同的批中还是在相同/不同的提交命令中并不重要。它们的行为都好像它们是一个非常大的主命令缓冲区

因此,同步在所有这些边界之间工作

vkQueueSubmit
告诉我们:

批处理开始执行的顺序与它们在pSubmits中出现的顺序相同,但可能会无序完成

并且
VkSubmitInfo
在一批中显示:

批处理中提交的命令缓冲区开始执行的顺序与它们在
pCommandBuffers
中出现的顺序相同,但可能会无序完成

重点补充

考虑到所有这些,我们知道如何提交这些批次并不重要。无论您是在1
vkQueueSubmit
还是4中执行此操作。无论您是在1批4个CB中进行,还是在4批各1个CB中进行。唯一重要的是这些CBs的呈现顺序


这就是为什么您应该尽可能少地使用
vkQueueSubmit
调用的原因。因为它不会影响程序的执行,但可能会影响性能。

我想我确实在某个时候看到过缓冲区开始执行的顺序,它们在批处理的命令缓冲区数组中出现,但我无法将其与我想确认的声明紧密联系起来,也就是说,这些缓冲区内的任何屏障都会表现为整个缓冲区都是有序的。特别是,一个批处理cou中可能有两个命令缓冲区