Mesa (lp-binning): llvmpipe: checkpoint: use empty/full bin queues

Brian Paul brianp at kemper.freedesktop.org
Thu Dec 10 13:56:53 PST 2009


Module: Mesa
Branch: lp-binning
Commit: 9509f73c2147a9e225b5ef69a646e5dd711573f5
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9509f73c2147a9e225b5ef69a646e5dd711573f5

Author: Brian Paul <brianp at vmware.com>
Date:   Thu Dec 10 14:56:30 2009 -0700

llvmpipe: checkpoint: use empty/full bin queues

---

 src/gallium/drivers/llvmpipe/lp_rast.c      |   64 +++++++++++++++++++++++---
 src/gallium/drivers/llvmpipe/lp_rast_priv.h |    8 +++
 2 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 5659ae2..0cd95e0 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -40,6 +40,46 @@
 
 
 
+/**
+ * Called by rasterization threads to get the next chunk of work.
+ * We use a lock to make sure that all the threads get the same bins.
+ */
+static struct lp_bins *
+get_next_full_bin( struct lp_rasterizer *rast )
+{
+   pipe_mutex_lock( rast->get_bin_mutex );
+   if (!rast->curr_bins) {
+      /* this will wait until there's something in the queue */
+      rast->curr_bins = lp_bins_dequeue( rast->full_bins );
+      rast->release_count = 0;
+
+      lp_bin_iter_begin( rast->curr_bins );
+   }
+   pipe_mutex_unlock( rast->get_bin_mutex );
+   return rast->curr_bins;
+}
+
+
+/**
+ * Called by rasterization threads after they've finished with
+ * the current bin.  When all threads have called this, we reset
+ * the bin and put it into the 'empty bins' queue.
+ */
+static void
+release_current_bin( struct lp_rasterizer *rast )
+{
+   pipe_mutex_lock( rast->get_bin_mutex );
+   rast->release_count++;
+   if (rast->release_count == rast->num_threads) {
+      assert(rast->curr_bins);
+      lp_reset_bins( rast->curr_bins );
+      lp_bins_enqueue( rast->empty_bins, rast->curr_bins );
+      rast->curr_bins = NULL;
+   }
+   pipe_mutex_unlock( rast->get_bin_mutex );
+}
+
+
 
 /**
  * Begin the rasterization phase.
@@ -488,6 +528,7 @@ lp_rast_end_tile( struct lp_rasterizer *rast,
  * Rasterize commands for a single bin.
  * \param x, y  position of the bin's tile in the framebuffer
  * Must be called between lp_rast_begin() and lp_rast_end().
+ * Called per thread.
  */
 static void
 rasterize_bin( struct lp_rasterizer *rast,
@@ -514,6 +555,7 @@ rasterize_bin( struct lp_rasterizer *rast,
 
 /**
  * Rasterize/execute all bins.
+ * Called per thread.
  */
 static void
 rasterize_bins( struct lp_rasterizer *rast,
@@ -539,6 +581,7 @@ rasterize_bins( struct lp_rasterizer *rast,
       struct cmd_bin *bin;
       int x, y;
 
+      assert(bins);
       while ((bin = lp_bin_iter_next(bins, &x, &y))) {
          rasterize_bin( rast, thread_index, bin, x * TILE_SIZE, y * TILE_SIZE);
       }
@@ -593,11 +636,13 @@ lp_rasterize_bins( struct lp_rasterizer *rast,
       /* threaded rendering! */
       unsigned i;
 
-      rast->bins = bins;
+      lp_bins_enqueue( rast->full_bins, bins );
+
+      /* XXX need to move/fix these */
       rast->fb = fb;
       rast->write_depth = write_depth;
 
-      lp_bin_iter_begin( bins );
+      /*lp_bin_iter_begin( bins );*/
 
       /* signal the threads that there's work to do */
       for (i = 0; i < rast->num_threads; i++) {
@@ -608,10 +653,6 @@ lp_rasterize_bins( struct lp_rasterizer *rast,
       for (i = 0; i < rast->num_threads; i++) {
          pipe_semaphore_wait(&rast->tasks[i].work_done);
       }
-
-      /* reset bins and put into the empty queue */
-      lp_reset_bins( bins );
-      lp_bins_enqueue( rast->empty_bins, bins);
    }
 
    lp_rast_end( rast );
@@ -632,19 +673,26 @@ thread_func( void *init_data )
 {
    struct lp_rasterizer_task *task = (struct lp_rasterizer_task *) init_data;
    struct lp_rasterizer *rast = task->rast;
-   int debug = 0;
+   boolean debug = false;
 
    while (1) {
+      struct lp_bins *bins;
+
       /* wait for work */
       if (debug)
          debug_printf("thread %d waiting for work\n", task->thread_index);
       pipe_semaphore_wait(&task->work_ready);
 
+      bins = get_next_full_bin( rast );
+      assert(bins);
+
       /* do work */
       if (debug)
          debug_printf("thread %d doing work\n", task->thread_index);
       rasterize_bins(rast, task->thread_index,
-                     rast->bins, rast->fb, rast->write_depth);
+                     bins, rast->fb, rast->write_depth);
+      
+      release_current_bin( rast );
 
       /* signal done with work */
       if (debug)
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 4e4f8b3..f174aa1 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -95,10 +95,18 @@ struct lp_rasterizer
    boolean clipped_tile;
    boolean check_for_clipped_tiles;
 
+   /** The incoming queue of filled bins to rasterize */
    struct lp_bins_queue *full_bins;
+   /** The outgoing queue of emptied bins to return to setup modulee */
    struct lp_bins_queue *empty_bins;
+
    pipe_mutex get_bin_mutex;
 
+   /** The bins currently being rasterized by the threads */
+   struct lp_bins *curr_bins;
+   /** Counter to determine when all threads are done with current bin */
+   unsigned release_count;
+
    /* Framebuffer stuff
     */
    struct pipe_screen *screen;



More information about the mesa-commit mailing list