Vulkan设备-主机-与VkEvent的设备同步

时间:2018-07-02 08:43:31

标签: vulkan

我正在尝试将主机阶段同步到我的管道中,在设备上执行命令缓冲区期间,我基本上在该阶段编辑主机上的一些数据。通过阅读规范,我认为我正在执行正确的同步,执行/内存依赖关系和可用性/可见性操作,但是它既不适用于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 :(得分:0)

我在github上发布了一个问题:https://github.com/KhronosGroup/Vulkan-Docs/issues/755

经过一番讨论,得出的结论是,事件无法实现设备到主机的同步,必须使用隔离栅。