[Mesa-dev] [PATCH 8/8] gallium/u_threaded: avoid syncing in threaded_context_flush
Nicolai Hähnle
nhaehnle at gmail.com
Mon Nov 13 14:03:36 UTC 2017
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
More information about the mesa-dev
mailing list