From 2bce5c195f94e2cce8f67c6a8066b0ae408487ce Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 11 Dec 2009 14:52:42 -0700 Subject: 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(-) (limited to 'src/gallium') 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. @@ -525,6 +483,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 @@ -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; }; -- cgit v1.2.3