计算写入和传输同步

compute writes and transfer sync

我有一个写入存储缓冲区的计算着色器。一旦计算 队列变得空闲,存储缓冲区被转移到图像。管道障碍 传输前后注意布局转换。

相关代码如下:

vkCmdDispatch(...);
...
vkQueueWaitIdle(...);
...

...

VkImageMemoryBarrier i = {};

i.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
i.srcAccessMask = 0;
i.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
i.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
i.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
...
i.image = texture;

i.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
i.subresourceRange....

vkCmdPipelineBarrier(
        commandbuffer,
        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
        VK_PIPELINE_STAGE_TRANSFER_BIT,
        0,0,nullptr,0,nullptr,1,&i
);

...

vkCmdCopyBufferToImage(...);

...

i.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
i.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
i.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
i.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

vkCmdPipelineBarrier(
        commandbuffer,
        VK_PIPELINE_STAGE_TRANSFER_BIT,
        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
        0,0,nullptr,0,nullptr,1,&i
);

图像随后用于后续渲染过程,一切正常。

但是,我有点担心我可能遇到了未定义的行为, 因为即使等待计算队列也会保证之间的执行顺序 缓冲区写入和缓冲区传输,没有明确的屏障来确保写入 来自计算着色器的缓冲区传输实际上可用且可见。

我是否有一个隐式缓冲区或内存屏障(至少在这种情况下) 在规范(截至今天的 1.1.123)或任何其他类型的机制中找不到, 这样上面的代码是正确的并且计算着色器 wites 总是 可用于缓冲区传输?

如果没有,我认为应该 VkBufferMemoryBarrier 正确吗? 在第一个布局转换管道屏障之前?

我有点困惑,因为阅读规格,我发现:

"vkCmdPipelineBarrier是同步命令,插入依赖 在提交到同一队列的命令之间,或在同一子通道中的命令之间。"

但在这里我需要从两个不同的队列中插入一个内存依赖项,并且 两条不同的管道,所以我不太确定哪条管道必须有 屏障.. 如果一开始就需要屏障。

您正在考虑错误的同步工具。对于 个队列之间的同步,有 VkSemaphore.

在这种情况下还有其他并发症。队列族的概念——资源所有权。在 VK_SHARING_MODE_EXCLUSIVE 和不同队列系列的情况下,您必须按照规范的 Queue Family Ownership Transfer 部分中的说明进行操作。 IE。使用特殊的释放和获取屏障+信号量。

否则,只需要信号量,如 Semaphore Signaling and Semaphore Waiting & Unsignaling 部分所述:

The first access scope includes all memory access performed by the device.

The second access scope includes all memory access performed by the device.