title: Vulkan - synchronising access to a single Buffer
body: <p><strong>What is the best way to synchronise access to a single Buffer in Vulkan when multiple frames are in flight?</strong></p>
  <p>I'm new to Vulkan, but I'm finding synchronisation the hardest part to get my head around. I've looked through the Vulkan spec, the synchronisation examples (<a href="https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples" rel="nofollow noreferrer">https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples</a>), the Vulkan Tutorial (<a href="https://vulkan-tutorial.com/" rel="nofollow noreferrer">https://vulkan-tutorial.com/</a>), as well as a bunch of Stack Overflow posts. I'm still not sure I'm really 'getting it' though.</p>
  <p>To aid my learning, I'm trying to code the following:</p>
  <ul>
  <li>Have multiple frames in-flight, as described in the Vulkan tutorial (<a href="https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Rendering_and_presentation#page_Frames_in_flight" rel="nofollow noreferrer">https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Rendering_and_presentation#page_Frames_in_flight</a>).</li>
  <li>Have the vertex shader read from a single Storage Buffer.</li>
  <li>Update part of the Storage Buffer with fresh data every frame via a host-local and host-coherent 'Staging Buffer'.</li>
  <li>There will be multiple Staging Buffers - one for each frame in-flight.</li>
  </ul>
  <p>I think the command buffer for frame N (0 &lt;= N &lt; Maximum number of frames in flight) should look something like this:</p>
  <pre><code>// Many parameters omitted for brevity
  vkCmdCopyBuffer(commandBuffer[N], stagingBuffer[N], storageBuffer, ...);
  
  VkMemoryBarrier barrier = {0};
  barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  
  vkCmdPipelineBarrier(
      commandBuffer[N],
      VK_PIPELINE_STAGE_TRANSFER_BIT,
      VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
      0,
      1,
      &amp;barrier,
      ...
  );
  
  // begin render pass
  // drawing commands
  // end render pass
      
  vkCmdPipelineBarrier(
      commandBuffer[N],
      VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
      VK_PIPELINE_STAGE_TRANSFER_BIT,
      0,
      0,
      NULL,
      ...
  );
  </code></pre>
  <p>I believe the first pipeline barrier is needed to prevent the GPU from allowing the vertex shader to read from the Storage Buffer while it is being updated.</p>
  <p>I think the second pipeline barrier is needed to prevent the <code>vkCmdCopyBuffers</code> command of the next frame from executing until the vertex shader of the previous frame is done reading the Storage Buffer. My understanding is that a memory barrier isn't needed here because this is a 'WAR hazard' (<a href="https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples#first-draw-samples-a-texture-in-the-fragment-shader-second-draw-writes-to-that-texture-as-a-color-attachment" rel="nofollow noreferrer">https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples#first-draw-samples-a-texture-in-the-fragment-shader-second-draw-writes-to-that-texture-as-a-color-attachment</a>).</p>
  <p><strong>Is my suggestion correct?</strong> Or have I misunderstood something?</p>
  <p>NB: I'm aware that the approach I'm taking above (even if correct) may not be the best - e.g. perhaps having N Storage Buffers for each frame in-flight would offer better performance. However I'm hoping to get my head around synchronisation before proceeding further.</p>
  <p>I'd appreciate any help you Vulkan masters can provide!</p>