From e14be07f0fab02d8c7742fc0232d96b56bc32361 Mon Sep 17 00:00:00 2001
From: Frederico Linhares <fred@linhares.blue>
Date: Fri, 21 Oct 2022 11:52:48 -0300
Subject: feat Skip frame if image is not available.

---
 src/vk/renderer.cpp | 288 ++++++++++++++++++++++++++++------------------------
 1 file changed, 153 insertions(+), 135 deletions(-)

(limited to 'src/vk')

diff --git a/src/vk/renderer.cpp b/src/vk/renderer.cpp
index 7492cce..8d82b00 100644
--- a/src/vk/renderer.cpp
+++ b/src/vk/renderer.cpp
@@ -164,153 +164,171 @@ Renderer::~Renderer()
 void
 Renderer::draw()
 {
-  vkWaitForFences(cg_core.vk_device_with_swapchain->device, 1,
+  auto fence_status = vkGetFenceStatus(
+    cg_core.vk_device_with_swapchain->device,
+    cg_core.vk_swapchain->in_flight_fences[
+      cg_core.vk_swapchain->current_frame]);
+
+  if(fence_status == VK_SUCCESS)
+  {
+    auto next_frame = cg_core.vk_swapchain->current_frame + 1;
+    if(next_frame == Swapchain::max_frames_in_flight) next_frame = 0;
+
+    vkResetFences(cg_core.vk_device_with_swapchain->device, 1,
                   &cg_core.vk_swapchain->in_flight_fences[
-                    cg_core.vk_swapchain->current_frame], VK_TRUE,
-                  std::numeric_limits<uint64_t>::max());
-  vkResetFences(cg_core.vk_device_with_swapchain->device, 1,
-                &cg_core.vk_swapchain->in_flight_fences[
-                  cg_core.vk_swapchain->current_frame]);
+                    cg_core.vk_swapchain->current_frame]);
 
-  uint32_t image_index;
-  vkAcquireNextImageKHR(
+    uint32_t image_index;
+    vkAcquireNextImageKHR(
       cg_core.vk_device_with_swapchain->device,
       cg_core.vk_swapchain->swapchain, std::numeric_limits<uint64_t>::max(),
       cg_core.vk_swapchain->image_available_semaphores[
         cg_core.vk_swapchain->current_frame], VK_NULL_HANDLE, &image_index);
 
-  VkCommandBuffer draw_command_buffer =
-    this->draw_command_buffers[cg_core.vk_swapchain->current_frame];
-  vkResetCommandBuffer(draw_command_buffer, 0);
-
-  auto next_frame = cg_core.vk_swapchain->current_frame + 1;
-  if(next_frame == Swapchain::max_frames_in_flight) next_frame = 0;
-
-  // Begin command buffer.
-  {
-    VkCommandBufferBeginInfo begin_info{};
-    begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
-    begin_info.flags = 0;
-    begin_info.pInheritanceInfo = nullptr;
-    if (vkBeginCommandBuffer(draw_command_buffer, &begin_info) != VK_SUCCESS)
-      throw std::runtime_error{"Failed to beggin draw command buffer."};
-  }
-
-  // 3D drawing.
-  {
-    // Dark gray blue.
-    std::array<VkClearValue, 2> clear_values{};
-    clear_values[0].color = {0.12f, 0.12f, 0.18f, 1.0f};
-    clear_values[1].depthStencil = {1.0f, 0};
-
-    VkRenderPassBeginInfo render_pass_begin{};
-    render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
-    render_pass_begin.pNext = nullptr;
-    render_pass_begin.renderPass =
-      cg_core.vk_graphics_pipeline_3d_layout->render_pass;
-    render_pass_begin.framebuffer =
-      cg_core.vk_graphics_pipeline_3d->swapchain_framebuffers[image_index];
-    render_pass_begin.renderArea.offset = {0, 0};
-    render_pass_begin.renderArea.extent = {
-      static_cast<uint32_t>(cg_core.display_width),
-      static_cast<uint32_t>(cg_core.display_height)};
-    render_pass_begin.clearValueCount = clear_values.size();
-    render_pass_begin.pClearValues = clear_values.data();
-
-    vkCmdBeginRenderPass(
-      draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
-
-    for(auto &view: this->views_3d)
-      cg_core.vk_graphics_pipeline_3d->draw(
-        view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
-        image_index);
-
-    vkCmdEndRenderPass(draw_command_buffer);
+    VkCommandBuffer draw_command_buffer =
+      this->draw_command_buffers[cg_core.vk_swapchain->current_frame];
+    vkResetCommandBuffer(draw_command_buffer, 0);
+
+    // Begin command buffer.
+    {
+      VkCommandBufferBeginInfo begin_info{};
+      begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+      begin_info.flags = 0;
+      begin_info.pInheritanceInfo = nullptr;
+      if (vkBeginCommandBuffer(draw_command_buffer, &begin_info) != VK_SUCCESS)
+        throw std::runtime_error{"Failed to beggin draw command buffer."};
+    }
+
+    // 3D drawing.
+    {
+      // Dark gray blue.
+      std::array<VkClearValue, 2> clear_values{};
+      clear_values[0].color = {0.12f, 0.12f, 0.18f, 1.0f};
+      clear_values[1].depthStencil = {1.0f, 0};
+
+      VkRenderPassBeginInfo render_pass_begin{};
+      render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+      render_pass_begin.pNext = nullptr;
+      render_pass_begin.renderPass =
+        cg_core.vk_graphics_pipeline_3d_layout->render_pass;
+      render_pass_begin.framebuffer =
+        cg_core.vk_graphics_pipeline_3d->swapchain_framebuffers[image_index];
+      render_pass_begin.renderArea.offset = {0, 0};
+      render_pass_begin.renderArea.extent = {
+        static_cast<uint32_t>(cg_core.display_width),
+        static_cast<uint32_t>(cg_core.display_height)};
+      render_pass_begin.clearValueCount = clear_values.size();
+      render_pass_begin.pClearValues = clear_values.data();
+
+      vkCmdBeginRenderPass(
+        draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
+
+      for(auto &view: this->views_3d)
+        cg_core.vk_graphics_pipeline_3d->draw(
+          view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
+          image_index);
+
+      vkCmdEndRenderPass(draw_command_buffer);
+    }
+
+    // 2D drawing
+    {
+      VkRenderPassBeginInfo render_pass_begin{};
+      render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+      render_pass_begin.pNext = nullptr;
+      render_pass_begin.renderPass =
+        cg_core.vk_graphics_pipeline_2d_layout->render_pass;
+      render_pass_begin.framebuffer =
+        cg_core.vk_graphics_pipeline_2d->swapchain_framebuffers[image_index];
+      render_pass_begin.renderArea.offset = {0, 0};
+      render_pass_begin.renderArea.extent = {
+        static_cast<uint32_t>(cg_core.display_width),
+        static_cast<uint32_t>(cg_core.display_height)};
+      render_pass_begin.clearValueCount = 0;
+      render_pass_begin.pClearValues = nullptr;
+
+      vkCmdBeginRenderPass(
+        draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
+
+      for(auto &view: this->views_2d)
+        cg_core.vk_graphics_pipeline_2d->draw(
+          view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
+          next_frame, image_index);
+
+      for(auto &view: this->views_3d)
+        cg_core.vk_graphics_pipeline_2d->draw(
+          view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
+          next_frame, image_index);
+
+      vkCmdEndRenderPass(draw_command_buffer);
+    }
+
+    // End command buffer.
+    if(vkEndCommandBuffer(draw_command_buffer) != VK_SUCCESS)
+      throw std::runtime_error{"Failed to end draw command buffer."};
+
+    // Submit drawing command.
+    {
+      auto queue{this->queue_family->get_queue()};
+
+      VkSemaphore wait_semaphores[]{
+        cg_core.vk_swapchain->image_available_semaphores[
+          cg_core.vk_swapchain->current_frame]};
+      VkPipelineStageFlags wait_stages[] =
+        {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
+      VkSemaphore signal_semaphores[]{
+        cg_core.vk_swapchain->render_finished_semaphores[
+          cg_core.vk_swapchain->current_frame]};
+
+      VkSubmitInfo submit_info{};
+      submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+      submit_info.pNext = nullptr;
+      submit_info.waitSemaphoreCount = 1;
+      submit_info.pWaitSemaphores = wait_semaphores;
+      submit_info.pWaitDstStageMask = wait_stages;
+      submit_info.commandBufferCount = 1;
+      submit_info.pCommandBuffers = &draw_command_buffer;
+      submit_info.signalSemaphoreCount = 1;
+      submit_info.pSignalSemaphores = signal_semaphores;
+
+      if(vkQueueSubmit(
+           queue.queue, 1, &submit_info, cg_core.vk_swapchain->in_flight_fences[
+             cg_core.vk_swapchain->current_frame]) != VK_SUCCESS)
+        throw std::runtime_error{"Failed to submit draw command buffer."};
+
+      VkSwapchainKHR swap_chains[]{cg_core.vk_swapchain->swapchain};
+
+      VkPresentInfoKHR present_info{};
+      present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+      present_info.pNext = nullptr;
+      present_info.waitSemaphoreCount = 1;
+      present_info.pWaitSemaphores = signal_semaphores;
+      present_info.swapchainCount = 1;
+      present_info.pSwapchains = swap_chains;
+      present_info.pImageIndices = &image_index;
+      present_info.pResults = nullptr;
+
+      vkQueuePresentKHR(queue.queue, &present_info);
+    }
+
+    // Prepare for the next frame.
+    {
+    this->models_to_draw[next_frame].clear();
+    for(auto &view: this->views_2d) view->sprites_to_draw[next_frame].clear();
+    for(auto &view: this->views_3d) view->sprites_to_draw[next_frame].clear();
+
+    cg_core.vk_swapchain->current_frame = next_frame;
+    }
   }
-
-  // 2D drawing
+  else
   {
-    VkRenderPassBeginInfo render_pass_begin{};
-    render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
-    render_pass_begin.pNext = nullptr;
-    render_pass_begin.renderPass =
-      cg_core.vk_graphics_pipeline_2d_layout->render_pass;
-    render_pass_begin.framebuffer =
-      cg_core.vk_graphics_pipeline_2d->swapchain_framebuffers[image_index];
-    render_pass_begin.renderArea.offset = {0, 0};
-    render_pass_begin.renderArea.extent = {
-      static_cast<uint32_t>(cg_core.display_width),
-      static_cast<uint32_t>(cg_core.display_height)};
-    render_pass_begin.clearValueCount = 0;
-    render_pass_begin.pClearValues = nullptr;
-
-    vkCmdBeginRenderPass(
-      draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
-
+    // Clear images for the current frame because we are skipping this frame.
+    this->models_to_draw[cg_core.vk_swapchain->current_frame].clear();
     for(auto &view: this->views_2d)
-     cg_core.vk_graphics_pipeline_2d->draw(
-       view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
-       next_frame, image_index);
-
+      view->sprites_to_draw[cg_core.vk_swapchain->current_frame].clear();
     for(auto &view: this->views_3d)
-     cg_core.vk_graphics_pipeline_2d->draw(
-       view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
-       next_frame, image_index);
-
-    vkCmdEndRenderPass(draw_command_buffer);
-  }
-
-  // End command buffer.
-  if(vkEndCommandBuffer(draw_command_buffer) != VK_SUCCESS)
-    throw std::runtime_error{"Failed to end draw command buffer."};
-
-  // Submit drawing command.
-  {
-    auto queue{this->queue_family->get_queue()};
-
-    VkSemaphore wait_semaphores[]{
-      cg_core.vk_swapchain->image_available_semaphores[
-        cg_core.vk_swapchain->current_frame]};
-    VkPipelineStageFlags wait_stages[] =
-      {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
-    VkSemaphore signal_semaphores[]{
-      cg_core.vk_swapchain->render_finished_semaphores[
-        cg_core.vk_swapchain->current_frame]};
-
-    VkSubmitInfo submit_info{};
-    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
-    submit_info.pNext = nullptr;
-    submit_info.waitSemaphoreCount = 1;
-    submit_info.pWaitSemaphores = wait_semaphores;
-    submit_info.pWaitDstStageMask = wait_stages;
-    submit_info.commandBufferCount = 1;
-    submit_info.pCommandBuffers = &draw_command_buffer;
-    submit_info.signalSemaphoreCount = 1;
-    submit_info.pSignalSemaphores = signal_semaphores;
-
-    if(vkQueueSubmit(
-         queue.queue, 1, &submit_info, cg_core.vk_swapchain->in_flight_fences[
-           cg_core.vk_swapchain->current_frame]) != VK_SUCCESS)
-      throw std::runtime_error{"Failed to submit draw command buffer."};
-
-    VkSwapchainKHR swap_chains[]{cg_core.vk_swapchain->swapchain};
-
-    VkPresentInfoKHR present_info{};
-    present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
-    present_info.pNext = nullptr;
-    present_info.waitSemaphoreCount = 1;
-    present_info.pWaitSemaphores = signal_semaphores;
-    present_info.swapchainCount = 1;
-    present_info.pSwapchains = swap_chains;
-    present_info.pImageIndices = &image_index;
-    present_info.pResults = nullptr;
-
-    vkQueuePresentKHR(queue.queue, &present_info);
+      view->sprites_to_draw[cg_core.vk_swapchain->current_frame].clear();
   }
-
-  // Prepare for the next frame.
-  this->models_to_draw[next_frame].clear();
-  cg_core.vk_swapchain->current_frame = next_frame;
 }
 
 }
-- 
cgit v1.2.3