如何同步统一缓冲区更新?

时间:2018-02-20 21:32:56

标签: vulkan

我有许多统一缓冲区 - 每个帧缓冲区一个缓冲区。我保证在围栏的帮助下,cpu上的更新是安全的,即当我memcpy时我确定缓冲区没有被使用。更新后,我正在冲洗记忆。

现在,如果我理解正确,我需要为gpu提供新数据 - 为此,我需要使用障碍。这就是我现在正在做的事情:

VkBufferMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.pNext = nullptr;
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = buffer;
barrier.offset = offset;
barrier.size = size;

vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);

嗯,实际上在我的情况下,一切都没有障碍。我需要它吗?

如果我分别将barrier.dstAccessMaskdstStageMask更改为VK_ACCESS_TRANSFER_READ_BITVK_PIPELINE_STAGE_TRANSFER_BIT,则所有内容都可以正常运行,图层不会抱怨。什么是更好的选择,为什么?

如果我尝试在vkCmdBeginRenderPass之后设置障碍,则该图层会抱怨。所以我在vkBeginCommandBuffervkCmdBeginRenderPass之间移动了所有障碍。这有多正确?

1 个答案:

答案 0 :(得分:2)

  

嗯,实际上在我的情况下,一切都没有障碍。

规范是否说你需要它?然后你需要它。

在处理Vulkan时,你不应该采取"一切似乎都有效"这表明你已经做好了一切。

  

更好的选择是什么?为什么?

更好的选择"是正确的。 GPU没有对此内存进行传输操作;它将其作为统一数据读取。因此,您在屏障中指定的操作必须与此匹配。

图层并不抱怨,因为验证层或多或少都不可能知道你何时写入内存。因此,他们无法判断您是否正确构建了一个屏障,以便为GPU提供此类写入。

  

如果我尝试在vkCmdBeginRenderPass之后设置障碍,则该图层会抱怨。

渲染过程中的障碍必须位于具有自依赖性的子区域内。屏障本身必须与子通道自我依赖相匹配。

基本上,你所谈论的那种障碍必须在渲染过程之前发生。

话虽如此,仅仅调用vkQueueSubmit会自动在vkQueueSubmit之前发出的(正确刷新的)主机写入与在submit命令中从命令缓冲区中使用这些写入(和当然,以后提交操作中的命令。)

所以你不应该需要这样的障碍,只要你能确保你在从它们读取的vkQueueSubmit之前完成了你的写作(以及任何需要的刷新)。如果你不能保证这一点,你可能应该使用vkCmdWaitEvents屏障来防止在完成写入(和刷新)之前尝试阅读。