From: Rob Clark Date: Tue, 17 Jul 2018 14:02:51 +0000 (-0400) Subject: freedreno: flush immediately when reading a pending batch X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f129971e71ccc8c711ccfc01d5adad7e30687549;p=mesa.git freedreno: flush immediately when reading a pending batch 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 --- diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c b/src/gallium/drivers/freedreno/freedreno_batch.c index 6244e3bcc25..b6f030ac903 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.c +++ b/src/gallium/drivers/freedreno/freedreno_batch.c @@ -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)) diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 9c6a21ca5b8..e1324e8c0af 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -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: */