summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2016-10-12 10:42:57 -0400
committerRob Clark <[email protected]>2016-12-01 20:24:59 -0500
commit534917495dca07bb63dbec49450c706fce36f176 (patch)
tree18302e519921619aba94a93c2d2579682586cf08
parent0b98e84e9ba082b9aa00b24fded3fb56224c6fc6 (diff)
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 <[email protected]>
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.c11
-rw-r--r--src/gallium/drivers/freedreno/freedreno_gmem.c35
-rw-r--r--src/gallium/drivers/freedreno/freedreno_gmem.h1
3 files changed, 40 insertions, 7 deletions
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);