From: Rob Clark Date: Wed, 12 Oct 2016 14:42:57 +0000 (-0400) Subject: freedreno: no-op render when we need a fence X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=534917495dca07bb63dbec49450c706fce36f176;p=mesa.git freedreno: no-op render when we need a fence If app tries to create a fence but there is no rendering to submit, we need a dummy/no-op submit. Use a string-marker for the purpose.. mostly since it avoids needing to realize that the packet format changes in later gen's (so one less place to fixup for a5xx). Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 03645075bdc..1128d918b52 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -53,8 +53,17 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, fd_bc_flush(&ctx->screen->batch_cache, ctx); } - if (fence) + if (fence) { + /* if there hasn't been any rendering submitted yet, we might not + * have actually created a fence + */ + if (!ctx->last_fence || ctx->batch->needs_out_fence_fd) { + ctx->batch->needs_flush = true; + fd_gmem_render_noop(ctx->batch); + fd_batch_reset(ctx->batch); + } fd_fence_ref(pctx->screen, fence, ctx->last_fence); + } } /** diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c index 69fb16d058b..aeccebd9fd2 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.c +++ b/src/gallium/drivers/freedreno/freedreno_gmem.c @@ -359,6 +359,20 @@ render_sysmem(struct fd_batch *batch) fd_reset_wfi(batch); } +static void +flush_ring(struct fd_batch *batch) +{ + struct fd_context *ctx = batch->ctx; + int out_fence_fd = -1; + + fd_ringbuffer_flush2(batch->gmem, batch->in_fence_fd, + batch->needs_out_fence_fd ? &out_fence_fd : NULL); + + fd_fence_ref(&ctx->screen->base, &ctx->last_fence, NULL); + ctx->last_fence = fd_fence_create(ctx, + fd_ringbuffer_timestamp(batch->gmem), out_fence_fd); +} + void fd_gmem_render_tiles(struct fd_batch *batch) { @@ -399,13 +413,22 @@ fd_gmem_render_tiles(struct fd_batch *batch) ctx->stats.batch_gmem++; } - int out_fence_fd = -1; - fd_ringbuffer_flush2(batch->gmem, batch->in_fence_fd, - batch->needs_out_fence_fd ? &out_fence_fd : NULL); + flush_ring(batch); +} - fd_fence_ref(&ctx->screen->base, &ctx->last_fence, NULL); - ctx->last_fence = fd_fence_create(ctx, - fd_ringbuffer_timestamp(batch->gmem), out_fence_fd); +/* special case for when we need to create a fence but have no rendering + * to flush.. just emit a no-op string-marker packet. + */ +void +fd_gmem_render_noop(struct fd_batch *batch) +{ + struct fd_context *ctx = batch->ctx; + struct pipe_context *pctx = &ctx->base; + + pctx->emit_string_marker(pctx, "noop", 4); + /* emit IB to drawcmds (which contain the string marker): */ + ctx->emit_ib(batch->gmem, batch->draw); + flush_ring(batch); } /* tile needs restore if it isn't completely contained within the diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.h b/src/gallium/drivers/freedreno/freedreno_gmem.h index 116423a40e2..6598ea9cc8b 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.h +++ b/src/gallium/drivers/freedreno/freedreno_gmem.h @@ -62,6 +62,7 @@ struct fd_gmem_stateobj { struct fd_batch; void fd_gmem_render_tiles(struct fd_batch *batch); +void fd_gmem_render_noop(struct fd_batch *batch); bool fd_gmem_needs_restore(struct fd_batch *batch, struct fd_tile *tile, uint32_t buffers);