[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