freedreno: flush immediately when reading a pending batch
authorRob Clark <robdclark@gmail.com>
Tue, 17 Jul 2018 14:02:51 +0000 (10:02 -0400)
committerRob Clark <robdclark@gmail.com>
Tue, 17 Jul 2018 15:00:00 +0000 (11:00 -0400)
Instead of the reading batch setting a dependency on the writing batch,
simply flush the writing batch immediately.  This avoids situations
where we have to flush the context's current batch later.

Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/freedreno_batch.c
src/gallium/drivers/freedreno/freedreno_context.c

index 6244e3b..b6f030a 100644 (file)
@@ -362,20 +362,27 @@ fd_batch_add_dep(struct fd_batch *batch, struct fd_batch *dep)
        if (batch->dependents_mask & (1 << dep->idx))
                return;
 
-       /* if the new depedency already depends on us, we need to flush
-        * to avoid a loop in the dependency graph.
-        */
-       if (batch_depends_on(dep, batch)) {
-               DBG("%p: flush forced on %p!", batch, dep);
-               mtx_unlock(&batch->ctx->screen->lock);
-               fd_batch_flush(dep, false, false);
-               mtx_lock(&batch->ctx->screen->lock);
-       } else {
-               struct fd_batch *other = NULL;
-               fd_batch_reference_locked(&other, dep);
-               batch->dependents_mask |= (1 << dep->idx);
-               DBG("%p: added dependency on %p", batch, dep);
-       }
+       /* a loop should not be possible */
+       debug_assert(!batch_depends_on(dep, batch));
+
+       struct fd_batch *other = NULL;
+       fd_batch_reference_locked(&other, dep);
+       batch->dependents_mask |= (1 << dep->idx);
+       DBG("%p: added dependency on %p", batch, dep);
+}
+
+static void
+flush_write_batch(struct fd_resource *rsc)
+{
+       struct fd_batch *b = NULL;
+       fd_batch_reference(&b, rsc->write_batch);
+
+       mtx_unlock(&b->ctx->screen->lock);
+       fd_batch_flush(b, true, false);
+       mtx_lock(&b->ctx->screen->lock);
+
+       fd_bc_invalidate_batch(b, false);
+       fd_batch_reference_locked(&b, NULL);
 }
 
 void
@@ -397,21 +404,12 @@ fd_batch_resource_used(struct fd_batch *batch, struct fd_resource *rsc, bool wri
 
        if (write) {
                /* if we are pending read or write by any other batch: */
-               if (rsc->batch_mask != (1 << batch->idx)) {
+               if (rsc->batch_mask & ~(1 << batch->idx)) {
                        struct fd_batch_cache *cache = &batch->ctx->screen->batch_cache;
                        struct fd_batch *dep;
 
-                       if (rsc->write_batch && rsc->write_batch != batch) {
-                               struct fd_batch *b = NULL;
-                               fd_batch_reference(&b, rsc->write_batch);
-
-                               mtx_unlock(&batch->ctx->screen->lock);
-                               fd_batch_flush(b, true, false);
-                               mtx_lock(&batch->ctx->screen->lock);
-
-                               fd_bc_invalidate_batch(b, false);
-                               fd_batch_reference_locked(&b, NULL);
-                       }
+                       if (rsc->write_batch && rsc->write_batch != batch)
+                               flush_write_batch(rsc);
 
                        foreach_batch(dep, cache, rsc->batch_mask) {
                                struct fd_batch *b = NULL;
@@ -429,10 +427,12 @@ fd_batch_resource_used(struct fd_batch *batch, struct fd_resource *rsc, bool wri
                }
                fd_batch_reference_locked(&rsc->write_batch, batch);
        } else {
-               if (rsc->write_batch) {
-                       fd_batch_add_dep(batch, rsc->write_batch);
-                       fd_bc_invalidate_batch(rsc->write_batch, false);
-               }
+               /* If reading a resource pending a write, go ahead and flush the
+                * writer.  This avoids situations where we end up having to
+                * flush the current batch in _resource_used()
+                */
+               if (rsc->write_batch && rsc->write_batch != batch)
+                       flush_write_batch(rsc);
        }
 
        if (rsc->batch_mask & (1 << batch->idx))
index 9c6a21c..e1324e8 100644 (file)
@@ -101,6 +101,8 @@ fd_emit_string_marker(struct pipe_context *pctx, const char *string, int len)
        if (!ctx->batch)
                return;
 
+       ctx->batch->needs_flush = true;
+
        ring = ctx->batch->draw;
 
        /* max packet size is 0x3fff dwords: */