Mesa (master): llvmpipe: move fences from per-bin to per-thread

Jose Fonseca jrfonseca at kemper.freedesktop.org
Tue Jul 13 16:24:27 UTC 2010


Module: Mesa
Branch: master
Commit: 3bd9aedbac79eec16bfe6f5fc6f6a021eebe769a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3bd9aedbac79eec16bfe6f5fc6f6a021eebe769a

Author: Keith Whitwell <keithw at vmware.com>
Date:   Thu Jul  8 15:13:35 2010 +0100

llvmpipe: move fences from per-bin to per-thread

Rather than inserting an lp_rast_fence command at the end of each
bin, have each rasterizer thread call this function directly once
it has run out of work to do on a particular scene.

This results in fewer calls to the mutex & related functions, but more
importantly makes it easier to recognize empty bins.

---

 src/gallium/drivers/llvmpipe/lp_fence.c |    9 ++----
 src/gallium/drivers/llvmpipe/lp_fence.h |   18 ++++++++++++++
 src/gallium/drivers/llvmpipe/lp_flush.c |   10 +-------
 src/gallium/drivers/llvmpipe/lp_rast.c  |    4 +++
 src/gallium/drivers/llvmpipe/lp_scene.c |    3 ++
 src/gallium/drivers/llvmpipe/lp_scene.h |    1 +
 src/gallium/drivers/llvmpipe/lp_setup.c |   39 ++++++++++++++++++++----------
 src/gallium/drivers/llvmpipe/lp_setup.h |    3 +-
 8 files changed, 58 insertions(+), 29 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_fence.c b/src/gallium/drivers/llvmpipe/lp_fence.c
index 75d8d2b..f9805e5 100644
--- a/src/gallium/drivers/llvmpipe/lp_fence.c
+++ b/src/gallium/drivers/llvmpipe/lp_fence.c
@@ -28,7 +28,6 @@
 
 #include "pipe/p_screen.h"
 #include "util/u_memory.h"
-#include "util/u_inlines.h"
 #include "lp_debug.h"
 #include "lp_fence.h"
 
@@ -59,7 +58,7 @@ lp_fence_create(unsigned rank)
 
 
 /** Destroy a fence.  Called when refcount hits zero. */
-static void
+void
 lp_fence_destroy(struct lp_fence *fence)
 {
    pipe_mutex_destroy(fence->mutex);
@@ -77,12 +76,10 @@ llvmpipe_fence_reference(struct pipe_screen *screen,
                          struct pipe_fence_handle **ptr,
                          struct pipe_fence_handle *fence)
 {
-   struct lp_fence *old = (struct lp_fence *) *ptr;
+   struct lp_fence **old = (struct lp_fence **) ptr;
    struct lp_fence *f = (struct lp_fence *) fence;
 
-   if (pipe_reference(&old->reference, &f->reference)) {
-      lp_fence_destroy(old);
-   }
+   lp_fence_reference(old, f);
 }
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_fence.h b/src/gallium/drivers/llvmpipe/lp_fence.h
index d9270f5..13358fb 100644
--- a/src/gallium/drivers/llvmpipe/lp_fence.h
+++ b/src/gallium/drivers/llvmpipe/lp_fence.h
@@ -32,6 +32,7 @@
 
 #include "os/os_thread.h"
 #include "pipe/p_state.h"
+#include "util/u_inlines.h"
 
 
 struct pipe_screen;
@@ -61,4 +62,21 @@ void
 llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen);
 
 
+void
+lp_fence_destroy(struct lp_fence *fence);
+
+static INLINE void
+lp_fence_reference(struct lp_fence **ptr,
+                   struct lp_fence *f)
+{
+   struct lp_fence *old = *ptr;
+
+   if (pipe_reference(&old->reference, &f->reference)) {
+      lp_fence_destroy(old);
+   }
+   
+   *ptr = f;
+}
+
+
 #endif /* LP_FENCE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
index 0cd288b..d78656f 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.c
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -51,16 +51,8 @@ llvmpipe_flush( struct pipe_context *pipe,
 
    draw_flush(llvmpipe->draw);
 
-   if (fence) {
-      /* if we're going to flush the setup/rasterization modules, emit
-       * a fence.
-       * XXX this (and the code below) may need fine tuning...
-       */
-      *fence = lp_setup_fence( llvmpipe->setup );
-   }
-
    /* ask the setup module to flush */
-   lp_setup_flush(llvmpipe->setup, flags);
+   lp_setup_flush(llvmpipe->setup, flags, fence);
 
    /* Enable to dump BMPs of the color/depth buffers each frame */
    if (0) {
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 1a82dd5..1dde327 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -815,6 +815,10 @@ rasterize_scene(struct lp_rasterizer_task *task,
       }
    }
 #endif
+
+   if (scene->fence) {
+      lp_rast_fence(task, lp_rast_arg_fence(scene->fence));
+   }
 }
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index e8d36bb..f2226a5 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -32,6 +32,7 @@
 #include "util/u_simple_list.h"
 #include "lp_scene.h"
 #include "lp_scene_queue.h"
+#include "lp_fence.h"
 
 
 /** List of texture references */
@@ -198,6 +199,8 @@ lp_scene_reset(struct lp_scene *scene )
       make_empty_list(ref_list);
    }
 
+   lp_fence_reference(&scene->fence, NULL);
+
    scene->scene_size = 0;
 
    scene->has_color_clear = FALSE;
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h
index 4e55d43..fa1b311 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.h
+++ b/src/gallium/drivers/llvmpipe/lp_scene.h
@@ -112,6 +112,7 @@ struct resource_ref {
  */
 struct lp_scene {
    struct pipe_context *pipe;
+   struct lp_fence *fence;
 
    /** the framebuffer to render the scene into */
    struct pipe_framebuffer_state fb;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 2bd6fce..3b83f4e 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -271,7 +271,8 @@ set_scene_state( struct lp_setup_context *setup,
  */
 void
 lp_setup_flush( struct lp_setup_context *setup,
-                unsigned flags )
+                unsigned flags,
+                struct pipe_fence_handle **fence)
 {
    LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
@@ -288,6 +289,15 @@ lp_setup_flush( struct lp_setup_context *setup,
           */
          lp_scene_bin_everywhere(scene, lp_rast_store_color, dummy);
       }
+
+
+      if (fence) {
+         /* if we're going to flush the setup/rasterization modules, emit
+          * a fence.
+          */
+         *fence = lp_setup_fence( setup );
+      }
+
    }
 
    set_scene_state( setup, SETUP_FLUSHED );
@@ -433,24 +443,27 @@ lp_setup_clear( struct lp_setup_context *setup,
 struct pipe_fence_handle *
 lp_setup_fence( struct lp_setup_context *setup )
 {
-   if (setup->num_threads == 0) {
+   if (setup->scene == NULL)
       return NULL;
-   }
-   else {
+   else if (setup->num_threads == 0)
+      return NULL;
+   else
+   {
       struct lp_scene *scene = lp_setup_get_current_scene(setup);
-      const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */
-      struct lp_fence *fence = lp_fence_create(rank);
-
-      LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank);
+      const unsigned rank = setup->num_threads;
 
       set_scene_state( setup, SETUP_ACTIVE );
+      
+      assert(scene->fence == NULL);
 
-      /* insert the fence into all command bins */
-      lp_scene_bin_everywhere( scene,
-                               lp_rast_fence,
-                               lp_rast_arg_fence(fence) );
+      /* The caller gets a reference, we keep a copy too, so need to
+       * bump the refcount:
+       */
+      lp_fence_reference(&scene->fence, lp_fence_create(rank));
+
+      LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank);
 
-      return (struct pipe_fence_handle *) fence;
+      return (struct pipe_fence_handle *) scene->fence;
    }
 }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index 6a0dc55..73b1c85 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -84,7 +84,8 @@ lp_setup_fence( struct lp_setup_context *setup );
 
 void
 lp_setup_flush( struct lp_setup_context *setup,
-                unsigned flags );
+                unsigned flags,
+                struct pipe_fence_handle **fence);
 
 
 void




More information about the mesa-commit mailing list