diff options
author | Rob Clark <[email protected]> | 2019-07-31 12:30:24 -0700 |
---|---|---|
committer | Rob Clark <[email protected]> | 2019-08-02 10:24:14 -0700 |
commit | 9d5beab4414f483ad94372d36c2c6f23f6c1ca41 (patch) | |
tree | 6ed8e75a42a964f530f33355e9f2fe86cd881fbf /src/gallium | |
parent | e1790c532a431ad3f8abe36175613f4b5f48fa3f (diff) |
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 <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/freedreno/freedreno_batch.c | 21 |
1 files changed, 10 insertions, 11 deletions
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); |