[Mesa-dev] [PATCH 8/8] gallium/u_threaded: avoid syncing in threaded_context_flush

Marek Olšák maraeo at gmail.com
Fri Nov 17 17:53:20 UTC 2017


For the series:

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Mon, Nov 13, 2017 at 3:03 PM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> We could always do the flush asynchronously, but if we're going to wait
> for a fence anyway and the driver thread is currently idle, the additional
> communication overhead isn't worth it.
> ---
>  src/gallium/auxiliary/util/u_threaded_context.c | 16 +++++++++++++---
>  src/gallium/auxiliary/util/u_threaded_context.h |  3 ++-
>  src/gallium/drivers/radeonsi/si_fence.c         |  3 ++-
>  3 files changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
> index ecd42724548..eb8f7011682 100644
> --- a/src/gallium/auxiliary/util/u_threaded_context.c
> +++ b/src/gallium/auxiliary/util/u_threaded_context.c
> @@ -223,27 +223,37 @@ _tc_sync(struct threaded_context *tc, const char *info, const char *func)
>
>  /**
>   * Call this from fence_finish for same-context fence waits of deferred fences
>   * that haven't been flushed yet.
>   *
>   * The passed pipe_context must be the one passed to pipe_screen::fence_finish,
>   * i.e., the wrapped one.
>   */
>  void
>  threaded_context_flush(struct pipe_context *_pipe,
> -                       struct tc_unflushed_batch_token *token)
> +                       struct tc_unflushed_batch_token *token,
> +                       bool prefer_async)
>  {
>     struct threaded_context *tc = threaded_context(_pipe);
>
>     /* This is called from the state-tracker / application thread. */
> -   if (token->tc && token->tc == tc)
> -      tc_sync(token->tc);
> +   if (token->tc && token->tc == tc) {
> +      struct tc_batch *last = &tc->batch_slots[tc->last];
> +
> +      /* Prefer to do the flush in the driver thread if it is already
> +       * running. That should be better for cache locality.
> +       */
> +      if (prefer_async || !util_queue_fence_is_signalled(&last->fence))
> +         tc_batch_flush(tc);
> +      else
> +         tc_sync(token->tc);
> +   }
>  }
>
>  static void
>  tc_set_resource_reference(struct pipe_resource **dst, struct pipe_resource *src)
>  {
>     *dst = NULL;
>     pipe_resource_reference(dst, src);
>  }
>
>  void
> diff --git a/src/gallium/auxiliary/util/u_threaded_context.h b/src/gallium/auxiliary/util/u_threaded_context.h
> index e1ba73607db..ed653b7600d 100644
> --- a/src/gallium/auxiliary/util/u_threaded_context.h
> +++ b/src/gallium/auxiliary/util/u_threaded_context.h
> @@ -373,21 +373,22 @@ struct pipe_context *threaded_context_unwrap_sync(struct pipe_context *pipe);
>
>  struct pipe_context *
>  threaded_context_create(struct pipe_context *pipe,
>                          struct slab_parent_pool *parent_transfer_pool,
>                          tc_replace_buffer_storage_func replace_buffer,
>                          tc_create_fence_func create_fence,
>                          struct threaded_context **out);
>
>  void
>  threaded_context_flush(struct pipe_context *_pipe,
> -                       struct tc_unflushed_batch_token *token);
> +                       struct tc_unflushed_batch_token *token,
> +                       bool prefer_async);
>
>  static inline struct threaded_context *
>  threaded_context(struct pipe_context *pipe)
>  {
>     return (struct threaded_context*)pipe;
>  }
>
>  static inline struct threaded_resource *
>  threaded_resource(struct pipe_resource *res)
>  {
> diff --git a/src/gallium/drivers/radeonsi/si_fence.c b/src/gallium/drivers/radeonsi/si_fence.c
> index 5163d652c83..9d6bcfe1027 100644
> --- a/src/gallium/drivers/radeonsi/si_fence.c
> +++ b/src/gallium/drivers/radeonsi/si_fence.c
> @@ -196,21 +196,22 @@ static boolean si_fence_finish(struct pipe_screen *screen,
>
>                 if (rfence->tc_token) {
>                         /* Ensure that si_flush_from_st will be called for
>                          * this fence, but only if we're in the API thread
>                          * where the context is current.
>                          *
>                          * Note that the batch containing the flush may already
>                          * be in flight in the driver thread, so the fence
>                          * may not be ready yet when this call returns.
>                          */
> -                       threaded_context_flush(ctx, rfence->tc_token);
> +                       threaded_context_flush(ctx, rfence->tc_token,
> +                                              timeout == 0);
>                 }
>
>                 if (timeout == PIPE_TIMEOUT_INFINITE) {
>                         util_queue_fence_wait(&rfence->ready);
>                 } else {
>                         if (!util_queue_fence_wait_timeout(&rfence->ready, abs_timeout))
>                                 return false;
>                 }
>
>                 if (timeout && timeout != PIPE_TIMEOUT_INFINITE) {
> --
> 2.11.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list