[Mesa-dev] [PATCH 12/12] radeonsi: turn SDMA IBs into de-facto preambles of GFX IBs

Nicolai Hähnle nhaehnle at gmail.com
Thu Jan 5 15:26:44 UTC 2017


That Deus Ex number is impressive. For the series:

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>

On 02.01.2017 23:54, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> Draw calls no longer flush SDMA IBs. r600_need_dma_space is
> responsible for synchronizing execution between both IBs.
>
> Initial buffer clears and fast clears will stay unflushed in the SDMA IB
> (up to 64 MB) as long as the GFX IB isn't flushed either.
> ---
>  src/gallium/drivers/radeon/r600_pipe_common.c |  4 ++--
>  src/gallium/drivers/radeonsi/si_hw_context.c  | 20 ++++++++++++++++----
>  2 files changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 4d8bb74..28bb791 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -352,23 +352,23 @@ static void r600_flush_from_st(struct pipe_context *ctx,
>  	unsigned rflags = 0;
>  	struct pipe_fence_handle *gfx_fence = NULL;
>  	struct pipe_fence_handle *sdma_fence = NULL;
>  	bool deferred_fence = false;
>
>  	if (flags & PIPE_FLUSH_END_OF_FRAME)
>  		rflags |= RADEON_FLUSH_END_OF_FRAME;
>  	if (flags & PIPE_FLUSH_DEFERRED)
>  		rflags |= RADEON_FLUSH_ASYNC;
>
> -	if (rctx->dma.cs) {
> +	/* DMA IBs are preambles to gfx IBs, therefore must be flushed first. */
> +	if (rctx->dma.cs)
>  		rctx->dma.flush(rctx, rflags, fence ? &sdma_fence : NULL);
> -	}
>
>  	if (!radeon_emitted(rctx->gfx.cs, rctx->initial_gfx_cs_size)) {
>  		if (fence)
>  			ws->fence_reference(&gfx_fence, rctx->last_gfx_fence);
>  		if (!(rflags & RADEON_FLUSH_ASYNC))
>  			ws->cs_sync_flush(rctx->gfx.cs);
>  	} else {
>  		/* Instead of flushing, create a deferred fence. Constraints:
>  		 * - The state tracker must allow a deferred flush.
>  		 * - The state tracker must request a fence.
> diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
> index 87ba316..57eaac9 100644
> --- a/src/gallium/drivers/radeonsi/si_hw_context.c
> +++ b/src/gallium/drivers/radeonsi/si_hw_context.c
> @@ -55,25 +55,27 @@ static unsigned si_ce_needed_cs_space(void)
>  	space += 2;
>
>  	return space;
>  }
>
>  /* initialize */
>  void si_need_cs_space(struct si_context *ctx)
>  {
>  	struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
>  	struct radeon_winsys_cs *ce_ib = ctx->ce_ib;
> -	struct radeon_winsys_cs *dma = ctx->b.dma.cs;
>
> -	/* Flush the DMA IB if it's not empty. */
> -	if (radeon_emitted(dma, 0))
> -		ctx->b.dma.flush(ctx, RADEON_FLUSH_ASYNC, NULL);
> +	/* There is no need to flush the DMA IB here, because
> +	 * r600_need_dma_space always flushes the GFX IB if there is
> +	 * a conflict, which means any unflushed DMA commands automatically
> +	 * precede the GFX IB (= they had no dependency on the GFX IB when
> +	 * they were submitted).
> +	 */
>
>  	/* There are two memory usage counters in the winsys for all buffers
>  	 * that have been added (cs_add_buffer) and two counters in the pipe
>  	 * driver for those that haven't been added yet.
>  	 */
>  	if (unlikely(!radeon_cs_memory_below_limit(ctx->b.screen, ctx->b.gfx.cs,
>  						   ctx->b.vram, ctx->b.gtt))) {
>  		ctx->b.gtt = 0;
>  		ctx->b.vram = 0;
>  		ctx->b.gfx.flush(ctx, RADEON_FLUSH_ASYNC, NULL);
> @@ -99,20 +101,30 @@ void si_context_gfx_flush(void *context, unsigned flags,
>
>  	if (ctx->gfx_flush_in_progress)
>  		return;
>
>  	if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size))
>  		return;
>
>  	if (r600_check_device_reset(&ctx->b))
>  		return;
>
> +	/* If the state tracker is flushing the GFX IB, r600_flush_from_st is
> +	 * responsible for flushing the DMA IB and merging the fences from both.
> +	 * This code is only needed when the driver flushes the GFX IB
> +	 * internally, and it never asks for a fence handle.
> +	 */
> +	if (radeon_emitted(ctx->b.dma.cs, 0)) {
> +		assert(fence == NULL); /* internal flushes only */
> +		ctx->b.dma.flush(ctx, flags, NULL);
> +	}
> +
>  	ctx->gfx_flush_in_progress = true;
>
>  	r600_preflush_suspend_features(&ctx->b);
>
>  	ctx->b.flags |= SI_CONTEXT_CS_PARTIAL_FLUSH |
>  			SI_CONTEXT_PS_PARTIAL_FLUSH;
>
>  	/* DRM 3.1.0 doesn't flush TC for VI correctly. */
>  	if (ctx->b.chip_class == VI && ctx->b.screen->info.drm_minor <= 1)
>  		ctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2 |
>


More information about the mesa-dev mailing list