From: Nicolai Hähnle <nicolai.haeh...@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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to