[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