summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2018-10-04 08:05:49 -0400
committerRob Clark <robdclark@gmail.com>2018-10-26 18:10:00 -0400
commitddb7fadaf8b1aa3004e72d6b0e28e465f8f45fba (patch)
tree538551a48ca92cd881434242674df62e6df7cc1f /src
parent01194cd5826fb58a4f9464594850ffc3f4ae6073 (diff)
freedreno: avoid no-op flushes by re-using last-fence
Noticed that with webgl (in chromium, at least) we end up generating a lot of no-op submits just to get a fence. Tracking the last fence and returning that if there is no rendering since last flush avoids this. Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_blitter.c3
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.c19
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.h6
-rw-r--r--src/gallium/drivers/freedreno/freedreno_draw.c5
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c3
5 files changed, 34 insertions, 2 deletions
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
index c962fe79970..30840955b61 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
@@ -28,6 +28,7 @@
#include "util/u_dump.h"
#include "freedreno_blitter.h"
+#include "freedreno_fence.h"
#include "freedreno_resource.h"
#include "fd6_blitter.h"
@@ -486,6 +487,8 @@ fd6_blit(struct pipe_context *pctx, const struct pipe_blit_info *info)
return;
}
+ fd_fence_ref(pctx->screen, &ctx->last_fence, NULL);
+
batch = fd_bc_alloc_batch(&ctx->screen->batch_cache, ctx, true);
fd6_emit_restore(batch, batch->draw);
diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c
index 5c56be29b13..a08acea7a48 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.c
+++ b/src/gallium/drivers/freedreno/freedreno_context.c
@@ -49,14 +49,24 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
DBG("%p: flush: flags=%x\n", ctx->batch, flags);
+ /* if no rendering since last flush, ie. app just decided it needed
+ * a fence, re-use the last one:
+ */
+ if (ctx->last_fence) {
+ fd_fence_ref(pctx->screen, &fence, ctx->last_fence);
+ goto out;
+ }
+
if (!batch)
return;
/* Take a ref to the batch's fence (batch can be unref'd when flushed: */
fd_fence_ref(pctx->screen, &fence, batch->fence);
- if (flags & PIPE_FLUSH_FENCE_FD)
- batch->needs_out_fence_fd = true;
+ /* TODO is it worth trying to figure out if app is using fence-fd's, to
+ * avoid requesting one every batch?
+ */
+ batch->needs_out_fence_fd = true;
if (!ctx->screen->reorder) {
fd_batch_flush(batch, true, false);
@@ -66,9 +76,12 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
fd_bc_flush(&ctx->screen->batch_cache, ctx);
}
+out:
if (fencep)
fd_fence_ref(pctx->screen, fencep, fence);
+ fd_fence_ref(pctx->screen, &ctx->last_fence, fence);
+
fd_fence_ref(pctx->screen, &fence, NULL);
}
@@ -137,6 +150,8 @@ fd_context_destroy(struct pipe_context *pctx)
DBG("");
+ fd_fence_ref(pctx->screen, &ctx->last_fence, NULL);
+
if (ctx->screen->reorder && util_queue_is_initialized(&ctx->flush_queue))
util_queue_destroy(&ctx->flush_queue);
diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h
index 2ebfaca2e5f..01038d30919 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.h
+++ b/src/gallium/drivers/freedreno/freedreno_context.h
@@ -230,6 +230,12 @@ struct fd_context {
*/
struct fd_batch *batch;
+ /* NULL if there has been rendering since last flush. Otherwise
+ * keeps a reference to the last fence so we can re-use it rather
+ * than having to flush no-op batch.
+ */
+ struct pipe_fence_handle *last_fence;
+
/* Are we in process of shadowing a resource? Used to detect recursion
* in transfer_map, and skip unneeded synchronization.
*/
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index 5f9706c0b6e..02ea41e2c4e 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -34,6 +34,7 @@
#include "freedreno_draw.h"
#include "freedreno_context.h"
+#include "freedreno_fence.h"
#include "freedreno_state.h"
#include "freedreno_resource.h"
#include "freedreno_query_acc.h"
@@ -98,6 +99,8 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
return;
}
+ fd_fence_ref(pctx->screen, &ctx->last_fence, NULL);
+
/* Upload a user index buffer. */
struct pipe_resource *indexbuf = NULL;
unsigned index_offset = 0;
@@ -382,6 +385,8 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
if (!fd_render_condition_check(pctx))
return;
+ fd_fence_ref(pctx->screen, &ctx->last_fence, NULL);
+
if (ctx->in_blit) {
fd_batch_reset(batch);
fd_context_all_dirty(ctx);
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c
index 759ae7d28ae..54d73858962 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -35,6 +35,7 @@
#include "freedreno_resource.h"
#include "freedreno_batch_cache.h"
+#include "freedreno_fence.h"
#include "freedreno_screen.h"
#include "freedreno_surface.h"
#include "freedreno_context.h"
@@ -1070,6 +1071,8 @@ void
fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond, bool discard,
enum fd_render_stage stage)
{
+ fd_fence_ref(ctx->base.screen, &ctx->last_fence, NULL);
+
util_blitter_save_fragment_constant_buffer_slot(ctx->blitter,
ctx->constbuf[PIPE_SHADER_FRAGMENT].cb);
util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb);