diff options
author | Nicolai Hähnle <[email protected]> | 2017-10-22 17:38:50 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2017-11-09 14:00:42 +0100 |
commit | 609a230375cae7710b2a9f40a42341b4cd853a3e (patch) | |
tree | 1b404da87aa1ac457c8d8320b7e62081becc52c0 /src/gallium/auxiliary/util/u_threaded_context.h | |
parent | 11b380ed0c61344b461ad2d1b66bf81e2c46b84b (diff) |
gallium/u_threaded: implement asynchronous flushes
This requires out-of-band creation of fences, and will be signaled to
the pipe_context::flush implementation by a special TC_FLUSH_ASYNC flag.
v2:
- remove an incorrect assertion
- handle fence_server_sync for unsubmitted fences by
relying on the improved cs_add_fence_dependency
- only implement asynchronous flushes on amdgpu
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/util/u_threaded_context.h')
-rw-r--r-- | src/gallium/auxiliary/util/u_threaded_context.h | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_threaded_context.h b/src/gallium/auxiliary/util/u_threaded_context.h index a9f79a66d42..ea815ed5e03 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.h +++ b/src/gallium/auxiliary/util/u_threaded_context.h @@ -108,6 +108,29 @@ * The threaded context uses its own buffer invalidation mechanism. * * + * Rules for fences + * ---------------- + * + * Flushes will be executed asynchronously in the driver thread if a + * create_fence callback is provided. This affects fence semantics as follows. + * + * When the threaded context wants to perform an asynchronous flush, it will + * use the create_fence callback to pre-create the fence from the calling + * thread. This pre-created fence will be passed to pipe_context::flush + * together with the TC_FLUSH_ASYNC flag. + * + * The callback receives the unwrapped context as a parameter, but must use it + * in a thread-safe way because it is called from a non-driver thread. + * + * If the threaded_context does not immediately flush the current batch, the + * callback also receives a tc_unflushed_batch_token. If fence_finish is called + * on the returned fence in the context that created the fence, + * threaded_context_flush must be called. + * + * The driver must implement pipe_context::fence_server_sync properly, since + * the threaded context handles PIPE_FLUSH_ASYNC. + * + * * Additional requirements * ----------------------- * @@ -160,10 +183,14 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "util/u_inlines.h" #include "util/u_queue.h" #include "util/u_range.h" #include "util/slab.h" +struct threaded_context; +struct tc_unflushed_batch_token; + /* These are transfer flags sent to drivers. */ /* Never infer whether it's safe to use unsychronized mappings: */ #define TC_TRANSFER_MAP_NO_INFER_UNSYNCHRONIZED (1u << 29) @@ -172,6 +199,10 @@ /* transfer_map is called from a non-driver thread: */ #define TC_TRANSFER_MAP_THREADED_UNSYNC (1u << 31) +/* Custom flush flags sent to drivers. */ +/* fence is pre-populated with a fence created by the create_fence callback */ +#define TC_FLUSH_ASYNC (1u << 31) + /* Size of the queue = number of batch slots in memory. * - 1 batch is always idle and records new commands * - 1 batch is being executed @@ -204,6 +235,8 @@ typedef void (*tc_replace_buffer_storage_func)(struct pipe_context *ctx, struct pipe_resource *dst, struct pipe_resource *src); +typedef struct pipe_fence_handle *(*tc_create_fence_func)(struct pipe_context *ctx, + struct tc_unflushed_batch_token *token); struct threaded_resource { struct pipe_resource b; @@ -293,10 +326,21 @@ struct ALIGN16 tc_call { union tc_payload payload; }; +/** + * A token representing an unflushed batch. + * + * See the general rules for fences for an explanation. + */ +struct tc_unflushed_batch_token { + struct pipe_reference ref; + struct threaded_context *tc; +}; + struct tc_batch { struct pipe_context *pipe; unsigned sentinel; unsigned num_total_call_slots; + struct tc_unflushed_batch_token *token; struct util_queue_fence fence; struct tc_call call[TC_CALLS_PER_BATCH]; }; @@ -306,6 +350,7 @@ struct threaded_context { struct pipe_context *pipe; struct slab_child_pool pool_transfers; tc_replace_buffer_storage_func replace_buffer_storage; + tc_create_fence_func create_fence; unsigned map_buffer_alignment; struct list_head unflushed_queries; @@ -330,8 +375,13 @@ 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); + static inline struct threaded_context * threaded_context(struct pipe_context *pipe) { @@ -356,4 +406,13 @@ threaded_transfer(struct pipe_transfer *transfer) return (struct threaded_transfer*)transfer; } +static inline void +tc_unflushed_batch_token_reference(struct tc_unflushed_batch_token **dst, + struct tc_unflushed_batch_token *src) +{ + if (pipe_reference((struct pipe_reference *)*dst, (struct pipe_reference *)src)) + free(*dst); + *dst = src; +} + #endif |