diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.c b/src/gallium/drivers/freedreno/a6xx/fd6_context.c index 4dcaf03b156..69de576b848 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.c @@ -192,7 +192,7 @@ fd6_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) fd6_blitter_init(pctx); fd6_ctx->border_color_uploader = u_upload_create(pctx, 4096, 0, - PIPE_USAGE_STREAM, 0); + PIPE_USAGE_STREAM, 0); - return pctx; + return fd_context_init_tc(pctx, flags); } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.c b/src/gallium/drivers/freedreno/a6xx/fd6_program.c index 125da7daebe..f9c400914a1 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_program.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.c @@ -1072,6 +1072,8 @@ fd6_program_create(void *data, struct ir3_shader_variant *bs, struct fd_context *ctx = fd_context(data); struct fd6_program_state *state = CALLOC_STRUCT(fd6_program_state); + tc_assert_driver_thread(ctx->tc); + /* if we have streamout, use full VS in binning pass, as the * binning pass VS will have outputs on other than position/psize * stripped out: diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c index 951f8a261fd..a0cf5ec2adb 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c @@ -112,6 +112,8 @@ void fd6_validate_format(struct fd_context *ctx, struct fd_resource *rsc, enum pipe_format format) { + tc_assert_driver_thread(ctx->tc); + if (!rsc->layout.ubwc) return; diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c index 614e04b5357..b922766b28c 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c @@ -339,6 +339,9 @@ fd6_sampler_view_update(struct fd_context *ctx, struct fd6_pipe_sampler_view *so } } +/* NOTE this can be called in either driver thread or frontend thread + * depending on where the last unref comes from + */ static void fd6_sampler_view_destroy(struct pipe_context *pctx, struct pipe_sampler_view *_view) diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 93c57e4a6b0..49520e969d3 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -249,6 +249,8 @@ fd_context_batch(struct fd_context *ctx) { struct fd_batch *batch = NULL; + tc_assert_driver_thread(ctx->tc); + fd_batch_reference(&batch, ctx->batch); if (unlikely(!batch)) { @@ -613,3 +615,29 @@ fail: pctx->destroy(pctx); return NULL; } + +struct pipe_context * +fd_context_init_tc(struct pipe_context *pctx, unsigned flags) +{ + struct fd_context *ctx = fd_context(pctx); + + if (!(flags & PIPE_CONTEXT_PREFER_THREADED)) + return pctx; + + /* Clover (compute-only) is unsupported. */ + if (flags & PIPE_CONTEXT_COMPUTE_ONLY) + return pctx; + + struct pipe_context *tc = threaded_context_create(pctx, + &ctx->screen->transfer_pool, + fd_replace_buffer_storage, + NULL, // TODO fd_create_fence for async flush + &ctx->tc); + + uint64_t total_ram; + if (tc && tc != pctx && os_get_total_physical_memory(&total_ram)) { + ((struct threaded_context *) tc)->bytes_mapped_limit = total_ram / 16; + } + + return tc; +} diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 491746590c4..06ae46b5af3 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -182,6 +182,8 @@ struct ir3_shader_key; struct fd_context { struct pipe_context base; + struct threaded_context *tc; + struct list_head node; /* node in screen->context_list */ /* We currently need to serialize emitting GMEM batches, because of @@ -549,6 +551,7 @@ void fd_emit_string5(struct fd_ringbuffer *ring, const char *string, int len); struct pipe_context * fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, const uint8_t *primtypes, void *priv, unsigned flags); +struct pipe_context * fd_context_init_tc(struct pipe_context *pctx, unsigned flags); void fd_context_destroy(struct pipe_context *pctx) assert_dt; diff --git a/src/gallium/drivers/freedreno/freedreno_query_acc.c b/src/gallium/drivers/freedreno/freedreno_query_acc.c index 5603a6cf83a..6fb0816ac3e 100644 --- a/src/gallium/drivers/freedreno/freedreno_query_acc.c +++ b/src/gallium/drivers/freedreno/freedreno_query_acc.c @@ -157,6 +157,9 @@ fd_acc_get_query_result(struct fd_context *ctx, struct fd_query *q, int ret; if (pending(rsc, false)) { + assert(!q->base.flushed); + tc_assert_driver_thread(ctx->tc); + /* piglit spec@arb_occlusion_query@occlusion_query_conform * test, and silly apps perhaps, get stuck in a loop trying * to get query result forever with wait==false.. we don't @@ -180,6 +183,7 @@ fd_acc_get_query_result(struct fd_context *ctx, struct fd_query *q, } if (rsc->track->write_batch) { + tc_assert_driver_thread(ctx->tc); fd_context_access_begin(ctx); fd_batch_flush(rsc->track->write_batch); fd_context_access_end(ctx); diff --git a/src/gallium/drivers/freedreno/freedreno_query_hw.c b/src/gallium/drivers/freedreno/freedreno_query_hw.c index 6fbe365a93b..9eb025954a5 100644 --- a/src/gallium/drivers/freedreno/freedreno_query_hw.c +++ b/src/gallium/drivers/freedreno/freedreno_query_hw.c @@ -213,6 +213,9 @@ fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, struct fd_resource *rsc = fd_resource(period->end->prsc); if (pending(rsc, false)) { + assert(!q->base.flushed); + tc_assert_driver_thread(ctx->tc); + /* piglit spec@arb_occlusion_query@occlusion_query_conform * test, and silly apps perhaps, get stuck in a loop trying * to get query result forever with wait==false.. we don't @@ -251,6 +254,7 @@ fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, struct fd_resource *rsc = fd_resource(start->prsc); if (rsc->track->write_batch) { + tc_assert_driver_thread(ctx->tc); fd_context_access_begin(ctx); fd_batch_flush(rsc->track->write_batch); fd_context_access_end(ctx); diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 2c0a7c089eb..b8c89b223ef 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -487,6 +487,8 @@ fd_try_shadow_resource(struct fd_context *ctx, struct fd_resource *rsc, void fd_resource_uncompress(struct fd_context *ctx, struct fd_resource *rsc) { + tc_assert_driver_thread(ctx->tc); + bool success = fd_try_shadow_resource(ctx, rsc, 0, NULL, FD_FORMAT_MOD_QCOM_TILED); @@ -744,6 +746,8 @@ resource_transfer_map(struct pipe_context *pctx, char *buf; int ret = 0; + tc_assert_driver_thread(ctx->tc); + /* we always need a staging texture for tiled buffers: * * TODO we might sometimes want to *also* shadow the resource to avoid