[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