From 9509f73c2147a9e225b5ef69a646e5dd711573f5 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 10 Dec 2009 14:56:30 -0700 Subject: [PATCH] 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 5659ae2ca5a..0cd95e0ca72 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 4e4f8b36a7a..f174aa15052 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; -- 2.30.2