From: Rob Clark Date: Wed, 31 Jul 2019 19:30:24 +0000 (-0700) Subject: freedreno/batch: fix dependency loop detection X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9d5beab4414f483ad94372d36c2c6f23f6c1ca41;p=mesa.git freedreno/batch: fix dependency loop detection We can have a scenario like: A -> B A -> C -> B When adding the A->C dependency, it doesn't really matter that C depends on something that A depends on, that isn't a necessary condition for a dependency loop. Instead what we want to know is that nothing C depends on, directly or indirectly, depends on A. We can detect this by recursively OR'ing the dependents_mask of C and all it's dependencies. Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c b/src/gallium/drivers/freedreno/freedreno_batch.c index 6bab243453d..52870cd0aa1 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.c +++ b/src/gallium/drivers/freedreno/freedreno_batch.c @@ -401,31 +401,30 @@ fd_batch_flush(struct fd_batch *batch, bool sync) fd_batch_reference(&tmp, NULL); } -/* does 'batch' depend directly or indirectly on 'other' ? */ -static bool -batch_depends_on(struct fd_batch *batch, struct fd_batch *other) +/* find a batches dependents mask, including recursive dependencies: */ +static uint32_t +recursive_dependents_mask(struct fd_batch *batch) { struct fd_batch_cache *cache = &batch->ctx->screen->batch_cache; struct fd_batch *dep; + uint32_t dependents_mask = batch->dependents_mask; - if (batch->dependents_mask & (1 << other->idx)) - return true; + foreach_batch(dep, cache, batch->dependents_mask) + dependents_mask |= recursive_dependents_mask(dep); - foreach_batch(dep, cache, other->dependents_mask) - if (batch_depends_on(batch, dep)) - return true; - - return false; + return dependents_mask; } void fd_batch_add_dep(struct fd_batch *batch, struct fd_batch *dep) { + pipe_mutex_assert_locked(batch->ctx->screen->lock); + if (batch->dependents_mask & (1 << dep->idx)) return; /* a loop should not be possible */ - debug_assert(!batch_depends_on(dep, batch)); + debug_assert(!((1 << batch->idx) & recursive_dependents_mask(dep))); struct fd_batch *other = NULL; fd_batch_reference_locked(&other, dep);