2016-05-27 2 views
16

Существует несколько способов обработки синхронизации в Vulkan. Вот как я это понимаю:Синхронизация между буферами команд в Vulkan

  • Заборы - это графические процессоры для синхронизации процессора.
  • Семафоры являются графическими процессорами GPU, они используются для синхронизации очередей представлений (в тех же или разных очередях).
  • События более общие, сбрасываются и проверяются как на процессоре, так и на графическом процессоре.
  • Барьеры используются для синхронизации внутри командного буфера.

В моем случае у меня есть два командных буфера. И я хочу, чтобы второй буфер команды выполнялся после первого.

submitInfo.pCommandBuffers = &firstCommandBuffer; 
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 

// wait for first command buffer to finish 
submitInfo.pCommandBuffers = &secondCommandBuffer; 
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 

Какая синхронизация лучше всего подходит для этого? Если я использую vkQueueWaitIdle(queue)),, это то же самое, что использовать забор, или я должен использовать для этого события или семафоры?

Если я пошлю несколько commandbuffer в очереди в то же время:

std::vector<VkCommandBuffer> submitCmdBuffers = { 
     firstCommandBuffer, 
     secondCommandBuffer 
    }; 
    submitInfo.commandBufferCount = submitCmdBuffers.size(); 
    submitInfo.pCommandBuffers = submitCmdBuffers.data(); 

Есть еще способ синхронизации между первой и второй?

+2

«* И я хочу, чтобы второй командный буфер выполнялся после первого. *« Сколько вы «хотите», чтобы это произошло? То есть, что является вторым буфером команд, так что это так важно, чтобы первый выполнил * завершенное выполнение до начала второго? –

+1

Первый буфер команд - это объект рендеринга с включенным тестом глубины. Второй командный буфер - это рендеринг контуров сеток с выключенным тестом глубины. Потому что он должен быть поверх других объектов. – hidayat

+0

Если вы делаете одно представление. затем используйте vkCmdSetEvent в своем первом командном буфере и vkCmdWaitEvents во второй и сохраните маски src и dst, насколько это возможно. –

ответ

11

Первый буфер команд - это объект рендеринга с включенным тестом на глубину. Второй командный буфер - это рендеринг контуров сеток с выключенным тестом глубины. Потому что он должен быть поверх других объектов.

Для этого случая то, что вам нужно, зависит от того, что такое буферы команд.

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

Поскольку раздел 2.2.1's API Ordering защищает вас. Глубокое тестирование и запись глубины в экземпляре визуализации будут всегда действовать в порядке API. Поэтому более поздние команды, будь то в одном CB или другом, будут упорядочены в отношении глубинного тестирования/записи.

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

В этом случае маска сцены для команды vkCmdSetEvent должна быть этапом, записывающим значение глубины.Это может быть EARLY_FRAGMENT_TESTS_BIT или LATE_FRAGMENT_TESTS_BIT. Чтобы быть в безопасности, используйте оба варианта. Однако, поскольку вы, вероятно, обновляете один и тот же буфер цветов, вам также нужен этап COLOR_ATTACHMENT_OUTPUT_BIT. Вставьте эту команду в конец первого командного буфера (или после завершения записи глубины).

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

Поскольку память задействована, ваш vkCmdWaitEvent также должен будет использовать зависимость от памяти на глубинах и цветовых буферах.

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

+0

ваши знания впечатляют :), «Если это вторичные буферы команд», почему имеет значение, являются ли они первичными или вторичными буферами команд, если они находятся в одном и том же сеансе рендеринга? – hidayat

+1

@hidayat: потому что вы не можете иметь два первичных командных буфера в одном экземпляре экземпляра визуализации. 'vkCmdEndCommandBuffer' * не может быть вызван, пока экземпляр renderpass активен. Только с дополнительными буферами команд возможно, чтобы они оба выдавали команды внутри одного экземпляра renderpass. Они делают это, наследуя экземпляр renderpass первичного командного буфера, который они выполняют внутри. –

4

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

Семафоры - это еще один способ синхронизации выполнения командного буфера, но они работают только с представлением очереди, поэтому они более тяжелые, чем события.

+0

Не мог ли барьер работать? Я продолжаю читать здесь, что барьеры работают через границы буферного буфера: http://stackoverflow.com/a/36602598/1364776 Не может ли это примениться? Или дело только в том, что события более легкие, чем барьеры? – mjwach

Смежные вопросы