[Mesa-dev] [PATCH 1/2] winsys/radeon: add the implementation of fences from r300g

Marek Olšák maraeo at gmail.com
Tue Oct 8 12:59:45 PDT 2013


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/drivers/r300/r300_flush.c         | 13 ++-----
 src/gallium/drivers/r300/r300_screen.c        | 28 +++-----------
 src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 56 +++++++++++++++++++++++++++
 src/gallium/winsys/radeon/drm/radeon_winsys.h | 23 +++++++++++
 4 files changed, 87 insertions(+), 33 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index 3dd3864..cbe2b57 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -76,26 +76,19 @@ void r300_flush(struct pipe_context *pipe,
                 struct pipe_fence_handle **fence)
 {
     struct r300_context *r300 = r300_context(pipe);
-    struct pb_buffer **rfence = (struct pb_buffer**)fence;
 
     if (r300->screen->info.drm_minor >= 12) {
         flags |= RADEON_FLUSH_KEEP_TILING_FLAGS;
     }
 
-    if (rfence) {
-        /* Create a fence, which is a dummy BO. */
-        *rfence = r300->rws->buffer_create(r300->rws, 1, 1, TRUE,
-                                           RADEON_DOMAIN_GTT);
-        /* Add the fence as a dummy relocation. */
-        r300->rws->cs_add_reloc(r300->cs,
-                                r300->rws->buffer_get_cs_handle(*rfence),
-                                RADEON_USAGE_READWRITE, RADEON_DOMAIN_GTT);
+    if (fence) {
+        *fence = r300->rws->cs_create_fence(r300->cs);
     }
 
     if (r300->dirty_hw) {
         r300_flush_and_cleanup(r300, flags);
     } else {
-        if (rfence) {
+        if (fence) {
             /* We have to create a fence object, but the command stream is empty
              * and we cannot emit an empty CS. Let's write to some reg. */
             CS_LOCALS(r300);
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index dd036fc..9ec58a9 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -558,17 +558,17 @@ static void r300_fence_reference(struct pipe_screen *screen,
                                  struct pipe_fence_handle **ptr,
                                  struct pipe_fence_handle *fence)
 {
-    pb_reference((struct pb_buffer**)ptr,
-                             (struct pb_buffer*)fence);
+    struct radeon_winsys *rws = r300_screen(screen)->rws;
+
+    rws->fence_reference(ptr, fence);
 }
 
 static boolean r300_fence_signalled(struct pipe_screen *screen,
                                     struct pipe_fence_handle *fence)
 {
     struct radeon_winsys *rws = r300_screen(screen)->rws;
-    struct pb_buffer *rfence = (struct pb_buffer*)fence;
 
-    return !rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE);
+    return rws->fence_wait(rws, fence, 0);
 }
 
 static boolean r300_fence_finish(struct pipe_screen *screen,
@@ -576,26 +576,8 @@ static boolean r300_fence_finish(struct pipe_screen *screen,
                                  uint64_t timeout)
 {
     struct radeon_winsys *rws = r300_screen(screen)->rws;
-    struct pb_buffer *rfence = (struct pb_buffer*)fence;
-
-    if (timeout != PIPE_TIMEOUT_INFINITE) {
-        int64_t start_time = os_time_get();
-
-        /* Convert to microseconds. */
-        timeout /= 1000;
-
-        /* Wait in a loop. */
-        while (rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE)) {
-            if (os_time_get() - start_time >= timeout) {
-                return FALSE;
-            }
-            os_time_sleep(10);
-        }
-        return TRUE;
-    }
 
-    rws->buffer_wait(rfence, RADEON_USAGE_READWRITE);
-    return TRUE;
+    return rws->fence_wait(rws, fence, timeout);
 }
 
 struct pipe_screen* r300_screen_create(struct radeon_winsys *rws)
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
index 62f7704..add4962 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
@@ -65,6 +65,7 @@
 #include "radeon_drm_cs.h"
 
 #include "util/u_memory.h"
+#include "os/os_time.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -630,6 +631,58 @@ static boolean radeon_bo_is_referenced(struct radeon_winsys_cs *rcs,
     return FALSE;
 }
 
+/* FENCES */
+
+static struct pipe_fence_handle *
+radeon_cs_create_fence(struct radeon_winsys_cs *rcs)
+{
+    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+    struct pb_buffer *fence;
+
+    /* Create a fence, which is a dummy BO. */
+    fence = cs->ws->base.buffer_create(&cs->ws->base, 1, 1, TRUE,
+                                       RADEON_DOMAIN_GTT);
+    /* Add the fence as a dummy relocation. */
+    cs->ws->base.cs_add_reloc(rcs, cs->ws->base.buffer_get_cs_handle(fence),
+                              RADEON_USAGE_READWRITE, RADEON_DOMAIN_GTT);
+    return (struct pipe_fence_handle*)fence;
+}
+
+static bool radeon_fence_wait(struct radeon_winsys *ws,
+                              struct pipe_fence_handle *fence,
+                              uint64_t timeout)
+{
+    struct pb_buffer *rfence = (struct pb_buffer*)fence;
+
+    if (timeout == 0)
+        return !ws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE);
+
+    if (timeout != PIPE_TIMEOUT_INFINITE) {
+        int64_t start_time = os_time_get();
+
+        /* Convert to microseconds. */
+        timeout /= 1000;
+
+        /* Wait in a loop. */
+        while (ws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE)) {
+            if (os_time_get() - start_time >= timeout) {
+                return FALSE;
+            }
+            os_time_sleep(10);
+        }
+        return TRUE;
+    }
+
+    ws->buffer_wait(rfence, RADEON_USAGE_READWRITE);
+    return TRUE;
+}
+
+static void radeon_fence_reference(struct pipe_fence_handle **dst,
+                                   struct pipe_fence_handle *src)
+{
+    pb_reference((struct pb_buffer**)dst, (struct pb_buffer*)src);
+}
+
 void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
 {
     ws->base.cs_create = radeon_drm_cs_create;
@@ -642,4 +695,7 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
     ws->base.cs_set_flush_callback = radeon_drm_cs_set_flush;
     ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced;
     ws->base.cs_sync_flush = radeon_drm_cs_sync_flush;
+    ws->base.cs_create_fence = radeon_cs_create_fence;
+    ws->base.fence_wait = radeon_fence_wait;
+    ws->base.fence_reference = radeon_fence_reference;
 }
diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
index 581cd84..c000371 100644
--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
@@ -485,6 +485,29 @@ struct radeon_winsys {
     void (*cs_sync_flush)(struct radeon_winsys_cs *cs);
 
     /**
+     * Return a fence associated with the CS. The fence will be signalled
+     * once the CS is flushed and all commands in the CS are completed
+     * by the GPU.
+     */
+    struct pipe_fence_handle *(*cs_create_fence)(struct radeon_winsys_cs *cs);
+
+    /**
+     * Wait for the fence and return true if the fence has been signalled.
+     * The timeout of 0 will only return the status.
+     * The timeout of PIPE_TIMEOUT_INFINITE will always wait until the fence
+     * is signalled.
+     */
+    bool (*fence_wait)(struct radeon_winsys *ws,
+                       struct pipe_fence_handle *fence,
+                       uint64_t timeout);
+
+    /**
+     * Reference counting for fences.
+     */
+    void (*fence_reference)(struct pipe_fence_handle **dst,
+                            struct pipe_fence_handle *src);
+
+    /**
      * Initialize surface
      *
      * \param ws        The winsys this function is called from.
-- 
1.8.1.2



More information about the mesa-dev mailing list