freedreno: avoid no-op flushes by re-using last-fence
authorRob Clark <robdclark@gmail.com>
Thu, 4 Oct 2018 12:05:49 +0000 (08:05 -0400)
committerRob Clark <robdclark@gmail.com>
Fri, 26 Oct 2018 22:10:00 +0000 (18:10 -0400)
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>
src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
src/gallium/drivers/freedreno/freedreno_context.c
src/gallium/drivers/freedreno/freedreno_context.h
src/gallium/drivers/freedreno/freedreno_draw.c
src/gallium/drivers/freedreno/freedreno_resource.c

index c962fe7997075ecd89135e8211b6f166f44ca705..30840955b61cb8554f7ed3082b04e6c5c1c990b0 100644 (file)
@@ -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);
index 5c56be29b1394cf9f46731f5c3c52100b99bf0b9..a08acea7a48d302e759b8a2871cdd9f18c7f35ac 100644 (file)
@@ -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);
 
index 2ebfaca2e5f29058af351f767998165a1ae7ad4a..01038d309199503929df1bf8ab3958c83d17e60e 100644 (file)
@@ -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.
         */
index 5f9706c0b6e9b8a3f477717c29e82c8d25c4bf15..02ea41e2c4e4ef7be9acdbc12b405138dd05cce3 100644 (file)
@@ -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);
index 759ae7d28ae6f4f4926178265c8dbf7747bbb154..54d738589626a6d2d3235f05f14afc5302121303 100644 (file)
@@ -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);