[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:53:55 UTC 2018
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;
>
> 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/cc740fe2/attachment-0001.html>
More information about the mesa-dev
mailing list