mjw*_*ach 3 synchronization memory-barriers vulkan
Vulkan 规范 (1.0.27) 表示(在第6.5 节“管道障碍”中):
pMemoryBarriers、pBufferMemoryBarriers 和 pImageMemoryBarriers 数组的每个元素指定内存依赖性的两半,如上面所定义。[...]
如果在渲染通道实例之外调用 vkCmdPipelineBarrier,则第一组命令是提交到队列并记录在命令缓冲区中的所有先前命令,第二组命令是记录在命令缓冲区中并提交到队列的所有后续命令。
(这个措辞很有趣;如果从字面上解释,它似乎是说屏障只在一个命令缓冲区内对命令进行排序,而“提交到队列”部分可能是多余的;但如果解释得更模糊一点,它似乎旨在说屏障在其命令缓冲区和队列中对命令进行排序。其他 Stack Overflow 页面向我指出了以下内容,这似乎证实了后一种解释: https: //github.com/KhronosGroup/Vulkan-Docs/issues/300)
那么我的问题是。假设您有四个命令缓冲区,分两批提交,每批提交两个,全部在一个vkQueueSubmit
命令中:
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);
Run Code Online (Sandbox Code Playgroud)
假设四个命令缓冲区中的每一个都包括屏障和一些动作命令(根据规范,这些命令是“执行动作(例如绘制/调度)的命令”)。那么,我倾向于天真地期望,障碍会将命令缓冲区视为按字母顺序提交,以便它们的第一和第二“一半”将包括(可能除其他外)以下内容:
| 屏障| 上半场| 下半场| |--------------------------------|---------------------------------------- -|----------------------------| | 缓冲区 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; 然后 A1和B0;然后 B1和C0;然后 C1和D0;然后 D1
--该表的每一行中的所有命令都没有特定的顺序执行,除非它们自己的特殊功能可能需要它。
是这样吗?或者这仅适用于在四个不同命令中提交命令缓冲区 AD 的情况vkQueueSubmit
?(或者它根本不适用?)
根据 Vulkan 规范 1.0.35 版本,命令缓冲区边界对操作之间的排序没有任何影响:
命令缓冲区边界,无论是在相同或不同批次或提交的主命令缓冲区之间,还是在主命令缓冲区和辅助命令缓冲区之间,都不会引入任何隐式排序约束。换句话说,在任何信号量或栅栏操作之间提交命令缓冲区集(可以包括执行辅助命令缓冲区)会执行记录的命令,就像它们已全部记录到单个主命令缓冲区中一样,除了当前状态被重置之外在每个边界上。显式排序约束可以用事件和管道障碍来表达。
因此,CB 是主要/次要、相同/不同批次、相同/不同提交命令并不重要。它们都表现得好像它们是一个非常大的主命令缓冲区。
因此,同步在所有这些边界之间起作用。
vkQueueSubmit
告诉我们:
批次按照它们在 pSubmits 中出现的顺序开始执行,但可能会乱序完成。
并VkSubmitInfo
在一批中说:
批量提交的命令缓冲区按照它们出现的顺序开始执行,但
pCommandBuffers
可能会乱序完成。
添加了强调。
鉴于所有这些,我们知道您如何提交这些批次并不重要。无论您是在 1 批还是 4 批中进行。vkQueueSubmit
无论您是在 1 批 4 个 CB 中进行,还是在 4 批中每批 1 个 CB 中进行。唯一重要的是这些 CB 的呈现顺序。
这就是为什么您应该vkQueueSubmit
尽可能少地使用调用。因为它不会对程序的执行产生任何影响,但可能会对性能产生重大影响。
归档时间: |
|
查看次数: |
1028 次 |
最近记录: |