st/mesa: implement st_server_wait_sync properly
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Thu, 9 Nov 2017 13:34:19 +0000 (14:34 +0100)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Mon, 20 Nov 2017 17:15:07 +0000 (18:15 +0100)
Asynchronous flushes require a proper implementation of
st_server_wait_sync, because we could have the following with
threaded Gallium:

 Context 1 app     Context 1 driver         Context 2
 -------------     ----------------         ---------
 f = glFenceSync
 glFlush
 <-- app sync -->                           <-- app sync -->
                                            glWaitSync(f)
                                            .. draw calls ..
                   pipe_context::flush
                     for glFenceSync
                   pipe_context::flush
                     for glFlush

Reviewed-by: Andres Rodriguez <andresx7@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/mesa/state_tracker/st_cb_syncobj.c

index 637fbe3..44323b4 100644 (file)
@@ -130,8 +130,30 @@ static void st_server_wait_sync(struct gl_context *ctx,
                                 struct gl_sync_object *obj,
                                 GLbitfield flags, GLuint64 timeout)
 {
-   /* NO-OP.
-    * Neither Gallium nor DRM interfaces support blocking on the GPU. */
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   struct pipe_screen *screen = pipe->screen;
+   struct st_sync_object *so = (struct st_sync_object*)obj;
+   struct pipe_fence_handle *fence = NULL;
+
+   /* Nothing needs to be done here if the driver does not support async
+    * flushes. */
+   if (!pipe->fence_server_sync)
+      return;
+
+   /* If the fence doesn't exist, assume it's signalled. */
+   mtx_lock(&so->mutex);
+   if (!so->fence) {
+      mtx_unlock(&so->mutex);
+      so->b.StatusFlag = GL_TRUE;
+      return;
+   }
+
+   /* We need a local copy of the fence pointer. */
+   screen->fence_reference(screen, &fence, so->fence);
+   mtx_unlock(&so->mutex);
+
+   pipe->fence_server_sync(pipe, fence);
+   screen->fence_reference(screen, &fence, NULL);
 }
 
 void st_init_syncobj_functions(struct dd_function_table *functions)