[Mesa-dev] [PATCH 4/6] gallium: add way for drivers to create fences without flushing
Marek Olšák
maraeo at gmail.com
Mon Apr 4 12:10:04 UTC 2016
There is one problem with this: It doesn't allow calling
pipe_context::fence_finish from another thread in a thread-safe
manner, and it implies that fence_finish is generally NOT thread-safe.
This thread safety is something I'd like to preserve.
I would say that a flush flag telling the driver not to flush would be
better, so that drivers which have per-screen fences and cheap flushes
can ignore it.
Marek
On Fri, Apr 1, 2016 at 10:29 PM, Rob Clark <robdclark at gmail.com> wrote:
> From: Rob Clark <robclark at freedesktop.org>
>
> Since current thing is kinda horrible for tilers. And that issue will
> be even worse with EGL_ANDROID_native_fence_sync.
>
> Not wired up yet for gl syncobj, which can come later. For now we just
> need this with EGL.
>
> Signed-off-by: Rob Clark <robclark at freedesktop.org>
> ---
> src/gallium/include/pipe/p_context.h | 24 ++++++++++++++++++++++++
> src/gallium/state_trackers/dri/dri2.c | 29 ++++++++++++++++++++---------
> 2 files changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
> index 1c97e82..02a946b 100644
> --- a/src/gallium/include/pipe/p_context.h
> +++ b/src/gallium/include/pipe/p_context.h
> @@ -457,6 +457,30 @@ struct pipe_context {
> unsigned flags);
>
> /**
> + * Create a fence without necessarily flushing rendering. Note
> + * that if the driver implements this, it must also implement
> + * ctx->fence_finish() which will be used instead of
> + * screen->fence_finish() to give the driver an opportunity to
> + * flush.
> + *
> + * This allows drivers, in particular tilers, to defer flush
> + * until someone actually wants to wait on a fence.
> + *
> + * \param fence if not NULL, an old fence to unref and transfer a
> + * new fence reference to
> + */
> + void (*create_fence)(struct pipe_context *pipe,
> + struct pipe_fence_handle **fence);
> +
> + /**
> + * Wait for the fence to finish.
> + * \param timeout in nanoseconds (may be PIPE_TIMEOUT_INFINITE).
> + */
> + boolean (*fence_finish)(struct pipe_context *pipe,
> + struct pipe_fence_handle *fence,
> + uint64_t timeout);
> +
> + /**
> * Create a view on a texture to be used by a shader stage.
> */
> struct pipe_sampler_view * (*create_sampler_view)(struct pipe_context *ctx,
> diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
> index fb0a180..b66d885 100644
> --- a/src/gallium/state_trackers/dri/dri2.c
> +++ b/src/gallium/state_trackers/dri/dri2.c
> @@ -1320,7 +1320,12 @@ dri2_create_fence(__DRIcontext *_ctx)
> if (!fence)
> return NULL;
>
> - ctx->flush(ctx, &fence->pipe_fence, 0);
> + if (ctx->create_fence) {
> + debug_assert(ctx->fence_finish);
> + ctx->create_fence(ctx, &fence->pipe_fence);
> + } else {
> + ctx->flush(ctx, &fence->pipe_fence, 0);
> + }
>
> if (!fence->pipe_fence) {
> FREE(fence);
> @@ -1376,27 +1381,33 @@ static GLboolean
> dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
> uint64_t timeout)
> {
> + struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
> struct dri2_fence *fence = (struct dri2_fence*)_fence;
> struct dri_screen *driscreen = fence->driscreen;
> struct pipe_screen *screen = driscreen->base.screen;
> + struct pipe_fence_handle *pipe_fence = NULL;
>
> - /* No need to flush. The context was flushed when the fence was created. */
> + /* No need to flush. The context was flushed when the fence was created,
> + * or the ctx implements ctx->fence_finish() which will take care of
> + * flushing if required
> + */
>
> if (fence->pipe_fence)
> - return screen->fence_finish(screen, fence->pipe_fence, timeout);
> + pipe_fence = fence->pipe_fence;
> else if (fence->cl_event) {
> - struct pipe_fence_handle *pipe_fence =
> - driscreen->opencl_dri_event_get_fence(fence->cl_event);
> -
> - if (pipe_fence)
> - return screen->fence_finish(screen, pipe_fence, timeout);
> - else
> + pipe_fence = driscreen->opencl_dri_event_get_fence(fence->cl_event);
> + if (!pipe_fence)
> return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
> }
> else {
> assert(0);
> return false;
> }
> +
> + if (ctx->fence_finish)
> + return ctx->fence_finish(ctx, pipe_fence, timeout);
> +
> + return screen->fence_finish(screen, pipe_fence, timeout);
> }
>
> static void
> --
> 2.5.5
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list