Vulkan Device - Host - Синхронизация устройства с VkEvent - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь синхронизировать этап хоста в моем конвейере, где я в основном редактирую некоторые данные на хосте во время выполнения буфера команд на устройстве. После прочтения спецификации, я думаю, что я делаю правильную синхронизацию, выполнение / зависимости от памяти и операции доступности / видимости, но это не работает ни на NV, ни на AMD. Это вообще возможно? Если так, что я делаю неправильно с точки зрения синхронизации?

В итоге я делаю следующее:

  • [D] Буфер устройства (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) копируется на видимый и связный хост (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT).
  • [D] Первое событие установлено.
  • [D] Ожидается второе событие.
  • [H] Тем временем хост ожидает первого события.
  • [H] После того, как он был установлен, он увеличивает числа в видимом буфере хоста.
  • [H] Затем он устанавливает второе событие.
  • [D] Затем устройство продолжает копировать видимый буфер хоста обратно в локальный буфер устройства.

Что происходит?

В NV первая часть работает, правильные данные поступают на стороне хоста, но измененные данные никогда не поступают на стороне устройства. На AMD даже первая часть не работает, и я уже не получаю данные на хосте.

Запись в буфер команд:

// ...
VkMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.srcAccessMask = ...;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
vkCmdPipelineBarrier(command_buffer, ..., VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr);

copyWholeBuffer(command_buffer, host_buffer, device_buffer);

barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr);

vkCmdSetEvent(command_buffer, device_to_host_sync_event, VK_PIPELINE_STAGE_TRANSFER_BIT);

barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
vkCmdWaitEvents(command_buffer, 1, &host_to_device_sync_event, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 1, &barrier, 0, nullptr, 0, nullptr);

copyWholeBuffer(command_buffer, device_buffer, host_buffer);

barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = ...;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, ..., 0, 1, &barrier, 0, nullptr, 0, nullptr);
// ...

Исполнение

vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);

while(vkGetEventStatus(device, device_to_host_sync_event) != VK_EVENT_SET)
    std::this_thread::sleep_for(std::chrono::microseconds(10));

void* data;

vkMapMemory(device, host_buffer, 0, BUFFER_SIZE, 0, &data);

// read and write parts of the memory

vkUnmapMemory(device, host_buffer);

vkSetEvent(device, host_to_device_sync_event);

vkDeviceWaitIdle(device);

Я загрузил рабочий пример: https://gist.github.com/neXyon/859b2e52bac9a5a56b804d8a9d5fa4a5

Интересные биты начинаются со строки 292! Посмотрите, работает ли он у вас?

1 Ответ

0 голосов
/ 01 августа 2018

Я открыл вопрос на github: https://github.com/KhronosGroup/Vulkan-Docs/issues/755

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

...