[Mesa-dev] [PATCH] [RFC v2] mesa/glthread: Call unmarshal_batch directly in glthread_finish when batch queue is empty.

Nicolai Hähnle nhaehnle at gmail.com
Wed Mar 29 16:24:49 UTC 2017


On 29.03.2017 18:11, Bartosz Tomczyk wrote:
> This avoids costly thread synchronisation. With this fix games that previously regressed with mesa_glthread=true like xonotic or grid autosport.
> Could someone test if games that benefit from glthread didn't regress?

Please make sure the commit message is wrapped to 75 characters.

The approach seems like a good idea: if the current thread is going to 
wait anyway, we might as well do any pending work locally to avoid 
context switch overhead. Would be nice to see some benchmarks, but this 
should mostly be a win -- the only reason I could imagine why it might 
not be is cache effects, and those could go either way.


> ---
>  src/mesa/main/glthread.c | 49 +++++++++++++++++++++++++++++++++---------------
>  1 file changed, 34 insertions(+), 15 deletions(-)
>
> diff --git a/src/mesa/main/glthread.c b/src/mesa/main/glthread.c
> index 06115b916d..eef7202f01 100644
> --- a/src/mesa/main/glthread.c
> +++ b/src/mesa/main/glthread.c
> @@ -194,18 +194,11 @@ _mesa_glthread_restore_dispatch(struct gl_context *ctx)
>     }
>  }
>
> -void
> -_mesa_glthread_flush_batch(struct gl_context *ctx)
> +static void
> +_mesa_glthread_flush_batch_no_lock(struct gl_context *ctx)

A better and more idiomatic name for this function would be 
_mesa_glthread_flush_batch_locked.


>  {
>     struct glthread_state *glthread = ctx->GLThread;
> -   struct glthread_batch *batch;
> -
> -   if (!glthread)
> -      return;
> -
> -   batch = glthread->batch;
> -   if (!batch->used)
> -      return;
> +   struct glthread_batch *batch = glthread->batch;
>
>     /* Immediately reallocate a new batch, since the next marshalled call would
>      * just do it.
> @@ -223,10 +216,26 @@ _mesa_glthread_flush_batch(struct gl_context *ctx)
>        return;
>     }
>
> -   pthread_mutex_lock(&glthread->mutex);
>     *glthread->batch_queue_tail = batch;
>     glthread->batch_queue_tail = &batch->next;
>     pthread_cond_broadcast(&glthread->new_work);
> +
> +}
> +void
> +_mesa_glthread_flush_batch(struct gl_context *ctx)
> +{
> +   struct glthread_state *glthread = ctx->GLThread;
> +   struct glthread_batch *batch;
> +
> +   if (!glthread)
> +      return;
> +
> +   batch = glthread->batch;
> +   if (!batch->used)
> +      return;
> +
> +   pthread_mutex_lock(&glthread->mutex);
> +   _mesa_glthread_flush_batch_no_lock(ctx);
>     pthread_mutex_unlock(&glthread->mutex);
>  }
>
> @@ -252,12 +261,22 @@ _mesa_glthread_finish(struct gl_context *ctx)
>     if (pthread_self() == glthread->thread)
>        return;
>
> -   _mesa_glthread_flush_batch(ctx);
> -
>     pthread_mutex_lock(&glthread->mutex);
>
> -   while (glthread->batch_queue || glthread->busy)
> -      pthread_cond_wait(&glthread->work_done, &glthread->mutex);
> +   if (!(glthread->batch_queue || glthread->busy))
> +   {
> +      if (glthread->batch && glthread->batch->used)
> +      {
> +         glthread_unmarshal_batch(ctx, glthread->batch);

You _must_ reset the api dispatch afterwards; otherwise, your change 
here effectively disables glthread forever. To be on the safe side, I 
think you need to save the current dispatch in a temp variable and then 
reset after unmarshalling.

Cheers,
Nicolai


> +      }
> +      glthread_allocate_batch(ctx);
> +   }
> +   else
> +   {
> +      _mesa_glthread_flush_batch_no_lock(ctx);
> +      while (glthread->batch_queue || glthread->busy)
> +         pthread_cond_wait(&glthread->work_done, &glthread->mutex);
> +   }
>
>     pthread_mutex_unlock(&glthread->mutex);
>  }
>


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list