summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2019-07-31 12:30:24 -0700
committerRob Clark <[email protected]>2019-08-02 10:24:14 -0700
commit9d5beab4414f483ad94372d36c2c6f23f6c1ca41 (patch)
tree6ed8e75a42a964f530f33355e9f2fe86cd881fbf /src/gallium
parente1790c532a431ad3f8abe36175613f4b5f48fa3f (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.c21
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);