freedreno: Avoid deferred-flush dependency loops
We can't blindly make every other batch a dependency of the current batch, because it is possible they already have a dependency on the current batch, which would result in a loop. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18200>
This commit is contained in:
@@ -170,9 +170,33 @@ fd_bc_flush(struct fd_context *ctx, bool deferred) assert_dt
|
||||
*/
|
||||
if (deferred) {
|
||||
struct fd_batch *current_batch = fd_context_batch(ctx);
|
||||
struct fd_batch *deps[ARRAY_SIZE(cache->batches)] = {0};
|
||||
unsigned ndeps = 0;
|
||||
|
||||
/* To avoid a dependency loop, pull out any batches that already
|
||||
* have a dependency on the current batch. This ensures the
|
||||
* following loop adding a dependency to the current_batch, all
|
||||
* remaining batches do not have a direct or indirect dependency
|
||||
* on the current_batch.
|
||||
*
|
||||
* The batches that have a dependency on the current batch will
|
||||
* be flushed immediately (after dropping screen lock) instead
|
||||
*/
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
if ((batches[i] != current_batch) &&
|
||||
fd_batch_has_dep(batches[i], current_batch)) {
|
||||
/* We can't immediately flush while we hold the screen lock,
|
||||
* but that doesn't matter. We just want to skip adding any
|
||||
* deps that would result in a loop, we can flush after we've
|
||||
* updated the dependency graph and dropped the lock.
|
||||
*/
|
||||
fd_batch_reference_locked(&deps[ndeps++], batches[i]);
|
||||
fd_batch_reference_locked(&batches[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
if (batches[i] != current_batch) {
|
||||
if (batches[i] && (batches[i] != current_batch)) {
|
||||
fd_batch_add_dep(current_batch, batches[i]);
|
||||
}
|
||||
}
|
||||
@@ -180,6 +204,14 @@ fd_bc_flush(struct fd_context *ctx, bool deferred) assert_dt
|
||||
fd_batch_reference_locked(¤t_batch, NULL);
|
||||
|
||||
fd_screen_unlock(ctx->screen);
|
||||
|
||||
/* If we have any batches that we could add a dependency on (unlikely)
|
||||
* flush them immediately.
|
||||
*/
|
||||
for (unsigned i = 0; i < ndeps; i++) {
|
||||
fd_batch_flush(deps[i]);
|
||||
fd_batch_reference(&deps[i], NULL);
|
||||
}
|
||||
} else {
|
||||
fd_screen_unlock(ctx->screen);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user