gallium/u_threaded: avoid syncing in threaded_context_flush
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Fri, 10 Nov 2017 10:15:44 +0000 (11:15 +0100)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Mon, 20 Nov 2017 17:16:15 +0000 (18:16 +0100)
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.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/auxiliary/util/u_threaded_context.c
src/gallium/auxiliary/util/u_threaded_context.h
src/gallium/drivers/radeonsi/si_fence.c

index 84fbb224533b7148266bb211ae6beef1ed356ac2..ffa824744e5fb59e203ad5829d11a5e3e5124689 100644 (file)
@@ -231,13 +231,23 @@ _tc_sync(struct threaded_context *tc, MAYBE_UNUSED const char *info, MAYBE_UNUSE
  */
 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
index 34089561f34e38bfffc9b4f4e726f6760f14dd6e..53c5a7e8c4c8ad5e8f6c806e5a33516d1fc84ed1 100644 (file)
@@ -381,7 +381,8 @@ threaded_context_create(struct pipe_context *pipe,
 
 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)
index 5163d652c83719a040a73193caa98736228c96aa..9d6bcfe102745f6d1e7e2d9129bee8428f8ce4d0 100644 (file)
@@ -203,7 +203,8 @@ static boolean si_fence_finish(struct pipe_screen *screen,
                         * 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) {