aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2018-07-17 10:02:51 -0400
committerRob Clark <[email protected]>2018-07-17 11:00:00 -0400
commitf129971e71ccc8c711ccfc01d5adad7e30687549 (patch)
treed3a11d22daceb339db4e921480ef18a5892832e2 /src
parent20f677f6bccdabafbffd0d8e948514dda0acb3f4 (diff)
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 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/freedreno/freedreno_batch.c60
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.c2
2 files changed, 32 insertions, 30 deletions
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: */