diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/panfrost/pan_context.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_context.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_job.c | 16 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_screen.c | 75 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_screen.h | 3 |
5 files changed, 59 insertions, 58 deletions
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index e09e30a569e..5317cfe6f7c 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -1343,14 +1343,30 @@ panfrost_flush( { struct panfrost_context *ctx = pan_context(pipe); struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); + struct util_dynarray fences; + + /* We must collect the fences before the flush is done, otherwise we'll + * lose track of them. + */ + if (fence) { + util_dynarray_init(&fences, NULL); + panfrost_batch_fence_reference(batch->out_sync); + util_dynarray_append(&fences, struct panfrost_batch_fence *, + batch->out_sync); + } /* Submit the frame itself */ panfrost_batch_submit(batch); if (fence) { - struct panfrost_fence *f = panfrost_fence_create(ctx); + struct panfrost_fence *f = panfrost_fence_create(ctx, &fences); pipe->screen->fence_reference(pipe->screen, fence, NULL); *fence = (struct pipe_fence_handle *)f; + + util_dynarray_foreach(&fences, struct panfrost_batch_fence *, fence) + panfrost_batch_fence_unreference(*fence); + + util_dynarray_fini(&fences); } } diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 3b09952345c..d50ed57d5d8 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -94,7 +94,7 @@ struct panfrost_query { struct panfrost_fence { struct pipe_reference reference; - int fd; + struct util_dynarray syncfds; }; struct panfrost_streamout { @@ -193,9 +193,6 @@ struct panfrost_context { /* True for t6XX, false for t8xx. */ bool is_t6xx; - - /* The out sync fence of the last submitted batch. */ - struct panfrost_batch_fence *last_out_sync; }; /* Corresponds to the CSO */ diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index b0494af3482..211e48bafd4 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -819,13 +819,6 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch, free(bo_handles); free(in_syncs); - /* Release the last batch fence if any, and retain the new one */ - if (ctx->last_out_sync) - panfrost_batch_fence_unreference(ctx->last_out_sync); - - panfrost_batch_fence_reference(batch->out_sync); - ctx->last_out_sync = batch->out_sync; - if (ret) { fprintf(stderr, "Error submitting: %m\n"); return errno; @@ -884,15 +877,6 @@ panfrost_batch_submit(struct panfrost_batch *batch) * to wait on it. */ batch->out_sync->signaled = true; - - /* Release the last batch fence if any, and set ->last_out_sync - * to NULL - */ - if (ctx->last_out_sync) { - panfrost_batch_fence_unreference(ctx->last_out_sync); - ctx->last_out_sync = NULL; - } - goto out; } diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index e2c31f7f821..55c66e0c9a7 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -575,7 +575,9 @@ panfrost_fence_reference(struct pipe_screen *pscreen, struct panfrost_fence *old = *p; if (pipe_reference(&(*p)->reference, &f->reference)) { - close(old->fd); + util_dynarray_foreach(&old->syncfds, int, fd) + close(*fd); + util_dynarray_fini(&old->syncfds); free(old); } *p = f; @@ -589,66 +591,67 @@ panfrost_fence_finish(struct pipe_screen *pscreen, { struct panfrost_screen *screen = pan_screen(pscreen); struct panfrost_fence *f = (struct panfrost_fence *)fence; + struct util_dynarray syncobjs; int ret; - unsigned syncobj; - /* The fence was already signaled */ - if (f->fd == -1) + /* All fences were already signaled */ + if (!util_dynarray_num_elements(&f->syncfds, int)) return true; - ret = drmSyncobjCreate(screen->fd, 0, &syncobj); - if (ret) { - fprintf(stderr, "Failed to create syncobj to wait on: %m\n"); - return false; - } + util_dynarray_init(&syncobjs, NULL); + util_dynarray_foreach(&f->syncfds, int, fd) { + uint32_t syncobj; - ret = drmSyncobjImportSyncFile(screen->fd, syncobj, f->fd); - if (ret) { - fprintf(stderr, "Failed to import fence to syncobj: %m\n"); - return false; + ret = drmSyncobjCreate(screen->fd, 0, &syncobj); + assert(!ret); + + ret = drmSyncobjImportSyncFile(screen->fd, syncobj, *fd); + assert(!ret); + util_dynarray_append(&syncobjs, uint32_t, syncobj); } uint64_t abs_timeout = os_time_get_absolute_timeout(timeout); if (abs_timeout == OS_TIMEOUT_INFINITE) abs_timeout = INT64_MAX; - ret = drmSyncobjWait(screen->fd, &syncobj, 1, abs_timeout, 0, NULL); + ret = drmSyncobjWait(screen->fd, util_dynarray_begin(&syncobjs), + util_dynarray_num_elements(&syncobjs, uint32_t), + abs_timeout, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL, + NULL); - drmSyncobjDestroy(screen->fd, syncobj); + util_dynarray_foreach(&syncobjs, uint32_t, syncobj) + drmSyncobjDestroy(screen->fd, *syncobj); return ret >= 0; } struct panfrost_fence * -panfrost_fence_create(struct panfrost_context *ctx) +panfrost_fence_create(struct panfrost_context *ctx, + struct util_dynarray *fences) { struct panfrost_screen *screen = pan_screen(ctx->base.screen); struct panfrost_fence *f = calloc(1, sizeof(*f)); if (!f) return NULL; - f->fd = -1; - - /* There was no job flushed yet or the batch fence was already - * signaled, let's return a dummy fence object that returns true - * directly when ->fence_finish() is called. - */ - if (!ctx->last_out_sync || ctx->last_out_sync->signaled) - goto out; - - /* Snapshot the last Panfrost's rendering's out fence. We'd rather have - * another syncobj instead of a sync file, but this is all we get. - * (HandleToFD/FDToHandle just gives you another syncobj ID for the - * same syncobj). - */ - drmSyncobjExportSyncFile(screen->fd, ctx->last_out_sync->syncobj, &f->fd); - if (f->fd == -1) { - fprintf(stderr, "export failed: %m\n"); - free(f); - return NULL; + util_dynarray_init(&f->syncfds, NULL); + + /* Export fences from all pending batches. */ + util_dynarray_foreach(fences, struct panfrost_batch_fence *, fence) { + int fd = -1; + + /* The fence is already signaled, no need to export it. */ + if ((*fence)->signaled) + continue; + + drmSyncobjExportSyncFile(screen->fd, (*fence)->syncobj, &fd); + if (fd == -1) + fprintf(stderr, "export failed: %m\n"); + + assert(fd != -1); + util_dynarray_append(&f->syncfds, int, fd); } -out: pipe_reference_init(&f->reference, 1); return f; diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h index fdc47df00ea..f09db8011c6 100644 --- a/src/gallium/drivers/panfrost/pan_screen.h +++ b/src/gallium/drivers/panfrost/pan_screen.h @@ -101,6 +101,7 @@ pan_screen(struct pipe_screen *p) } struct panfrost_fence * -panfrost_fence_create(struct panfrost_context *ctx); +panfrost_fence_create(struct panfrost_context *ctx, + struct util_dynarray *fences); #endif /* PAN_SCREEN_H */ |