gallium/u_threaded: Split out options struct

Rather than having an ever increasing list of parameters to
threaded_context_create(), split out a struct for optional
flags and parameters.  This should reduce churn in adding
new options.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13207>
This commit is contained in:
Rob Clark 2021-10-05 16:24:47 -07:00 committed by Marge Bot
parent 1fb63367a8
commit 1c1c43fbab
10 changed files with 63 additions and 68 deletions

View file

@ -457,9 +457,11 @@ static struct pipe_context *noop_create_context(struct pipe_screen *screen,
threaded_context_create(ctx,
&((struct noop_pipe_screen*)screen)->pool_transfers,
noop_replace_buffer_storage,
noop_create_fence,
noop_is_resource_busy,
false, false, NULL);
&(struct threaded_context_options) {
.create_fence = noop_create_fence,
.is_resource_busy = noop_is_resource_busy,
},
NULL);
if (tc && tc != ctx)
threaded_context_init_bytes_mapped_limit((struct threaded_context *)tc, 4);

View file

@ -86,8 +86,7 @@ trace_context_create(struct trace_screen *tr_scr,
struct pipe_context *
trace_context_create_threaded(struct pipe_screen *screen, struct pipe_context *pipe,
tc_replace_buffer_storage_func *replace_buffer,
tc_create_fence_func *create_fence,
tc_is_resource_busy *is_resource_busy);
struct threaded_context_options *options);
#ifdef __cplusplus
}
#endif

View file

@ -333,8 +333,7 @@ trace_context_is_resource_busy(struct pipe_screen *_screen,
struct pipe_context *
trace_context_create_threaded(struct pipe_screen *screen, struct pipe_context *pipe,
tc_replace_buffer_storage_func *replace_buffer,
tc_create_fence_func *create_fence,
tc_is_resource_busy *is_resource_busy)
struct threaded_context_options *options)
{
if (!trace_screens)
return pipe;
@ -353,14 +352,14 @@ trace_context_create_threaded(struct pipe_screen *screen, struct pipe_context *p
struct trace_context *tr_ctx = trace_context(ctx);
tr_ctx->replace_buffer_storage = *replace_buffer;
tr_ctx->create_fence = *create_fence;
tr_scr->is_resource_busy = *is_resource_busy;
tr_ctx->create_fence = options->create_fence;
tr_scr->is_resource_busy = options->is_resource_busy;
tr_ctx->threaded = true;
*replace_buffer = trace_context_replace_buffer_storage;
if (*create_fence)
*create_fence = trace_context_create_fence;
if (*is_resource_busy)
*is_resource_busy = trace_context_is_resource_busy;
if (options->create_fence)
options->create_fence = trace_context_create_fence;
if (options->is_resource_busy)
options->is_resource_busy = trace_context_is_resource_busy;
return ctx;
}

View file

@ -221,7 +221,7 @@ tc_batch_execute(void *job, UNUSED void *gdata, int thread_index)
struct util_queue_fence *fence =
&tc->buffer_lists[batch->buffer_list_index].driver_flushed_fence;
if (tc->driver_calls_flush_notify) {
if (tc->options.driver_calls_flush_notify) {
tc->signal_fences_next_flush[tc->num_signal_fences_next_flush++] = fence;
/* Since our buffer lists are chained as a ring, we need to flush
@ -649,7 +649,7 @@ static bool
tc_is_buffer_busy(struct threaded_context *tc, struct threaded_resource *tbuf,
unsigned map_usage)
{
if (!tc->is_resource_busy)
if (!tc->options.is_resource_busy)
return true;
uint32_t id_hash = tbuf->buffer_id_unique & TC_BUFFER_ID_MASK;
@ -666,7 +666,7 @@ tc_is_buffer_busy(struct threaded_context *tc, struct threaded_resource *tbuf,
/* The buffer isn't referenced by any unflushed batch: we can safely ask to the driver whether
* this buffer is busy or not. */
return tc->is_resource_busy(tc->pipe->screen, tbuf->latest, map_usage);
return tc->options.is_resource_busy(tc->pipe->screen, tbuf->latest, map_usage);
}
void
@ -2613,7 +2613,7 @@ tc_get_device_reset_status(struct pipe_context *_pipe)
struct threaded_context *tc = threaded_context(_pipe);
struct pipe_context *pipe = tc->pipe;
if (!tc->unsynchronized_get_device_reset_status)
if (!tc->options.unsynchronized_get_device_reset_status)
tc_sync(tc);
return pipe->get_device_reset_status(pipe);
@ -2883,7 +2883,7 @@ tc_flush(struct pipe_context *_pipe, struct pipe_fence_handle **fence,
struct pipe_screen *screen = pipe->screen;
bool async = flags & (PIPE_FLUSH_DEFERRED | PIPE_FLUSH_ASYNC);
if (async && tc->create_fence) {
if (async && tc->options.create_fence) {
if (fence) {
struct tc_batch *next = &tc->batch_slots[tc->next];
@ -2896,7 +2896,8 @@ tc_flush(struct pipe_context *_pipe, struct pipe_fence_handle **fence,
next->token->tc = tc;
}
screen->fence_reference(screen, fence, tc->create_fence(pipe, next->token));
screen->fence_reference(screen, fence,
tc->options.create_fence(pipe, next->token));
if (!*fence)
goto out_of_memory;
}
@ -4186,15 +4187,7 @@ void tc_driver_internal_flush_notify(struct threaded_context *tc)
* in pipe_screen.
* \param replace_buffer callback for replacing a pipe_resource's storage
* with another pipe_resource's storage.
* \param create_fence optional callback to create a fence for async flush
* \param is_resource_busy optional callback to tell TC if transfer_map()/etc
* with the given usage would stall
* \param driver_calls_flush_notify whether the driver calls
* tc_driver_internal_flush_notify after every
* driver flush
* \param unsynchronized_get_device_reset_status if true, get_device_reset_status()
* calls will not be synchronized with
* driver thread
* \param options optional TC options/callbacks
* \param out if successful, the threaded_context will be returned here in
* addition to the return value if "out" != NULL
*/
@ -4202,10 +4195,7 @@ 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,
tc_is_resource_busy is_resource_busy,
bool driver_calls_flush_notify,
bool unsynchronized_get_device_reset_status,
const struct threaded_context_options *options,
struct threaded_context **out)
{
struct threaded_context *tc;
@ -4224,17 +4214,16 @@ threaded_context_create(struct pipe_context *pipe,
return NULL;
}
pipe = trace_context_create_threaded(pipe->screen, pipe, &replace_buffer, &create_fence, &is_resource_busy);
if (options)
tc->options = *options;
pipe = trace_context_create_threaded(pipe->screen, pipe, &replace_buffer, &tc->options);
/* The driver context isn't wrapped, so set its "priv" to NULL. */
pipe->priv = NULL;
tc->pipe = pipe;
tc->replace_buffer_storage = replace_buffer;
tc->create_fence = create_fence;
tc->is_resource_busy = is_resource_busy;
tc->driver_calls_flush_notify = driver_calls_flush_notify;
tc->unsynchronized_get_device_reset_status = unsynchronized_get_device_reset_status;
tc->map_buffer_alignment =
pipe->screen->get_param(pipe->screen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT);
tc->ubo_alignment =

View file

@ -408,13 +408,29 @@ struct tc_buffer_list {
BITSET_DECLARE(buffer_list, TC_BUFFER_ID_MASK + 1);
};
/**
* Optional TC parameters/callbacks.
*/
struct threaded_context_options {
tc_create_fence_func create_fence;
tc_is_resource_busy is_resource_busy;
bool driver_calls_flush_notify;
/**
* If true, ctx->get_device_reset_status() will be called without
* synchronizing with driver thread. Drivers can enable this to avoid
* TC syncs if their implementation of get_device_reset_status() is
* safe to call without synchronizing with driver thread.
*/
bool unsynchronized_get_device_reset_status;
};
struct threaded_context {
struct pipe_context base;
struct pipe_context *pipe;
struct slab_child_pool pool_transfers;
tc_replace_buffer_storage_func replace_buffer_storage;
tc_create_fence_func create_fence;
tc_is_resource_busy is_resource_busy;
struct threaded_context_options options;
unsigned map_buffer_alignment;
unsigned ubo_alignment;
@ -425,19 +441,10 @@ struct threaded_context {
unsigned num_direct_slots;
unsigned num_syncs;
bool driver_calls_flush_notify;
bool use_forced_staging_uploads;
bool add_all_gfx_bindings_to_buffer_list;
bool add_all_compute_bindings_to_buffer_list;
/**
* If true, ctx->get_device_reset_status() will be called without
* synchronizing with driver thread. Drivers can enable this to avoid
* TC syncs if their implementation of get_device_reset_status() is
* safe to call without synchronizing with driver thread.
*/
bool unsynchronized_get_device_reset_status;
/* Estimation of how much vram/gtt bytes are mmap'd in
* the current tc_batch.
*/
@ -505,10 +512,7 @@ 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,
tc_is_resource_busy is_resource_busy,
bool driver_calls_flush_notify,
bool unsynchronized_get_device_reset_status,
const struct threaded_context_options *options,
struct threaded_context **out);
void

View file

@ -325,9 +325,6 @@ crocus_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
return threaded_context_create(ctx, &screen->transfer_pool,
crocus_replace_buffer_storage,
NULL, /* TODO: asynchronous flushes? */
NULL,
false,
false,
&ice->thrctx);
}

View file

@ -691,10 +691,11 @@ fd_context_init_tc(struct pipe_context *pctx, unsigned flags)
struct pipe_context *tc = threaded_context_create(
pctx, &ctx->screen->transfer_pool,
fd_replace_buffer_storage,
fd_fence_create_unflushed,
fd_resource_busy,
false,
true,
&(struct threaded_context_options){
.create_fence = fd_fence_create_unflushed,
.is_resource_busy = fd_resource_busy,
.unsynchronized_get_device_reset_status = true,
},
&ctx->tc);
if (tc && tc != pctx)

View file

@ -379,8 +379,5 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
return threaded_context_create(ctx, &screen->transfer_pool,
iris_replace_buffer_storage,
NULL, /* TODO: asynchronous flushes? */
NULL,
false,
false,
&ice->thrctx);
}

View file

@ -862,10 +862,12 @@ static struct pipe_context *si_pipe_create_context(struct pipe_screen *screen, v
struct pipe_context *tc =
threaded_context_create(ctx, &sscreen->pool_transfers,
si_replace_buffer_storage,
sscreen->info.is_amdgpu ? si_create_fence : NULL,
si_is_resource_busy,
true,
false,
&(struct threaded_context_options){
.create_fence = sscreen->info.is_amdgpu ?
si_create_fence : NULL,
.is_resource_busy = si_is_resource_busy,
.driver_calls_flush_notify = true,
},
&((struct si_context *)ctx)->tc);
if (tc && tc != ctx)

View file

@ -4214,8 +4214,13 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
struct threaded_context *tc = (struct threaded_context*)threaded_context_create(&ctx->base, &screen->transfer_pool,
zink_context_replace_buffer_storage,
zink_create_tc_fence_for_tc,
zink_context_is_resource_busy, true, true, &ctx->tc);
&(struct threaded_context_options){
.create_fence = zink_create_tc_fence_for_tc,
.is_resource_busy = zink_context_is_resource_busy,
.driver_calls_flush_notify = true,
.unsynchronized_get_device_reset_status = true,
},
&ctx->tc);
if (tc && (struct zink_context*)tc != ctx) {
threaded_context_init_bytes_mapped_limit(tc, 4);