Если вы хотите воспользоваться преимуществами асинхронного выполнения графического процессора, вам нужно, чтобы процессор избегал зависания для операций графического процессора.Так что никогда не ждите на заборе партии, которая была только что выпущена .То же самое относится и к памяти: вы никогда не должны захотеть записывать в память, которая читается с помощью операции GPU, которую вы только что отправили.
Вы должны по крайней мере дважды буферизовать вещи.Если вы меняете данные вершин в каждом кадре, вам следует выделить достаточно памяти для хранения двух копий этих данных.Нет необходимости делать многократные выделения или даже делать несколько VkBuffer
с (просто увеличьте выделение и буферы, затем выберите область хранения, которую вы будете использовать при ее привязке).Пока одна область памяти читается командами графического процессора, вы записываете в другую.
Каждая отправляемая партия читает из определенной памяти.Таким образом, ограничение для этой партии будет установлено, когда графический процессор закончит чтение из этой памяти.Поэтому, если вы хотите выполнять запись в память из ЦП, вы не сможете начать этот процесс до тех пор, пока не будет задан предел, представляющий операцию чтения из GPU для этого чтения из памяти.
Но поскольку вы выполняете двойную буферизацию, как это,забор для памяти, в которую вы собираетесь записать, , а не забор для пакета, который вы отправили в последнем кадре.Это партия, которую вы передали в кадр до .Поскольку прошло некоторое время с тех пор, как графический процессор получил эту операцию, гораздо менее вероятно, что ЦПУ действительно придется ждать.То есть забор, надо надеяться, уже установлен.
Теперь вы не должны делать буквальный vkWaitForFences
на этом заборе.Вы должны проверить, установлено ли оно, а если нет, пойти и сделать что-то еще полезное со своим временем.Но если у вас нет ничего полезного, чем вы могли бы заниматься, тогда, вероятно, все в порядке (вместо того, чтобы сидеть и крутиться на тесте).
Как только забор установлен, вы знаете, что можете свободно записывать в память.
Как узнать, что память, которую я записал с помощью memcpy, закончила отправку на устройство до того, как она будет прочитана проходом рендеринга?
Вы знаете, потому что память связна.Вот что VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
означает в этом контексте: изменения хоста в памяти устройства видны для графического процессора без необходимости явных операций видимости, и наоборот.
Ну ... почти.
Если вы не хотите использовать какую-либо синхронизацию, вы должны вызвать vkQueueSubmit
для пакета чтения после того, как вы закончили модифицировать память на ЦП.Если их вызывают в неправильном порядке, вам понадобится барьер памяти.Например, у вас может быть некоторая часть пакетного ожидания для события, установленного хостом (через vkSetEvent
), который сообщает графическому процессору, когда вы закончили писать.И, следовательно, вы можете отправить этот пакет перед выполнением записи в память.Но в этом случае вызов vkCmdWaitEvents
должен включать маску этапа источника HOST
(так как именно он устанавливает событие), и он должен иметь барьер памяти, флаг доступа к источнику которого также включает HOST_WRITE
(так как это пишет ктов память).
Но в большинстве случаев проще просто записать в память перед отправкой пакета.Таким образом, вам не нужно использовать синхронизацию хоста / события.