I have three compute kernels that have to run in succession, synchronized so that the previous kernel finishes before the next kernel starts.
This is because a previous kernel writes a buffer that is used by the next kernel.
This may be a mistake, but what I have now:
I tried adding VkMemoryBarrier
and VkBufferMemoryBarrier
, but I don't think I have synchronized them, because they were placed on a pipeline, and I think not between pipelines? I added them with vkCmdPipelineBarrier
What would be a good way to make sure three compute kernels run in succession, with the caches flushed between them?
This is how I create a memory barrier:
static void add_memory_barrier(VkDeviceMemory mem, VkCommandBuffer cmdBuf, VkDeviceSize sz)
{
const VkMemoryBarrier b =
{
VK_STRUCTURE_TYPE_MEMORY_BARRIER,
0,
VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT,
};
vkCmdPipelineBarrier
(
cmdBuf,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, // dependency flags
1, // num memory barriers
&b,
0, // num buffer memory barriers
0,
0, // num image memory barriers
0
);
}
https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ https://www.khronos.org/blog/understanding-vulkan-synchronization
I think that the first example in the first link pretty much answers your question. Your approach is probably working as long as you specify the correct Stage and Access masks, but you didn't say which ones you are using.
Barriers also don't have the notion of being "on a pipeline" or "between pipelines". A pipeline bind just says what pipeline should be in effect for the next dispatch and doesn't interact with a barrier.
So if you put in a command buffer:
Bind A, Dispatch A, Barrier, Bind B, Dispatch B
this should be the same as:
Bind A, Dispatch A, Bind B, Barrier, Dispatch B
The bind of B really doesn't take effect until the dispatch of B and that won't happen until the barrier is satisfied.