Редко упоминаемая функция Vulkan "vkCmdUpdateBuffer ()", для чего она используется? - PullRequest
0 голосов
/ 13 февраля 2019

Кажется, это простой вопрос API Vulkan, но я действительно не могу найти ответ после поиска в Интернете.Я заметил, что есть функция Vulkan:

void vkCmdUpdateBuffer(
    VkCommandBuffer                             commandBuffer,
    VkBuffer                                    dstBuffer,
    VkDeviceSize                                dstOffset,
    VkDeviceSize                                dataSize,
    const void*                                 pData);

На первый взгляд, я думаю, что она может быть использована для записи буфера команд, так как он имеет префикс vkCmd в своем имени, но в документе говорится, что

vkCmdUpdateBuffer разрешен только вне прохода рендеринга.Эта команда рассматривается как операция «передача» для целей барьеров синхронизации.

Поэтому я начинаю думать, что это удобная функция, которая оборачивает операцию передачи данных в буфер, например, используя memcpy() для копированияданные от хоста к устройству.

Тогда мой вопрос: почему НЕ существует ни одного образца / учебника Vulkan (я их все искал), использующих vkCmdUpdateBuffer() вместо того, чтобы вручную копировать данные с помощью memcpy(),Я правильно понял?

1 Ответ

0 голосов
/ 13 февраля 2019

Все vkCmd* функции генерируют команды в командном буфере.Этот не исключение.Это команда переноса, и, как и большинство команд переноса, вы не можете выполнять их в течение прохода рендеринга.Но есть много команд, генерирующих буфер команд, которые не работают на проходах рендеринга.

Обычно операции передачи памяти Vulkan происходят только между памятью устройства.Типичный механизм для размещения хостом чего-либо в памяти устройства - запись в отображенный указатель.Но по определению это требует, чтобы целевая память была отображаемой.Поэтому, если вы хотите записать что-то в не отображаемую память, вы должны скопировать это в отображаемую память, а затем выполнить операцию переноса между отображаемой памятью в не отображаемую память с помощью функций vkCmdCopy*.

ИЭто нормально, если вы делаете несколько переводов одновременно.Вы можете скопировать кучу содержимого в отображенную память, а затем отправить пакет, содержащий все операции копирования, чтобы скопировать данные в соответствующие места.

Но иногда вы просто обновляете небольшой фрагмент памяти устройства,Если это невозможно сопоставить, тогда нужно проделать большую работу, чтобы передать несколько килобайт данных в графический процессор.В этом случае vkCmdUpdateBuffer может быть лучшим выбором, поскольку он может «напрямую» копировать память ЦП в любую память устройства.

Я говорю «напрямую», потому что это явно не то, что он делает.Он действительно делает то же самое, что и вы, за исключением того, что он делает это в буфере команд.Вы бы скопировали данные вашего ЦП в сопоставляемую память графического процессора, а затем создали команду, которая копирует из этой сопоставляемой памяти в не сопоставляемую память.

vkCmdUpdateBuffer делает то же самое.Он копирует данные из указателя / размера, указанного вами, в сопоставляемую память (которая обеспечивается самим буфером команд . Именно поэтому он имеет верхний предел 64 КБ).Эта копия происходит немедленно , точно так же, как если бы вы сделали memcpy, поэтому, когда эта функция вернется, вы можете делать все, что захотите, с указателем, который вы ей дали.Затем он создает команду в буфере команд, которая копирует из сопоставляемой памяти в буфере команд в область памяти назначения.

Документация для этой функции явно дает предупреждения об использовании ее для большихпереводы.То есть говорит вам не делать этого .Это для быстрых, маленьких , однократных обновлений неиспользуемой памяти.Ничего более.

Это одна из причин, по которой учебники не говорят об этом: это особая функция, которую многие начинающие пользователи попытаются использовать, потому что она проще, чем явный код.Но в большинстве случаев они не должны его использовать.

...