[Mesa-dev] [PATCH 6/7] radeonsi: implement pipe_context::server_fence_sync
Nicolai Hähnle
nhaehnle at gmail.com
Mon Sep 11 14:03:07 UTC 2017
On 06.09.2017 11:34, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> This will be more useful once we have sync_file support.
> ---
> src/gallium/drivers/radeon/r600_pipe_common.c | 44 +++++++++++++++++++++++++++
> src/gallium/drivers/radeon/radeon_winsys.h | 7 +++++
> src/gallium/winsys/amdgpu/drm/amdgpu_cs.c | 16 ++++++++++
> 3 files changed, 67 insertions(+)
>
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 5e05b60..46a5aa1 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -387,20 +387,63 @@ void r600_postflush_resume_features(struct r600_common_context *ctx)
> if (ctx->streamout.suspended) {
> ctx->streamout.append_bitmask = ctx->streamout.enabled_mask;
> r600_streamout_buffers_dirty(ctx);
> }
>
> /* resume queries */
> if (!LIST_IS_EMPTY(&ctx->active_queries))
> r600_resume_queries(ctx);
> }
>
> +static void r600_add_fence_dependency(struct r600_common_context *rctx,
> + struct pipe_fence_handle *fence)
> +{
> + struct radeon_winsys *ws = rctx->ws;
> +
> + if (rctx->dma.cs)
> + ws->cs_add_fence_dependency(rctx->dma.cs, fence);
> + ws->cs_add_fence_dependency(rctx->gfx.cs, fence);
> +}
> +
> +static void r600_fence_server_sync(struct pipe_context *ctx,
> + struct pipe_fence_handle *fence)
> +{
> + struct r600_common_context *rctx = (struct r600_common_context *)ctx;
> + struct r600_multi_fence *rfence = (struct r600_multi_fence *)fence;
> +
> + /* Only amdgpu needs to handle fence dependencies.
> + * radeon synchronizes all rings by default.
> + */
> + if (rctx->screen->info.drm_major == 2)
> + return;
Technically this is only true if we never import fences, since fences
could be from a different device. So I think the comment should say
"radeon synchronizes all rings by default and will not implement fence
imports" or something like that.
With that, the series is
Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>
> +
> + /* Only imported fences need to be handled by fence_server_sync,
> + * because the winsys handles synchronizations automatically for BOs
> + * within the process.
> + *
> + * Simply skip unflushed fences here, and the winsys will drop no-op
> + * dependencies (i.e. dependencies within the same ring).
> + */
> + if (rfence->gfx_unflushed.ctx)
> + return;
> +
> + /* All unflushed commands will not start execution before
> + * this fence dependency is signalled.
> + *
> + * Should we flush the context to allow more GPU parallelism?
> + */
> + if (rfence->sdma)
> + r600_add_fence_dependency(rctx, rfence->sdma);
> + if (rfence->gfx)
> + r600_add_fence_dependency(rctx, rfence->gfx);
> +}
> +
> static void r600_flush_from_st(struct pipe_context *ctx,
> struct pipe_fence_handle **fence,
> unsigned flags)
> {
> struct pipe_screen *screen = ctx->screen;
> struct r600_common_context *rctx = (struct r600_common_context *)ctx;
> struct radeon_winsys *ws = rctx->ws;
> struct pipe_fence_handle *gfx_fence = NULL;
> struct pipe_fence_handle *sdma_fence = NULL;
> bool deferred_fence = false;
> @@ -660,20 +703,21 @@ bool r600_common_context_init(struct r600_common_context *rctx,
>
> rctx->b.invalidate_resource = r600_invalidate_resource;
> rctx->b.resource_commit = r600_resource_commit;
> rctx->b.transfer_map = u_transfer_map_vtbl;
> rctx->b.transfer_flush_region = u_transfer_flush_region_vtbl;
> rctx->b.transfer_unmap = u_transfer_unmap_vtbl;
> rctx->b.texture_subdata = u_default_texture_subdata;
> rctx->b.memory_barrier = r600_memory_barrier;
> rctx->b.flush = r600_flush_from_st;
> rctx->b.set_debug_callback = r600_set_debug_callback;
> + rctx->b.fence_server_sync = r600_fence_server_sync;
> rctx->dma_clear_buffer = r600_dma_clear_buffer_fallback;
>
> /* evergreen_compute.c has a special codepath for global buffers.
> * Everything else can use the direct path.
> */
> if ((rscreen->chip_class == EVERGREEN || rscreen->chip_class == CAYMAN) &&
> (context_flags & PIPE_CONTEXT_COMPUTE_ONLY))
> rctx->b.buffer_subdata = u_default_buffer_subdata;
> else
> rctx->b.buffer_subdata = r600_buffer_subdata;
> diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h
> index f0a0a92..99e22e0 100644
> --- a/src/gallium/drivers/radeon/radeon_winsys.h
> +++ b/src/gallium/drivers/radeon/radeon_winsys.h
> @@ -567,20 +567,27 @@ struct radeon_winsys {
> enum radeon_feature_id fid,
> bool enable);
> /**
> * Make sure all asynchronous flush of the cs have completed
> *
> * \param cs A command stream.
> */
> void (*cs_sync_flush)(struct radeon_winsys_cs *cs);
>
> /**
> + * Add a fence dependency to the CS, so that the CS will wait for
> + * the fence before execution.
> + */
> + void (*cs_add_fence_dependency)(struct radeon_winsys_cs *cs,
> + struct pipe_fence_handle *fence);
> +
> + /**
> * Wait for the fence and return true if the fence has been signalled.
> * The timeout of 0 will only return the status.
> * The timeout of PIPE_TIMEOUT_INFINITE will always wait until the fence
> * is signalled.
> */
> bool (*fence_wait)(struct radeon_winsys *ws,
> struct pipe_fence_handle *fence,
> uint64_t timeout);
>
> /**
> diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
> index ca6021c..1d7ea34 100644
> --- a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
> +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
> @@ -929,20 +929,35 @@ static bool is_noop_fence_dependency(struct amdgpu_cs *acs,
>
> if (fence->ctx == acs->ctx &&
> fence->fence.ip_type == cs->request.ip_type &&
> fence->fence.ip_instance == cs->request.ip_instance &&
> fence->fence.ring == cs->request.ring)
> return true;
>
> return amdgpu_fence_wait((void *)fence, 0, false);
> }
>
> +static void amdgpu_cs_add_fence_dependency(struct radeon_winsys_cs *rws,
> + struct pipe_fence_handle *pfence)
> +{
> + struct amdgpu_cs *acs = amdgpu_cs(rws);
> + struct amdgpu_cs_context *cs = acs->csc;
> + struct amdgpu_fence *fence = (struct amdgpu_fence*)pfence;
> +
> + if (is_noop_fence_dependency(acs, fence))
> + return;
> +
> + unsigned idx = add_fence_dependency_entry(cs);
> + amdgpu_fence_reference(&cs->fence_dependencies[idx],
> + (struct pipe_fence_handle*)fence);
> +}
> +
> static void amdgpu_add_bo_fence_dependencies(struct amdgpu_cs *acs,
> struct amdgpu_cs_buffer *buffer)
> {
> struct amdgpu_cs_context *cs = acs->csc;
> struct amdgpu_winsys_bo *bo = buffer->bo;
> unsigned new_num_fences = 0;
>
> for (unsigned j = 0; j < bo->num_fences; ++j) {
> struct amdgpu_fence *bo_fence = (void *)bo->fences[j];
>
> @@ -1390,13 +1405,14 @@ void amdgpu_cs_init_functions(struct amdgpu_winsys *ws)
> ws->base.cs_create = amdgpu_cs_create;
> ws->base.cs_destroy = amdgpu_cs_destroy;
> ws->base.cs_add_buffer = amdgpu_cs_add_buffer;
> ws->base.cs_validate = amdgpu_cs_validate;
> ws->base.cs_check_space = amdgpu_cs_check_space;
> ws->base.cs_get_buffer_list = amdgpu_cs_get_buffer_list;
> ws->base.cs_flush = amdgpu_cs_flush;
> ws->base.cs_get_next_fence = amdgpu_cs_get_next_fence;
> ws->base.cs_is_buffer_referenced = amdgpu_bo_is_referenced;
> ws->base.cs_sync_flush = amdgpu_cs_sync_flush;
> + ws->base.cs_add_fence_dependency = amdgpu_cs_add_fence_dependency;
> ws->base.fence_wait = amdgpu_fence_wait_rel_timeout;
> ws->base.fence_reference = amdgpu_fence_reference;
> }
>
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the mesa-dev
mailing list