llvmpipe: checkpoint: more thread/queuing changes

Now mapping/unmapping the framebuffer is done by a rasteizer thread
rather than the main calling thread.
This commit is contained in:
Brian Paul 2009-12-11 14:52:42 -07:00
parent 24d894e557
commit 2bce5c195f
3 changed files with 84 additions and 75 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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;
};