FYI, I've already committed this because our other team needs this bug fix.
Marek On Thu, Aug 25, 2016 at 10:56 AM, Marek Olšák <mar...@gmail.com> wrote: > From: Marek Olšák <marek.ol...@amd.com> > > We can take advantage of the fact that multi_fence does the obvious thing > with NULL fences. > > This fixes unflushed fences that can get stuck due to empty IBs. > --- > src/gallium/drivers/r600/r600_hw_context.c | 8 +------- > src/gallium/drivers/radeon/r600_pipe_common.c | 29 > ++++++++++++++++++--------- > src/gallium/drivers/radeonsi/si_hw_context.c | 13 +++--------- > 3 files changed, 23 insertions(+), 27 deletions(-) > > diff --git a/src/gallium/drivers/r600/r600_hw_context.c > b/src/gallium/drivers/r600/r600_hw_context.c > index 4447393..58ba09d 100644 > --- a/src/gallium/drivers/r600/r600_hw_context.c > +++ b/src/gallium/drivers/r600/r600_hw_context.c > @@ -248,28 +248,22 @@ void r600_flush_emit(struct r600_context *rctx) > rctx->b.flags = 0; > } > > void r600_context_gfx_flush(void *context, unsigned flags, > struct pipe_fence_handle **fence) > { > struct r600_context *ctx = context; > struct radeon_winsys_cs *cs = ctx->b.gfx.cs; > struct radeon_winsys *ws = ctx->b.ws; > > - if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size) && > - (!fence || ctx->b.last_gfx_fence)) { > - if (fence) > - ws->fence_reference(fence, ctx->b.last_gfx_fence); > - if (!(flags & RADEON_FLUSH_ASYNC)) > - ws->cs_sync_flush(cs); > + if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size)) > return; > - } > > r600_preflush_suspend_features(&ctx->b); > > /* flush the framebuffer cache */ > ctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV | > R600_CONTEXT_FLUSH_AND_INV_CB | > R600_CONTEXT_FLUSH_AND_INV_DB | > R600_CONTEXT_FLUSH_AND_INV_CB_META | > R600_CONTEXT_FLUSH_AND_INV_DB_META | > R600_CONTEXT_WAIT_3D_IDLE | > diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c > b/src/gallium/drivers/radeon/r600_pipe_common.c > index ab620eb..b1da22f 100644 > --- a/src/gallium/drivers/radeon/r600_pipe_common.c > +++ b/src/gallium/drivers/radeon/r600_pipe_common.c > @@ -258,54 +258,63 @@ void r600_postflush_resume_features(struct > r600_common_context *ctx) > if (!LIST_IS_EMPTY(&ctx->active_queries)) > r600_resume_queries(ctx); > } > > 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; > 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) { > rctx->dma.flush(rctx, rflags, fence ? &sdma_fence : NULL); > } > > - /* Instead of flushing, create a deferred fence. Constraints: > - * - The state tracker must allow a deferred flush. > - * - The state tracker must request a fence. > - * Thread safety in fence_finish must be ensured by the state tracker. > - */ > - if (flags & PIPE_FLUSH_DEFERRED && fence) { > - gfx_fence = rctx->ws->cs_get_next_fence(rctx->gfx.cs); > - deferred_fence = true; > + 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 { > - rctx->gfx.flush(rctx, rflags, fence ? &gfx_fence : NULL); > + /* Instead of flushing, create a deferred fence. Constraints: > + * - The state tracker must allow a deferred flush. > + * - The state tracker must request a fence. > + * Thread safety in fence_finish must be ensured by the state > tracker. > + */ > + if (flags & PIPE_FLUSH_DEFERRED && fence) { > + gfx_fence = rctx->ws->cs_get_next_fence(rctx->gfx.cs); > + deferred_fence = true; > + } else { > + rctx->gfx.flush(rctx, rflags, fence ? &gfx_fence : > NULL); > + } > } > > /* Both engines can signal out of order, so we need to keep both > fences. */ > - if (gfx_fence || sdma_fence) { > + if (fence) { > struct r600_multi_fence *multi_fence = > CALLOC_STRUCT(r600_multi_fence); > if (!multi_fence) > return; > > multi_fence->reference.count = 1; > + /* If both fences are NULL, fence_finish will always return > true. */ > multi_fence->gfx = gfx_fence; > multi_fence->sdma = sdma_fence; > > if (deferred_fence) { > multi_fence->gfx_unflushed.ctx = rctx; > multi_fence->gfx_unflushed.ib_index = > rctx->num_gfx_cs_flushes; > } > > screen->fence_reference(screen, fence, NULL); > *fence = (struct pipe_fence_handle*)multi_fence; > diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c > b/src/gallium/drivers/radeonsi/si_hw_context.c > index 49d1a35..aeccb2d 100644 > --- a/src/gallium/drivers/radeonsi/si_hw_context.c > +++ b/src/gallium/drivers/radeonsi/si_hw_context.c > @@ -93,31 +93,24 @@ void si_need_cs_space(struct si_context *ctx) > void si_context_gfx_flush(void *context, unsigned flags, > struct pipe_fence_handle **fence) > { > struct si_context *ctx = context; > struct radeon_winsys_cs *cs = ctx->b.gfx.cs; > struct radeon_winsys *ws = ctx->b.ws; > > if (ctx->gfx_flush_in_progress) > return; > > - ctx->gfx_flush_in_progress = true; > - > - if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size) && > - (!fence || ctx->b.last_gfx_fence)) { > - if (fence) > - ws->fence_reference(fence, ctx->b.last_gfx_fence); > - if (!(flags & RADEON_FLUSH_ASYNC)) > - ws->cs_sync_flush(cs); > - ctx->gfx_flush_in_progress = false; > + if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size)) > return; > - } > + > + 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 | > SI_CONTEXT_INV_VMEM_L1; > -- > 2.7.4 > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev