[Mesa-dev] [PATCH v11 07+08/15] vulkan/wsi/x11: Consistently update and return swapchain status

Jason Ekstrand jason at jlekstrand.net
Wed Feb 21 19:58:51 UTC 2018


On Wed, Feb 21, 2018 at 11:53 AM, Jason Ekstrand <jason at jlekstrand.net>
wrote:

> For this one, I'm making live edits to see if I like the suggested
> changes.  I'll send out the v2 with the comments incorporated when I'm done.
>
> On Wed, Feb 21, 2018 at 11:32 AM, Jason Ekstrand <jason at jlekstrand.net>
> wrote:
>
>> From: Daniel Stone <daniels at collabora.com>
>>
>> Use a helper function for updating the swapchain status. This will be
>> used later to handle VK_SUBOPTIMAL_KHR, where we need to make a
>> non-error status stick to the swapchain until recreation.  Instead of
>> direct comparisons to VK_SUCCESS to check for error, test for negative
>> numbers meaning an error status, and positive numbers indicating
>> non-error statuses.
>>
>> Signed-off-by: Daniel Stone <daniels at collabora.com>
>> ---
>>  src/vulkan/wsi/wsi_common_x11.c | 104 ++++++++++++++++++++++++++++++
>> ----------
>>  1 file changed, 79 insertions(+), 25 deletions(-)
>>
>> diff --git a/src/vulkan/wsi/wsi_common_x11.c
>> b/src/vulkan/wsi/wsi_common_x11.c
>> index 2cc7a67..e845728 100644
>> --- a/src/vulkan/wsi/wsi_common_x11.c
>> +++ b/src/vulkan/wsi/wsi_common_x11.c
>> @@ -641,6 +641,36 @@ struct x11_swapchain {
>>     struct x11_image                             images[0];
>>  };
>>
>> +/**
>> + * Update the swapchain status with the result of an operation, and
>> return
>> + * the combined status. The chain status will eventually be returned from
>> + * AcquireNextImage and QueuePresent.
>> + *
>> + * We make sure to 'stick' more pessimistic statuses: an out-of-date
>> error
>> + * is permanent once seen, and every subsequent call will return this. If
>> + * this has not been seen, success will be returned.
>> + */
>> +static VkResult
>> +x11_swapchain_result(struct x11_swapchain *chain, VkResult result)
>> +{
>> +   /* Prioritise returning existing errors for consistency. */
>> +   if (chain->status < 0)
>> +      return chain->status;
>> +
>> +   /* If we have a new error, mark it as permanent on the chain and
>> return. */
>> +   if (result < 0) {
>> +      chain->status = result;
>> +      return result;
>> +   }
>> +
>> +   /* Return temporary errors, but don't persist them. */
>> +   if (result == VK_TIMEOUT || result == VK_NOT_READY)
>> +      return result;
>> +
>> +   /* No changes, so return the last status. */
>> +   return chain->status;
>> +}
>> +
>>  static struct wsi_image *
>>  x11_get_wsi_image(struct wsi_swapchain *wsi_chain, uint32_t image_index)
>>  {
>> @@ -648,6 +678,9 @@ x11_get_wsi_image(struct wsi_swapchain *wsi_chain,
>> uint32_t image_index)
>>     return &chain->images[image_index].base;
>>  }
>>
>> +/**
>> + * Process an X11 Present event. Does not update chain->status.
>> + */
>>  static VkResult
>>  x11_handle_dri3_present_event(struct x11_swapchain *chain,
>>                                xcb_present_generic_event_t *event)
>> @@ -719,6 +752,8 @@ x11_acquire_next_image_poll_x11(struct x11_swapchain
>> *chain,
>>     xcb_generic_event_t *event;
>>     struct pollfd pfds;
>>     uint64_t atimeout;
>> +   VkResult result = VK_SUCCESS;
>> +
>>     while (1) {
>>        for (uint32_t i = 0; i < chain->base.image_count; i++) {
>>           if (!chain->images[i].busy) {
>> @@ -726,7 +761,8 @@ x11_acquire_next_image_poll_x11(struct x11_swapchain
>> *chain,
>>              xshmfence_await(chain->images[i].shm_fence);
>>              *image_index = i;
>>              chain->images[i].busy = true;
>> -            return VK_SUCCESS;
>> +            result = VK_SUCCESS;
>>
>
> Since our neat little helper returns the accumulated result, these can all
> be
>
> - return VK_WHATEVER;
> + return x11_swapchain_result(chain, VK_WHATEVER);
>
> That makes things quite a bit cleaner.
>
>
>> +           goto out;
>>           }
>>        }
>>
>> @@ -734,24 +770,31 @@ x11_acquire_next_image_poll_x11(struct
>> x11_swapchain *chain,
>>
>>        if (timeout == UINT64_MAX) {
>>           event = xcb_wait_for_special_event(chain->conn,
>> chain->special_event);
>> -         if (!event)
>> -            return VK_ERROR_OUT_OF_DATE_KHR;
>> +         if (!event) {
>> +            result = VK_ERROR_OUT_OF_DATE_KHR;
>> +            goto out;
>> +         }
>>        } else {
>>           event = xcb_poll_for_special_event(chain->conn,
>> chain->special_event);
>>           if (!event) {
>>              int ret;
>> -            if (timeout == 0)
>> -               return VK_NOT_READY;
>> +            if (timeout == 0) {
>> +               result = VK_NOT_READY;
>> +               goto out;
>> +            }
>>
>>              atimeout = wsi_get_absolute_timeout(timeout);
>>
>>              pfds.fd = xcb_get_file_descriptor(chain->conn);
>>              pfds.events = POLLIN;
>>              ret = poll(&pfds, 1, timeout / 1000 / 1000);
>> -            if (ret == 0)
>> -               return VK_TIMEOUT;
>> -            if (ret == -1)
>> -               return VK_ERROR_OUT_OF_DATE_KHR;
>> +            if (ret == 0) {
>> +               result = VK_TIMEOUT;
>> +               goto out;
>> +            } else if (ret == -1) {
>> +               result = VK_ERROR_OUT_OF_DATE_KHR;
>> +               goto out;
>> +            }
>>
>>              /* If a non-special event happens, the fd will still
>>               * poll. So recalculate the timeout now just in case.
>> @@ -765,11 +808,18 @@ x11_acquire_next_image_poll_x11(struct
>> x11_swapchain *chain,
>>           }
>>        }
>>
>> +      /* Update the swapchain status here. We may catch non-fatal errors
>> here,
>> +       * in which case we need to update the status and continue.
>> +       */
>>        VkResult result = x11_handle_dri3_present_event(chain, (void
>> *)event);
>>
>
> This shadows the function-scope result variable.  I don't think that's
> what you intended.
>
>
>> +      result = x11_swapchain_result(chain, result);
>>        free(event);
>> -      if (result != VK_SUCCESS)
>> -         return result;
>> +      if (result < 0)
>> +         goto out;
>>     }
>> +
>> +out:
>> +   return x11_swapchain_result(chain, result);
>>  }
>>
>>  static VkResult
>> @@ -781,11 +831,9 @@ x11_acquire_next_image_from_queue(struct
>> x11_swapchain *chain,
>>     uint32_t image_index;
>>     VkResult result = wsi_queue_pull(&chain->acquire_queue,
>>                                      &image_index, timeout);
>> -   if (result != VK_SUCCESS) {
>> -      return result;
>> -   } else if (chain->status != VK_SUCCESS) {
>> -      return chain->status;
>> -   }
>> +   /* On error, the thread has shut down, so safe to update
>> chain->status */
>> +   if (result < 0)
>> +      return x11_swapchain_result(chain, result);
>>
>
> I think we also want
>
> if (result == VK_TIMEOUT)
>    return result;
>

No, you were right in your original comment, "|| result == VK_TIMEOUT" is
better.


>
>>     assert(image_index < chain->base.image_count);
>>     xshmfence_await(chain->images[image_index].shm_fence);
>> @@ -859,13 +907,16 @@ x11_queue_present(struct wsi_swapchain *anv_chain,
>>                    const VkPresentRegionKHR *damage)
>>  {
>>     struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
>> +   VkResult result;
>>
>>     if (chain->threaded) {
>>        wsi_queue_push(&chain->present_queue, image_index);
>> -      return chain->status;
>> +      result = chain->status;
>>     } else {
>> -      return x11_present_to_x11(chain, image_index, 0);
>> +      result = x11_present_to_x11(chain, image_index, 0);
>>
>
> Fun fact: x11_present_to_x11 always returns VK_SUCCESS.  I don't think
> this function needs to be modified at all.
>
>
>>     }
>> +
>> +   return x11_swapchain_result(chain, result);
>>  }
>>
>>  static void *
>> @@ -876,7 +927,7 @@ x11_manage_fifo_queues(void *state)
>>
>>     assert(chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR);
>>
>> -   while (chain->status == VK_SUCCESS) {
>> +   while (chain->status >= 0) {
>>        /* It should be safe to unconditionally block here.  Later in the
>> loop
>>         * we blocks until the previous present has landed on-screen.  At
>> that
>>         * point, we should have received IDLE_NOTIFY on all images
>> presented
>> @@ -885,15 +936,18 @@ x11_manage_fifo_queues(void *state)
>>         */
>>        uint32_t image_index;
>>        result = wsi_queue_pull(&chain->present_queue, &image_index,
>> INT64_MAX);
>> -      if (result != VK_SUCCESS) {
>> +      if (result < 0) {
>>           goto fail;
>> -      } else if (chain->status != VK_SUCCESS) {
>> +      } else if (chain->status < 0) {
>> +         /* The status can change underneath us if the swapchain is
>> destroyed
>> +          * from another thread.
>> +          */
>>           return NULL;
>>        }
>>
>>        uint64_t target_msc = chain->last_present_msc + 1;
>>        result = x11_present_to_x11(chain, image_index, target_msc);
>> -      if (result != VK_SUCCESS)
>> +      if (result < 0)
>>           goto fail;
>>
>>        while (chain->last_present_msc < target_msc) {
>> @@ -904,13 +958,13 @@ x11_manage_fifo_queues(void *state)
>>
>>           result = x11_handle_dri3_present_event(chain, (void *)event);
>>           free(event);
>> -         if (result != VK_SUCCESS)
>> +         if (result < 0)
>>              goto fail;
>>        }
>>     }
>>
>>  fail:
>> -   chain->status = result;
>> +   result = x11_swapchain_result(chain, result);
>>
>
> The "result =" does nothing here.  I'm fine with leaving it though as it's
> also not hurting anything.
>
>
>>     wsi_queue_push(&chain->acquire_queue, UINT32_MAX);
>>
>>     return NULL;
>> @@ -932,7 +986,7 @@ x11_image_init(VkDevice device_h, struct
>> x11_swapchain *chain,
>>        result = wsi_create_native_image(&chain->base, pCreateInfo,
>>                                         0, NULL, NULL, &image->base);
>>     }
>> -   if (result != VK_SUCCESS)
>> +   if (result < 0)
>>        return result;
>>
>>     image->pixmap = xcb_generate_id(chain->conn);
>> --
>> 2.5.0.400.gff86faf
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180221/ffb24a1a/attachment.html>


More information about the mesa-dev mailing list