[Mesa-dev] [PATCH] nouveau: emit and flush fence in fence_signalled if needed

Christoph Bumiller e0425955 at student.tuwien.ac.at
Tue May 7 13:37:56 PDT 2013


On 07.05.2013 19:25, Bryan Cain wrote:
> The Mesa state tracker expects us to emit the fence even if it doesn't call
> fence_finish.  Notably, this occurs when glClientWaitSync is called with
> timeout 0.
> 
> Fixes Portal and Left 4 Dead 2, which were both stalling on startup by
> repeatedly calling glClientWaitSync with timeout 0 while waiting for commands
> to complete.
> ---

I'm not sure I want to do this.
pipe_screen::fence_signalled probably shouldn't flush the command
buffer, r600g doesn't seem to do it either.

They should probably call glFlush() before looping on glClientWaitSync,
or, if they don't have anything better to do in the meantime, simply
specify an infinite timeout if they're going to loop forever anyway.

>  src/gallium/drivers/nouveau/nouveau_fence.c |   36 ++++++++++++++++++---------
>  src/gallium/drivers/nouveau/nouveau_fence.h |    1 +
>  2 files changed, 25 insertions(+), 12 deletions(-)
> 
> diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c
> index dea146c..722be01 100644
> --- a/src/gallium/drivers/nouveau/nouveau_fence.c
> +++ b/src/gallium/drivers/nouveau/nouveau_fence.c
> @@ -167,6 +167,25 @@ nouveau_fence_update(struct nouveau_screen *screen, boolean flushed)
>     }
>  }
>  
> +boolean
> +nouveau_fence_ensure_flushed(struct nouveau_fence *fence)
> +{
> +   struct nouveau_screen *screen = fence->screen;
> +
> +   if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) {
> +      nouveau_fence_emit(fence);
> +
> +      if (fence == screen->fence.current)
> +         nouveau_fence_new(screen, &screen->fence.current, FALSE);
> +   }
> +   if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) {
> +      if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel))
> +         return FALSE;
> +   }
> +
> +   return TRUE;
> +}
> +
>  #define NOUVEAU_FENCE_MAX_SPINS (1 << 31)
>  
>  boolean
> @@ -174,8 +193,9 @@ nouveau_fence_signalled(struct nouveau_fence *fence)
>  {
>     struct nouveau_screen *screen = fence->screen;
>  
> -   if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED)
> -      nouveau_fence_update(screen, FALSE);
> +   if (!nouveau_fence_ensure_flushed(fence))
> +      return FALSE;
> +   nouveau_fence_update(screen, FALSE);
>  
>     return fence->state == NOUVEAU_FENCE_STATE_SIGNALLED;
>  }
> @@ -189,16 +209,8 @@ nouveau_fence_wait(struct nouveau_fence *fence)
>     /* wtf, someone is waiting on a fence in flush_notify handler? */
>     assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
>  
> -   if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) {
> -      nouveau_fence_emit(fence);
> -
> -      if (fence == screen->fence.current)
> -         nouveau_fence_new(screen, &screen->fence.current, FALSE);
> -   }
> -   if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) {
> -      if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel))
> -         return FALSE;
> -   }
> +   if (!nouveau_fence_ensure_flushed(fence))
> +      return FALSE;
>  
>     do {
>        nouveau_fence_update(screen, FALSE);
> diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h
> index 3984a9a..d497c7f 100644
> --- a/src/gallium/drivers/nouveau/nouveau_fence.h
> +++ b/src/gallium/drivers/nouveau/nouveau_fence.h
> @@ -34,6 +34,7 @@ boolean nouveau_fence_new(struct nouveau_screen *, struct nouveau_fence **,
>  boolean nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *);
>  void    nouveau_fence_update(struct nouveau_screen *, boolean flushed);
>  void    nouveau_fence_next(struct nouveau_screen *);
> +boolean nouveau_fence_ensure_flushed(struct nouveau_fence *);
>  boolean nouveau_fence_wait(struct nouveau_fence *);
>  boolean nouveau_fence_signalled(struct nouveau_fence *);
>  
> 



More information about the mesa-dev mailing list