Return appropriate error code in acquire_next_image
authorIason Paraskevopoulos <iason.paraskevopoulos@arm.com>
Wed, 22 Sep 2021 10:15:26 +0000 (11:15 +0100)
committerMatteo Franchin <matteo.franchin@arm.com>
Thu, 25 Nov 2021 15:39:42 +0000 (15:39 +0000)
Fixes an issue, where acquire_next_image was always returning
VK_ERROR_OUT_OF_HOST_MEMORY when the swapchain had gone into a faulty
state.

Change-Id: Iafe016e4e31158d1a5f0d6d785f60d6a724c62ab
Signed-off-by: Iason Paraskevopoulos <iason.paraskevopoulos@arm.com>
wsi/swapchain_base.cpp
wsi/swapchain_base.hpp
wsi/wayland/swapchain.cpp

index e56a2bd..b04dc79 100644 (file)
@@ -80,7 +80,16 @@ void swapchain_base::page_flip_thread()
       vk_res = image_wait_present(sc_images[*pending_index], timeout);
       if (vk_res != VK_SUCCESS)
       {
-         m_is_valid = false;
+         /*
+          * Setting the error state to VK_TIMEOUT would communicate the wrong error
+          * state to the application through acquire_next_image. For this reason we
+          * convert it to VK_ERROR_DEVICE_LOST.
+          */
+         if (vk_res == VK_TIMEOUT)
+         {
+            vk_res = VK_ERROR_DEVICE_LOST;
+         }
+         set_error_state(vk_res);
          m_free_image_semaphore.post();
          continue;
       }
@@ -171,7 +180,6 @@ void swapchain_base::unpresent_image(uint32_t presented_index)
 swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
    : m_device_data(dev_data)
    , m_page_flip_thread_run(false)
-   , m_is_valid(false)
    , m_start_present_semaphore()
    , m_thread_sem_defined(false)
    , m_first_present(true)
@@ -185,6 +193,7 @@ swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAll
    , m_device(VK_NULL_HANDLE)
    , m_queue(VK_NULL_HANDLE)
    , m_image_acquire_lock()
+   , m_error_state(VK_NOT_READY)
 {
 }
 
@@ -295,7 +304,7 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
       ancestor->deprecate(reinterpret_cast<VkSwapchainKHR>(this));
    }
 
-   m_is_valid = true;
+   set_error_state(VK_SUCCESS);
 
    return VK_SUCCESS;
 }
@@ -315,7 +324,7 @@ void swapchain_base::teardown()
       auto *desc = reinterpret_cast<swapchain_base *>(m_descendant);
       sem_wait(&desc->m_start_present_semaphore);
    }
-   else if (m_is_valid)
+   else if (!error_has_occured())
    {
       /* If descendant hasn't started presenting, there are pending buffers in the swapchain. */
       wait_for_pending_buffers();
@@ -380,9 +389,9 @@ VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaph
       return retval;
    }
 
-   if (!m_is_valid)
+   if (error_has_occured())
    {
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
+      return get_error_state();
    }
 
    std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
index 382ee11..fabc069 100644 (file)
@@ -200,13 +200,6 @@ protected:
    bool m_page_flip_thread_run;
 
    /**
-    * @brief In case we encounter threading or drm errors we need a way to
-    * notify the user of the failure. When this flag is false, acquire_next_image
-    * will return an error code.
-    */
-   bool m_is_valid;
-
-   /**
     * @brief A semaphore to be signalled once a page flip event occurs.
     */
    util::timed_semaphore m_page_flip_semaphore;
@@ -431,9 +424,44 @@ protected:
     */
    virtual VkResult image_wait_present(swapchain_image &image, uint64_t timeout) = 0;
 
+   /**
+    * @brief Returns true if an error has occurred.
+    */
+   bool error_has_occured() const
+   {
+      return m_error_state != VK_SUCCESS;
+   }
+
+   VkResult get_error_state() const
+   {
+      return m_error_state;
+   }
+
+   /*
+    * @brief Set the error state.
+    *
+    * The error state should be set when a failure that should be communicated
+    * to the application occurs during the page flipping thread.
+    *
+    * @param state Error code to be returned from acquire_next_image.
+    */
+   void set_error_state(VkResult state)
+   {
+      m_error_state = state;
+   }
+
 private:
    std::mutex m_image_acquire_lock;
    /**
+    * @brief In case we encounter threading or drm errors we need a way to
+    * notify the user of the failure. While no error has occurred its value
+    * is VK_SUCCESS. When an error occurs, its value is set to the
+    * appropriate error code and it is returned to the user through the next
+    * acquire_next_image call.
+    */
+   VkResult m_error_state;
+
+   /**
     * @brief Wait for a buffer to become free.
     */
    VkResult wait_for_free_buffer(uint64_t timeout);
index a5caf3a..a424801 100644 (file)
@@ -601,7 +601,7 @@ void swapchain::present_image(uint32_t pendingIndex)
    /* if a frame is already pending, wait for a hint to present again */
    if (!m_wsi_surface->wait_next_frame_event())
    {
-      m_is_valid = false;
+      set_error_state(VK_ERROR_SURFACE_LOST_KHR);
    }
 
    wl_surface_attach(m_surface, image_data->buffer, 0, 0);
@@ -610,7 +610,7 @@ void swapchain::present_image(uint32_t pendingIndex)
    if (!present_sync_fd.has_value())
    {
       WSI_LOG_ERROR("Failed to export present fence.");
-      m_is_valid = false;
+      set_error_state(VK_ERROR_SURFACE_LOST_KHR);
    }
    else if (present_sync_fd->is_valid())
    {
@@ -625,7 +625,7 @@ void swapchain::present_image(uint32_t pendingIndex)
    {
       if (!m_wsi_surface->set_frame_callback())
       {
-         m_is_valid = false;
+         set_error_state(VK_ERROR_SURFACE_LOST_KHR);
       }
    }
 
@@ -635,7 +635,7 @@ void swapchain::present_image(uint32_t pendingIndex)
    {
       WSI_LOG_ERROR("error flushing the display");
       /* Setting the swapchain as invalid */
-      m_is_valid = false;
+      set_error_state(VK_ERROR_SURFACE_LOST_KHR);
    }
 }