[Mesa-dev] [PATCH v3 07/17] panfrost: Prepare panfrost_fence for batch pipelining
Alyssa Rosenzweig
alyssa at rosenzweig.io
Fri Sep 20 21:02:37 UTC 2019
(Still r-b)
On Wed, Sep 18, 2019 at 03:24:29PM +0200, Boris Brezillon wrote:
> The panfrost_fence logic currently waits on the last submitted batch,
> but the batch serialization that was enforced in
> panfrost_batch_submit() is about to go away, allowing for several
> batches to be pipelined, and the last submitted one is not necessarily
> the one that will finish last.
>
> We need to make sure the fence logic waits on all flushed batches, not
> only the last one.
>
> Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
> ---
> Changes in v3:
> * Fix a comment
> * Adjust things to match the changes done in "panfrost: Add a batch fence"
> ---
> src/gallium/drivers/panfrost/pan_context.c | 18 +++++-
> src/gallium/drivers/panfrost/pan_context.h | 5 +-
> src/gallium/drivers/panfrost/pan_job.c | 16 -----
> src/gallium/drivers/panfrost/pan_screen.c | 71 +++++++++++-----------
> src/gallium/drivers/panfrost/pan_screen.h | 3 +-
> 5 files changed, 57 insertions(+), 56 deletions(-)
>
> diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
> index 312a9e93e455..aad69e3f9991 100644
> --- a/src/gallium/drivers/panfrost/pan_context.c
> +++ b/src/gallium/drivers/panfrost/pan_context.c
> @@ -1349,14 +1349,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 3b09952345cf..d50ed57d5d8a 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 b0494af3482f..211e48bafd4e 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 e2c31f7f8213..55c66e0c9a79 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;
> + util_dynarray_init(&f->syncfds, NULL);
>
> - /* 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;
> + /* Export fences from all pending batches. */
> + util_dynarray_foreach(fences, struct panfrost_batch_fence *, fence) {
> + int fd = -1;
>
> - /* 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;
> + /* 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 fdc47df00ea1..f09db8011c6a 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 */
> --
> 2.21.0
More information about the mesa-dev
mailing list