From: Nicolai Hähnle <nicolai.haeh...@amd.com>

---
 src/gallium/drivers/radeonsi/si_fence.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/radeonsi/si_fence.c 
b/src/gallium/drivers/radeonsi/si_fence.c
index c51efad7106..b7b02b55831 100644
--- a/src/gallium/drivers/radeonsi/si_fence.c
+++ b/src/gallium/drivers/radeonsi/si_fence.c
@@ -111,22 +111,29 @@ static void si_fence_server_sync(struct pipe_context *ctx,
 
        util_queue_fence_wait(&rfence->ready);
 
        /* Only imported fences need to be handled by fence_server_sync,
         * because the winsys handles synchronizations automatically for BOs
         * within the process.
         *
         * Simply skip unflushed fences here, and the winsys will drop no-op
         * dependencies (i.e. dependencies within the same ring).
         */
-       if (rfence->gfx_unflushed.ctx)
+       if (rfence->gfx_unflushed.ctx) {
+               /* It is an application error to call glWaitSync for an
+                * unflushed fence from a different context, since it could
+                * cause a deadlock. Conceptually, it would be more correct to
+                * just hang here in that case.
+                */
+               assert(rfence->gfx_unflushed.ctx == rctx);
                return;
+       }
 
        /* All unflushed commands will not start execution before
         * this fence dependency is signalled.
         *
         * Should we flush the context to allow more GPU parallelism?
         */
        if (rfence->sdma)
                si_add_fence_dependency(rctx, rfence->sdma);
        if (rfence->gfx)
                si_add_fence_dependency(rctx, rfence->gfx);
@@ -182,20 +189,42 @@ static boolean si_fence_finish(struct pipe_screen *screen,
                }
        }
 
        if (!rfence->gfx)
                return true;
 
        /* Flush the gfx IB if it hasn't been flushed yet. */
        if (rctx &&
            rfence->gfx_unflushed.ctx == rctx &&
            rfence->gfx_unflushed.ib_index == rctx->num_gfx_cs_flushes) {
+               /* Section 4.1.2 (Signaling) of the OpenGL 4.6 (Core profile)
+                * spec says:
+                *
+                *    "If the sync object being blocked upon will not be
+                *     signaled in finite time (for example, by an associated
+                *     fence command issued previously, but not yet flushed to
+                *     the graphics pipeline), then ClientWaitSync may hang
+                *     forever. To help prevent this behavior, if
+                *     ClientWaitSync is called and all of the following are
+                *     true:
+                *
+                *     * the SYNC_FLUSH_COMMANDS_BIT bit is set in flags,
+                *     * sync is unsignaled when ClientWaitSync is called,
+                *     * and the calls to ClientWaitSync and FenceSync were
+                *       issued from the same context,
+                *
+                *     then the GL will behave as if the equivalent of Flush
+                *     were inserted immediately after the creation of sync."
+                *
+                * This means we need to flush for such fences even when we're
+                * not going to wait.
+                */
                rctx->gfx.flush(rctx, timeout ? 0 : RADEON_FLUSH_ASYNC, NULL);
                rfence->gfx_unflushed.ctx = NULL;
 
                if (!timeout)
                        return false;
 
                /* Recompute the timeout after all that. */
                if (timeout && timeout != PIPE_TIMEOUT_INFINITE) {
                        int64_t time = os_time_get_nano();
                        timeout = abs_timeout > time ? abs_timeout - time : 0;
-- 
2.11.0

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to