В спецификации Vulkan (1.0.27) говорится (в разделе 6.5. Трубопроводные барьеры):
Каждый элемент массивов pMemoryBarriers, pBufferMemoryBarriers и pImageMemoryBarriers определяет две половины зависимости от памяти, как определено выше. [...]
Если vkCmdPipelineBarrier вызывается вне экземпляра прохода рендеринга, то первый набор команд - это все предыдущие команды, отправленные в очередь и записанные в буфер команд, а второй набор команд - все последующие команды, записанные в буфере команд и отправленные в очередь. .
(Формулировка забавная; если интерпретировать буквально, кажется, что барьер упорядочивает команды только в одном командном буфере, оставляя, возможно, переданные в очередь части избыточными; но если интерпретировать немного более расплывчато, похоже, что цель состоит в том, чтобы сказать, что команды барьерных заказов как в своем буфере команд, так и в очереди. Другие страницы переполнения стека указывают мне на следующее, которое, кажется, подтверждает последнюю интерпретацию: 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);
Предположим, что каждый из четырех буферов команд включает в себя барьер и несколько команд действий (которые в соответствии со спецификацией являются командами, выполняющими действия (например, рисование / отправка)). Поэтому я склонен наивно ожидать, что барьеры будут воспринимать командные буферы как отправленные в алфавитном порядке, так что их первая и вторая половины будут включать (возможно, среди прочего) следующее:
| 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 |
где для буфера X, X0 - это набор команд действия, записанных в X до барьера, а X1 - это набор, записанный после барьера; и что в результате наборы команд будут выглядеть следующим образом:
A0; then A1 and B0; then B1 and C0; then C1 and D0; then D1
- при этом все команды в каждой строке этой таблицы выполняются в произвольном порядке, за исключением тех случаев, когда это может потребоваться их собственным особенностям.
Так ли это? Или это применимо только тогда, когда командные буферы A – D представлены четырьмя разными vkQueueSubmit
командами? (Или тогда это вообще не применимо?)