title: Do I need dedicated fences/semaphores per swap chain image, per frame or per command pool in Vulkan?
body: <p>I've read several articles on the CPU-GPU (using fences) and GPU-GPU (using semaphores) synchronization mechanisms, but still got trouble to understand how I should implement a simple render-loop.</p>
  <p>Please take a look at the simple <code>render()</code> function below. If I got it right, the minimal requirement is that we ensure the GPU-GPU synchronization between <code>vkAcquireNextImageKHR</code>, <code>vkQueueSubmit</code> and <code>vkQueuePresentKHR</code> by a <em>single</em> set of semaphores <code>image_available</code> and <code>rendering_finished</code> as I've done in the example code below.</p>
  <p>However, is this really safe? All operations are asynchronous. So, is it really safe to &quot;reuse&quot; the <code>image_available</code> semaphore in a subsequent call of <code>render()</code> again even though the signal request from the previous call hasn't fired yet? I would think it's not, but, on the other hand, we're using the same queues (don't know if it matters where the graphics and presentation queue are actually the same) and operations inside a queue should be sequentially consumed ... But if I got it right, they might not be consumed &quot;as a whole&quot; and could be reordered ...</p>
  <p>The second thing is that (again, unless I'm missing something) I clearly should use one fence per swap chain image to ensure that the operation on the image corresponding to the <code>image_index</code> of the call to <code>render()</code> has finished. But does that mean that I necessarily need to do a</p>
  <pre><code>if (vkWaitForFences(device(), 1, &amp;fence[image_index_of_last_call], VK_FALSE, std::numeric_limits&lt;std::uint64_t&gt;::max()) != VK_SUCCESS)
      throw std::runtime_error(&quot;vkWaitForFences&quot;);
  vkResetFences(device(), 1, &amp;fence[image_index_of_last_call]);
  </code></pre>
  <p>before my call to <code>vkAcquireNextImageKHR</code>? And do I then need dedicated <code>image_available</code> and <code>rendering_finished</code> semaphores per swap chain image? Or maybe per frame? Or maybe per command buffer/pool? I'm really confused ...</p>
  <hr />
  <pre><code>void render()
  {
      std::uint32_t image_index;
      switch (vkAcquireNextImageKHR(device(), swap_chain().handle(),
          std::numeric_limits&lt;std::uint64_t&gt;::max(), m_image_available, VK_NULL_HANDLE, &amp;image_index))
      {
      case VK_SUBOPTIMAL_KHR:
      case VK_SUCCESS:
          break;
      case VK_ERROR_OUT_OF_DATE_KHR:
          on_resized();
          return;
      default:
          throw std::runtime_error(&quot;vkAcquireNextImageKHR&quot;);
      }
  
      static VkPipelineStageFlags constexpr wait_destination_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  
      VkSubmitInfo submit_info{};
      submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  
      submit_info.waitSemaphoreCount = 1;
      submit_info.pWaitSemaphores = &amp;m_image_available;
      submit_info.signalSemaphoreCount = 1;
      submit_info.pSignalSemaphores = &amp;m_rendering_finished;
  
      submit_info.pWaitDstStageMask = &amp;wait_destination_stage_mask;
  
      if (vkQueueSubmit(graphics_queue().handle, 1, &amp;submit_info, VK_NULL_HANDLE) != VK_SUCCESS)
          throw std::runtime_error(&quot;vkQueueSubmit&quot;);
  
      VkPresentInfoKHR present_info{};
      present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  
      present_info.waitSemaphoreCount = 1;
      present_info.pWaitSemaphores = &amp;m_rendering_finished;
  
      present_info.swapchainCount = 1;
      present_info.pSwapchains = &amp;swap_chain().handle();
      present_info.pImageIndices = &amp;image_index;
  
      switch (vkQueuePresentKHR(presentation_queue().handle, &amp;present_info))
      {
      case VK_SUCCESS:
          break;
      case VK_ERROR_OUT_OF_DATE_KHR:
      case VK_SUBOPTIMAL_KHR:
          on_resized();
          return;
      default:
          throw std::runtime_error(&quot;vkQueuePresentKHR&quot;);
      }
  }
  </code></pre>
  <p><strong>EDIT</strong>: As suggested in the answers below, assume we have <code>k</code> &quot;frames in flight&quot; and hence <code>k</code> instances of the semaphores and the fence used in the code above, which I will denote by <code>m_image_available[i]</code>, <code>m_rendering_finished[i]</code> and <code>m_fence[i]</code> for <code>i = 0, ..., k - 1</code>. Let <code>i</code> denote the current index of the frame in flight, which is increased by <code>1</code> after each invocation of <code>render()</code>, and <code>j</code> denote the number of invocations of <code>render()</code>, starting from <code>j = 0</code>.</p>
  <p>Now, assume the swap chain contains three images.</p>
  <ul>
  <li>If <code>j = 0</code>, then <code>i = 0</code> and the first frame in flight is using swap chain image <code>0</code></li>
  <li>In the same way, if <code>j = a</code>, then <code>i = a</code> and the <code>a</code>th frame in flight is using swap chain image <code>a</code>, for <code>a= 2, 3</code></li>
  <li>Now, if <code>j = 3</code>, then <code>i = 3</code>, but since the swap chain image only has three images, the fourth frame in flight is using swap chain image <code>0</code> again. I wonder whether this is problematic or not. I guess it's not, since the wait/signal semaphores <code>m_image_available[3]</code>/<code>m_rendering_finished[3]</code>, used in the calls of <code>vkAcquireNextImageKHR</code>, <code>vkQueueSubmit</code> and <code>vkQueuePresentKHR</code> in this invocation of <code>render()</code>, are dedicated to this particular frame in flight.</li>
  <li>If we reach <code>j = k</code>, then <code>i = 0</code> again, since there are only <code>k</code> frames in flight. Now we potentially wait at the beginning of <code>render()</code>, if the call to <code>vkQueuePresentKHR</code> from the first invocation (<code>i = 0</code>) of <code>render()</code> hasn't signaled <code>m_fence[0]</code> yet.</li>
  </ul>
  <p>So, besides my doubts described in the third bullet point above, the only question which remains is why I shouldn't take <code>k</code> as large as possible? What I theoretically could imagine is that if we are submitting work to the GPU in a quicker fashion than the GPU is able to consume, the used queue(s) might continually grow and eventually overflow (is there some kind of &quot;max commands in queue&quot; limit?).</p>