summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-12-11 14:52:42 -0700
committerBrian Paul <brianp@vmware.com>2009-12-11 14:52:46 -0700
commit2bce5c195f94e2cce8f67c6a8066b0ae408487ce (patch)
tree9fb9aff0eddf7e8f249b0daaa0ad139ebd41f6c4 /src/gallium
parent24d894e5579bd11fdf294d86834093e353abf4db (diff)
llvmpipe: checkpoint: more thread/queuing changes
Now mapping/unmapping the framebuffer is done by a rasteizer thread rather than the main calling thread.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bin.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c130
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h24
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 4394e7bda0..565dd49f68 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 a8212d74e3..2ea3ac6b3b 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 4ae54ac8c1..ba14fc3675 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;
};