Mesa (lp-binning): llvmpipe: checkpoint: more thread/queuing changes

Brian Paul brianp at kemper.freedesktop.org
Fri Dec 11 17:01:20 PST 2009


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

Author: Brian Paul <brianp at vmware.com>
Date:   Fri Dec 11 14:52:42 2009 -0700

llvmpipe: checkpoint: more thread/queuing changes

Now mapping/unmapping the framebuffer is done by a rasteizer thread
rather than the main calling thread.

---

 src/gallium/drivers/llvmpipe/lp_bin.h       |    5 +
 src/gallium/drivers/llvmpipe/lp_rast.c      |  130 ++++++++++++++-------------
 src/gallium/drivers/llvmpipe/lp_rast_priv.h |   24 ++---
 3 files changed, 84 insertions(+), 75 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_bin.h b/src/gallium/drivers/llvmpipe/lp_bin.h
index 4394e7b..565dd49 100644
--- a/src/gallium/drivers/llvmpipe/lp_bin.h
+++ b/src/gallium/drivers/llvmpipe/lp_bin.h
@@ -108,6 +108,11 @@ struct lp_bins {
    struct cmd_bin tile[TILES_X][TILES_Y];
    struct data_block_list data;
 
+   /** the framebuffer to render the bins into */
+   struct pipe_framebuffer_state fb;
+
+   boolean write_depth;
+
    /**
     * Number of active tiles in each dimension.
     * This basically the framebuffer size divided by tile size
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index a8212d7..2ea3ac6 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -40,48 +40,6 @@
 #include "lp_bin.h"
 
 
-
-/**
- * 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.
  * Map the framebuffer surfaces.  Initialize the 'rast' state.
@@ -526,6 +484,22 @@ lp_rast_end_tile( struct lp_rasterizer *rast,
 
 
 /**
+ * When all the threads are done rasterizing a bin, one thread will
+ * call this function to reset the bin and put it onto the empty queue.
+ */
+static void
+release_bins( struct lp_rasterizer *rast,
+              struct lp_bins *bins )
+{
+   util_unreference_framebuffer_state( &bins->fb );
+
+   lp_reset_bins( bins );
+   lp_bins_enqueue( rast->empty_bins, bins );
+   rast->curr_bins = NULL;
+}
+
+
+/**
  * 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().
@@ -615,18 +589,23 @@ lp_rasterize_bins( struct lp_rasterizer *rast,
       }
    }
 
-   lp_rast_begin( rast, fb,
-                  fb->cbufs[0]!= NULL,
-                  fb->zsbuf != NULL && write_depth );
+   /* save framebuffer state in the bin */
+   util_copy_framebuffer_state(&bins->fb, fb);
+   bins->write_depth = write_depth;
 
    if (rast->num_threads == 0) {
       /* no threading */
+
+      lp_rast_begin( rast, fb,
+                     fb->cbufs[0]!= NULL,
+                     fb->zsbuf != NULL && write_depth );
+
       lp_bin_iter_begin( bins );
       rasterize_bins( rast, 0, bins, write_depth );
 
-      /* reset bins and put into the empty queue */
-      lp_reset_bins( bins );
-      lp_bins_enqueue( rast->empty_bins, bins);
+      release_bins( rast, bins );
+
+      lp_rast_end( rast );
    }
    else {
       /* threaded rendering! */
@@ -634,11 +613,6 @@ lp_rasterize_bins( struct lp_rasterizer *rast,
 
       lp_bins_enqueue( rast->full_bins, bins );
 
-      /* XXX need to move/fix these */
-      rast->write_depth = write_depth;
-
-      /*lp_bin_iter_begin( bins );*/
-
       /* signal the threads that there's work to do */
       for (i = 0; i < rast->num_threads; i++) {
          pipe_semaphore_signal(&rast->tasks[i].work_ready);
@@ -650,8 +624,6 @@ lp_rasterize_bins( struct lp_rasterizer *rast,
       }
    }
 
-   lp_rast_end( rast );
-
    LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
 }
 
@@ -671,23 +643,53 @@ thread_func( void *init_data )
    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);
+      if (task->thread_index == 0) {
+         /* thread[0]:
+          *  - get next set of bins to rasterize
+          *  - map the framebuffer surfaces
+          */
+         const struct pipe_framebuffer_state *fb;
+         boolean write_depth;
+
+         rast->curr_bins = lp_bins_dequeue( rast->full_bins );
+
+         lp_bin_iter_begin( rast->curr_bins );
+
+         fb = &rast->curr_bins->fb;
+         write_depth = rast->curr_bins->write_depth;
+
+         lp_rast_begin( rast, fb,
+                        fb->cbufs[0] != NULL,
+                        fb->zsbuf != NULL && write_depth );
+      }
+
+      /* Wait for all threads to get here so that threads[1+] don't
+       * get a null rast->curr_bins pointer.
+       */
+      pipe_barrier_wait( &rast->barrier );
 
       /* do work */
       if (debug)
          debug_printf("thread %d doing work\n", task->thread_index);
       rasterize_bins(rast, task->thread_index,
-                     bins, rast->write_depth);
+                     rast->curr_bins, rast->curr_bins->write_depth);
       
-      release_current_bin( rast );
+      /* wait for all threads to finish with this set of bins */
+      pipe_barrier_wait( &rast->barrier );
+
+      if (task->thread_index == 0) {
+         /* thread[0]:
+          * - release the bins object
+          * - unmap the framebuffer surfaces
+          */
+         release_bins( rast, rast->curr_bins );
+         lp_rast_end( rast );
+      }
 
       /* signal done with work */
       if (debug)
@@ -751,6 +753,9 @@ lp_rast_create( struct pipe_screen *screen, struct lp_bins_queue *empty )
 
    create_rast_threads(rast);
 
+   /* for synchronizing rasterization threads */
+   pipe_barrier_init( &rast->barrier, rast->num_threads );
+
    return rast;
 }
 
@@ -768,6 +773,9 @@ void lp_rast_destroy( struct lp_rasterizer *rast )
       align_free(rast->tasks[i].tile.color);
    }
 
+   /* for synchronizing rasterization threads */
+   pipe_barrier_destroy( &rast->barrier );
+
    FREE(rast);
 }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 4ae54ac..ba14fc3 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -93,18 +93,6 @@ 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;
@@ -122,14 +110,22 @@ struct lp_rasterizer
       char clear_stencil;
    } state;
 
+   /** 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;
+
+   /** The bins currently being rasterized by the threads */
+   struct lp_bins *curr_bins;
+
    /** A task object for each rasterization thread */
    struct lp_rasterizer_task tasks[MAX_THREADS];
 
    unsigned num_threads;
    pipe_thread threads[MAX_THREADS];
 
-   struct lp_bins *bins;
-   boolean write_depth;
+   /** For synchronizing the rasterization threads */
+   pipe_barrier barrier;
 };
 
 



More information about the mesa-commit mailing list