问题描述
在Vulkan中有几种处理同步的方法.这是我的理解方式:
There are several ways to handle synchronization in Vulkan. This is how I understand it:
- 围栏是GPU与CPU的同步.
- 信号量是GPU到GPU的同步,用于同步队列提交(在相同或不同的队列中).
- 事件更一般,重置并在CPU和GPU上进行检查.
- 屏障用于在命令缓冲区内进行同步.
- Fences are GPU to CPU syncs.
- Semaphores are GPU to GPU syncs, they are used to sync queuesubmissions (on the same or different queues).
- Events are more general, reset and checked on both CPU and GPU.
- Barriers are used for synchronization inside a command buffer.
就我而言,我有两个命令缓冲区.我希望第二个命令缓冲区在第一个之后执行.
In my case I have two command buffers. And I want the second command buffer to execute after the first one.
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)),
和使用围栏是一样的事情,还是应该为此使用事件或信号量?
What kind of synchronization is best for this?If I use vkQueueWaitIdle(queue)),
is that the same thing as using a fence or should I use event or semaphores for this?
如果我同时将多个命令缓冲区发送到队列:
If I send multiple commandbuffer to the queue at the same time:
std::vector<VkCommandBuffer> submitCmdBuffers = {
firstCommandBuffer,
secondCommandBuffer
};
submitInfo.commandBufferCount = submitCmdBuffers.size();
submitInfo.pCommandBuffers = submitCmdBuffers.data();
还有第一种和第二种之间同步的方法吗?
Is there still a way to synchronize between the first and the second one?
推荐答案
在这种情况下,您所需要的取决于这些命令缓冲区是什么.
For this case, what you need rather depends on what those command buffers are.
如果这些是在同一渲染过程实例中执行的辅助命令缓冲区,则不需要任何同步化.除非您正在从辅助命令缓冲区中的深度纹理中手动读取,否则不会.为什么?
If those are secondary command buffers executed within the same render pass instance, then you don't need any synchornization. Not unless you are manually reading from the depth texture in the secondary command buffer. Why?
因为第2.2.1节的 API订购保护您.渲染遍历实例中的深度测试和深度写入将始终以API顺序进行.因此,以后的命令,无论是在同一CB中还是在不同CB中,都将按顺序进行深度测试/编写.
Because section 2.2.1's API Ordering protects you. Depth testing and depth writing within a render-pass instance will always proceed in API order. So later commands, whether in the same CB or a different one, will be ordered with regard to depth testing/writing.
但是,如果需要从着色器读取深度缓冲区,或者命令缓冲区位于不同的渲染过程实例中,则需要通过事件进行显式同步.
However, if you need to read that depth buffer from the shader or your command buffers are in different render pass instances, then you need explicit synchronization via an event.
在这种情况下,vkCmdSetEvent
命令的阶段掩码应为写入深度值的阶段.这可能是EARLY_FRAGMENT_TESTS_BIT
或LATE_FRAGMENT_TESTS_BIT
.为了安全起见,请同时使用两者.但是,由于您可能要更新相同的颜色缓冲区,因此还需要COLOR_ATTACHMENT_OUTPUT_BIT
阶段.将此命令插入第一个命令缓冲区的末尾(或在完成所有深度写入之后).
In this case, the stage mask for the vkCmdSetEvent
command should be the stage that writes the depth value. This could be EARLY_FRAGMENT_TESTS_BIT
or LATE_FRAGMENT_TESTS_BIT
. To be safe, use both. However, since you're probably updating the same color buffer, you also need the COLOR_ATTACHMENT_OUTPUT_BIT
stage. Insert this command at the end of the first command buffer (or after all the depth writing is done).
对于vkCmdWaitEvent
,您要等待需要它的管道阶段.在您的情况下,这又是碎片测试和颜色附件.但是,如果着色器阶段要读取深度,则还需要在wait命令中使用该阶段.
For the vkCmdWaitEvent
, you want to wait on the pipeline stages that need it. In your case, this is again the fragment tests and color attachment. But if a shader stage is going to read the depth, you also need that stage in the wait command.
由于涉及内存,因此您的vkCmdWaitEvent
还需要对深度和颜色缓冲区使用内存依赖项.
Since memory is involved, your vkCmdWaitEvent
will also need to use a memory dependency on the depth and color buffers.
尽管如此,所有这些复杂性实际上就是为什么您应该尽可能将这些命令缓冲区放在同一个渲染通道实例中的原因.无法执行此操作的唯一原因是是否需要从着色器中的深度缓冲区读取.
Really though, all of this complexity is why you should try to put these command buffers in the same render pass instance if at all possible. The only reason you would be unable to do so is if you needed to read from the depth buffer in a shader.
这篇关于Vulkan中命令缓冲区之间的同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!