From 01b1900084152dbacd4025a31ced25f75666ce59 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 4 Dec 2009 15:31:09 -0700 Subject: [PATCH] llvmpipe: reorganization of binning data structions and funtions New lp_bins struct contains all bin information. More move bin-related code into lp_bin.[ch] Use new/updated bin-access functions to hide implementation details. The result is more/cleaner separation between the setup and rast components. This will make double-buffering of the bins easier, etc. --- src/gallium/drivers/llvmpipe/lp_bin.c | 78 ++++++++++++++++ src/gallium/drivers/llvmpipe/lp_bin.h | 61 ++++++++++-- src/gallium/drivers/llvmpipe/lp_rast.c | 51 ++++++++-- src/gallium/drivers/llvmpipe/lp_rast.h | 21 ++--- src/gallium/drivers/llvmpipe/lp_setup.c | 93 +++---------------- .../drivers/llvmpipe/lp_setup_context.h | 17 +--- src/gallium/drivers/llvmpipe/lp_setup_tri.c | 26 +++--- 7 files changed, 209 insertions(+), 138 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_bin.c b/src/gallium/drivers/llvmpipe/lp_bin.c index f43cdcbf3de..1f05416b3ee 100644 --- a/src/gallium/drivers/llvmpipe/lp_bin.c +++ b/src/gallium/drivers/llvmpipe/lp_bin.c @@ -29,6 +29,84 @@ #include "lp_bin.h" +void +lp_init_bins(struct lp_bins *bins) +{ + unsigned i, j; + for (i = 0; i < TILES_X; i++) + for (j = 0; j < TILES_Y; j++) { + struct cmd_bin *bin = lp_get_bin(bins, i, j); + bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block); + } + + bins->data.head = + bins->data.tail = CALLOC_STRUCT(data_block); +} + + +void +lp_reset_bins(struct lp_bins *bins, unsigned tiles_x, unsigned tiles_y) +{ + unsigned i, j; + + /* Free all but last binner command lists: + */ + for (i = 0; i < tiles_x; i++) { + for (j = 0; j < tiles_y; j++) { + struct cmd_bin *bin = lp_get_bin(bins, i, j); + struct cmd_block_list *list = &bin->commands; + struct cmd_block *block; + struct cmd_block *tmp; + + for (block = list->head; block != list->tail; block = tmp) { + tmp = block->next; + FREE(block); + } + + assert(list->tail->next == NULL); + list->head = list->tail; + list->head->count = 0; + } + } + + /* Free all but last binned data block: + */ + { + struct data_block_list *list = &bins->data; + struct data_block *block, *tmp; + + for (block = list->head; block != list->tail; block = tmp) { + tmp = block->next; + FREE(block); + } + + assert(list->tail->next == NULL); + list->head = list->tail; + list->head->used = 0; + } +} + + +void +lp_free_bin_data(struct lp_bins *bins) +{ + unsigned i, j; + + for (i = 0; i < TILES_X; i++) + for (j = 0; j < TILES_Y; j++) { + struct cmd_bin *bin = lp_get_bin(bins, i, j); + /* lp_reset_bins() should have been already called */ + assert(bin->commands.head == bin->commands.tail); + FREE(bin->commands.head); + bin->commands.head = NULL; + bin->commands.tail = NULL; + } + + FREE(bins->data.head); + bins->data.head = NULL; +} + + void lp_bin_new_cmd_block( struct cmd_block_list *list ) { diff --git a/src/gallium/drivers/llvmpipe/lp_bin.h b/src/gallium/drivers/llvmpipe/lp_bin.h index fa25d786311..4d12b932745 100644 --- a/src/gallium/drivers/llvmpipe/lp_bin.h +++ b/src/gallium/drivers/llvmpipe/lp_bin.h @@ -35,9 +35,19 @@ #ifndef LP_BIN_H #define LP_BIN_H +#include "lp_tile_soa.h" #include "lp_rast.h" +/* We're limited to 2K by 2K for 32bit fixed point rasterization. + * Will need a 64-bit version for larger framebuffers. + */ +#define MAXHEIGHT 2048 +#define MAXWIDTH 2048 +#define TILES_X (MAXWIDTH / TILE_SIZE) +#define TILES_Y (MAXHEIGHT / TILE_SIZE) + + #define CMD_BLOCK_MAX 128 #define DATA_BLOCK_SIZE (16 * 1024 - sizeof(unsigned) - sizeof(void *)) @@ -84,19 +94,40 @@ struct data_block_list { }; +/** + * All bins and bin data are contained here. + * Per-bin data goes into the 'tile' bins. + * Shared bin data goes into the 'data' buffer. + * When there are multiple threads, will want to double-buffer the + * bin arrays: + */ +struct lp_bins { + struct cmd_bin tile[TILES_X][TILES_Y]; + struct data_block_list data; +}; + + + +void lp_init_bins(struct lp_bins *bins); -extern void lp_bin_new_data_block( struct data_block_list *list ); +void lp_reset_bins(struct lp_bins *bins, unsigned tiles_x, unsigned tiles_y); -extern void lp_bin_new_cmd_block( struct cmd_block_list *list ); +void lp_free_bin_data(struct lp_bins *bins); + +void lp_bin_new_data_block( struct data_block_list *list ); + +void lp_bin_new_cmd_block( struct cmd_block_list *list ); /** - * Allocate space for a command/data in the given block list. + * Allocate space for a command/data in the bin's data buffer. * Grow the block list if needed. */ static INLINE void * -lp_bin_alloc( struct data_block_list *list, unsigned size) +lp_bin_alloc( struct lp_bins *bins, unsigned size) { + struct data_block_list *list = &bins->data; + if (list->tail->used + size > DATA_BLOCK_SIZE) { lp_bin_new_data_block( list ); } @@ -114,9 +145,11 @@ lp_bin_alloc( struct data_block_list *list, unsigned size) * As above, but with specific alignment. */ static INLINE void * -lp_bin_alloc_aligned( struct data_block_list *list, unsigned size, +lp_bin_alloc_aligned( struct lp_bins *bins, unsigned size, unsigned alignment ) { + struct data_block_list *list = &bins->data; + if (list->tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) { lp_bin_new_data_block( list ); } @@ -134,20 +167,32 @@ lp_bin_alloc_aligned( struct data_block_list *list, unsigned size, /* Put back data if we decide not to use it, eg. culled triangles. */ static INLINE void -lp_bin_putback_data( struct data_block_list *list, unsigned size) +lp_bin_putback_data( struct lp_bins *bins, unsigned size) { + struct data_block_list *list = &bins->data; assert(list->tail->used >= size); list->tail->used -= size; } -/* Add a command to a given bin. +/** Return pointer to a particular tile's bin. */ +static INLINE struct cmd_bin * +lp_get_bin(struct lp_bins *bins, unsigned x, unsigned y) +{ + return &bins->tile[x][y]; +} + + + +/* Add a command to bin[x][y]. */ static INLINE void -lp_bin_command( struct cmd_bin *bin, +lp_bin_command( struct lp_bins *bins, + unsigned x, unsigned y, lp_rast_cmd cmd, union lp_rast_cmd_arg arg ) { + struct cmd_bin *bin = lp_get_bin(bins, x, y); struct cmd_block_list *list = &bin->commands; if (list->tail->count == CMD_BLOCK_MAX) { diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index a466aec379e..87e3bfcd3f5 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -56,7 +56,8 @@ struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen ) * Begin the rasterization phase. * Map the framebuffer surfaces. Initialize the 'rast' state. */ -boolean lp_rast_begin( struct lp_rasterizer *rast, +static boolean +lp_rast_begin( struct lp_rasterizer *rast, struct pipe_surface *cbuf, struct pipe_surface *zsbuf, boolean write_color, @@ -121,7 +122,8 @@ boolean lp_rast_begin( struct lp_rasterizer *rast, * Finish the rasterization phase. * Unmap framebuffer surfaces. */ -void lp_rast_end( struct lp_rasterizer *rast ) +static void +lp_rast_end( struct lp_rasterizer *rast ) { struct pipe_screen *screen = rast->screen; @@ -469,12 +471,13 @@ 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(). */ -void -lp_rasterize_bin( struct lp_rasterizer *rast, - const struct cmd_bin *bin, - int x, int y) +static void +rasterize_bin( struct lp_rasterizer *rast, + const struct cmd_bin *bin, + int x, int y) { const struct cmd_block_list *commands = &bin->commands; struct cmd_block *block; @@ -493,6 +496,42 @@ lp_rasterize_bin( struct lp_rasterizer *rast, } +/** + * Rasterize/execute all bins. + */ +void +lp_rasterize_bins( struct lp_rasterizer *rast, + struct lp_bins *bins, + unsigned tiles_x, unsigned tiles_y, + const struct pipe_framebuffer_state *fb, + bool write_depth ) +{ + unsigned i, j; + + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + lp_rast_begin( rast, + fb->cbufs[0], + fb->zsbuf, + fb->cbufs[0] != NULL, + fb->zsbuf != NULL && write_depth, + fb->width, + fb->height ); + + /* loop over tile bins, rasterize each */ + for (i = 0; i < tiles_x; i++) { + for (j = 0; j < tiles_y; j++) { + struct cmd_bin *bin = lp_get_bin(bins, i, j); + rasterize_bin( rast, bin, i * TILE_SIZE, j * TILE_SIZE ); + } + } + + lp_rast_end( rast ); + + LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); +} + + /* Shutdown: */ diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 3d2388b8948..e623eafc9ad 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -47,6 +47,7 @@ * individual function calls like this. */ struct lp_rasterizer; +struct lp_bins; struct cmd_bin; struct pipe_screen; @@ -133,22 +134,12 @@ struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen ); void lp_rast_destroy( struct lp_rasterizer * ); +void lp_rasterize_bins( struct lp_rasterizer *rast, + struct lp_bins *bins, + unsigned tiles_x, unsigned tiles_y, + const struct pipe_framebuffer_state *fb, + bool write_depth ); -boolean lp_rast_begin( struct lp_rasterizer *rast, - struct pipe_surface *cbuf, - struct pipe_surface *zsbuf, - boolean write_color, - boolean write_zstencil, - unsigned width, - unsigned height ); - -void -lp_rasterize_bin( struct lp_rasterizer *rast, - const struct cmd_bin *bin, - int x, int y); - - -void lp_rast_end( struct lp_rasterizer * ); union lp_rast_cmd_arg { diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 47d2ac8e118..efaf5acfe84 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -80,8 +80,6 @@ first_point( struct setup_context *setup, static void reset_context( struct setup_context *setup ) { - unsigned i, j; - LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); /* Reset derived state */ @@ -90,40 +88,7 @@ static void reset_context( struct setup_context *setup ) setup->fs.stored = NULL; setup->dirty = ~0; - /* Free all but last binner command lists: - */ - for (i = 0; i < setup->tiles_x; i++) { - for (j = 0; j < setup->tiles_y; j++) { - struct cmd_block_list *list = &setup->tile[i][j].commands; - struct cmd_block *block; - struct cmd_block *tmp; - - for (block = list->head; block != list->tail; block = tmp) { - tmp = block->next; - FREE(block); - } - - assert(list->tail->next == NULL); - list->head = list->tail; - list->head->count = 0; - } - } - - /* Free all but last binned data block: - */ - { - struct data_block_list *list = &setup->data; - struct data_block *block, *tmp; - - for (block = list->head; block != list->tail; block = tmp) { - tmp = block->next; - FREE(block); - } - - assert(list->tail->next == NULL); - list->head = list->tail; - list->head->used = 0; - } + lp_reset_bins(&setup->bins, setup->tiles_x, setup->tiles_y); /* Reset some state: */ @@ -177,7 +142,7 @@ static void bin_everywhere( struct setup_context *setup, unsigned i, j; for (i = 0; i < setup->tiles_x; i++) for (j = 0; j < setup->tiles_y; j++) - lp_bin_command( &setup->tile[i][j], cmd, arg ); + lp_bin_command( &setup->bins, i, j, cmd, arg ); } @@ -194,13 +159,13 @@ bin_state_command( struct setup_context *setup, unsigned i, j; for (i = 0; i < setup->tiles_x; i++) { for (j = 0; j < setup->tiles_y; j++) { - struct cmd_bin *bin = &setup->tile[i][j]; + struct cmd_bin *bin = &setup->bins.tile[i][j]; lp_rast_cmd last_cmd = lp_get_last_command(bin); if (last_cmd == cmd) { lp_replace_last_command_arg(bin, arg); } else { - lp_bin_command( bin, cmd, arg ); + lp_bin_command( &setup->bins, i, j, cmd, arg ); } } } @@ -212,29 +177,10 @@ static void rasterize_bins( struct setup_context *setup, boolean write_depth ) { - struct lp_rasterizer *rast = setup->rast; - unsigned i, j; - - LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - - lp_rast_begin( rast, - setup->fb->cbufs[0], - setup->fb->zsbuf, - setup->fb->cbufs[0] != NULL, - setup->fb->zsbuf != NULL && write_depth, - setup->fb->width, - setup->fb->height ); - - /* loop over tile bins, rasterize each */ - for (i = 0; i < setup->tiles_x; i++) { - for (j = 0; j < setup->tiles_y; j++) { - lp_rasterize_bin( rast, &setup->tile[i][j], - i * TILE_SIZE, - j * TILE_SIZE ); - } - } - - lp_rast_end( rast ); + lp_rasterize_bins(setup->rast, + &setup->bins, setup->tiles_x, setup->tiles_y, + setup->fb, + write_depth); reset_context( setup ); @@ -559,7 +505,7 @@ lp_setup_update_shader_state( struct setup_context *setup ) uint8_t *stored; unsigned i, j; - stored = lp_bin_alloc_aligned(&setup->data, 4 * 16, 16); + stored = lp_bin_alloc_aligned(&setup->bins, 4 * 16, 16); /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { @@ -591,7 +537,7 @@ lp_setup_update_shader_state( struct setup_context *setup ) current_size) != 0) { void *stored; - stored = lp_bin_alloc(&setup->data, current_size); + stored = lp_bin_alloc(&setup->bins, current_size); if(stored) { memcpy(stored, current_data, @@ -621,7 +567,7 @@ lp_setup_update_shader_state( struct setup_context *setup ) * and append it to the bin's setup data buffer. */ struct lp_rast_state *stored = - (struct lp_rast_state *) lp_bin_alloc(&setup->data, sizeof *stored); + (struct lp_rast_state *) lp_bin_alloc(&setup->bins, sizeof *stored); if(stored) { memcpy(stored, &setup->fs.current, @@ -677,17 +623,11 @@ lp_setup_tri(struct setup_context *setup, void lp_setup_destroy( struct setup_context *setup ) { - unsigned i, j; - reset_context( setup ); pipe_buffer_reference(&setup->constants.current, NULL); - for (i = 0; i < TILES_X; i++) - for (j = 0; j < TILES_Y; j++) - FREE(setup->tile[i][j].commands.head); - - FREE(setup->data.head); + lp_free_bin_data(&setup->bins); lp_rast_destroy( setup->rast ); FREE( setup ); @@ -702,19 +642,12 @@ struct setup_context * lp_setup_create( struct pipe_screen *screen ) { struct setup_context *setup = CALLOC_STRUCT(setup_context); - unsigned i, j; setup->rast = lp_rast_create( screen ); if (!setup->rast) goto fail; - for (i = 0; i < TILES_X; i++) - for (j = 0; j < TILES_Y; j++) - setup->tile[i][j].commands.head = - setup->tile[i][j].commands.tail = CALLOC_STRUCT(cmd_block); - - setup->data.head = - setup->data.tail = CALLOC_STRUCT(data_block); + lp_init_bins(&setup->bins); setup->triangle = first_triangle; setup->line = first_line; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index dc12eb78471..8478bb9014c 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -40,14 +40,6 @@ #include "lp_tile_soa.h" /* for TILE_SIZE */ #include "lp_bin.h" -/* We're limited to 2K by 2K for 32bit fixed point rasterization. - * Will need a 64-bit version for larger framebuffers. - */ -#define MAXHEIGHT 2048 -#define MAXWIDTH 2048 -#define TILES_X (MAXWIDTH / TILE_SIZE) -#define TILES_Y (MAXHEIGHT / TILE_SIZE) - #define LP_SETUP_NEW_FS 0x01 #define LP_SETUP_NEW_CONSTANTS 0x02 @@ -63,14 +55,7 @@ struct setup_context { struct lp_rasterizer *rast; - /** - * Per-bin data goes into the 'tile' bins. - * Shared bin data goes into the 'data' buffer. - * When there are multiple threads, will want to double-buffer the - * bin arrays: - */ - struct cmd_bin tile[TILES_X][TILES_Y]; - struct data_block_list data; + struct lp_bins bins; /* size of framebuffer, in tiles */ unsigned tiles_x; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index 5e53b4050e8..b8f79849e8b 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -185,9 +185,9 @@ static void setup_tri_coefficients( struct setup_context *setup, { unsigned bytes; bytes = (setup->fs.nr_inputs + 1) * 4 * sizeof(float); - tri->inputs.a0 = lp_bin_alloc_aligned( &setup->data, bytes, 16 ); - tri->inputs.dadx = lp_bin_alloc_aligned( &setup->data, bytes, 16 ); - tri->inputs.dady = lp_bin_alloc_aligned( &setup->data, bytes, 16 ); + tri->inputs.a0 = lp_bin_alloc_aligned( &setup->bins, bytes, 16 ); + tri->inputs.dadx = lp_bin_alloc_aligned( &setup->bins, bytes, 16 ); + tri->inputs.dady = lp_bin_alloc_aligned( &setup->bins, bytes, 16 ); } /* The internal position input is in slot zero: @@ -263,7 +263,7 @@ do_triangle_ccw(struct setup_context *setup, const int y2 = subpixel_snap(v2[0][1]); const int y3 = subpixel_snap(v3[0][1]); - struct lp_rast_triangle *tri = lp_bin_alloc( &setup->data, sizeof *tri ); + struct lp_rast_triangle *tri = lp_bin_alloc( &setup->bins, sizeof *tri ); float area, oneoverarea; int minx, maxx, miny, maxy; @@ -283,7 +283,7 @@ do_triangle_ccw(struct setup_context *setup, * XXX: subject to overflow?? */ if (area <= 0) { - lp_bin_putback_data( &setup->data, sizeof *tri ); + lp_bin_putback_data( &setup->bins, sizeof *tri ); return; } @@ -295,7 +295,7 @@ do_triangle_ccw(struct setup_context *setup, if (tri->miny == tri->maxy || tri->minx == tri->maxx) { - lp_bin_putback_data( &setup->data, sizeof *tri ); + lp_bin_putback_data( &setup->bins, sizeof *tri ); return; } @@ -405,7 +405,7 @@ do_triangle_ccw(struct setup_context *setup, { /* Triangle is contained in a single tile: */ - lp_bin_command( &setup->tile[minx][miny], lp_rast_triangle, + lp_bin_command( &setup->bins, minx, miny, lp_rast_triangle, lp_rast_arg_triangle(tri) ); } else @@ -464,17 +464,17 @@ do_triangle_ccw(struct setup_context *setup, { in = 1; /* triangle covers the whole tile- shade whole tile */ - lp_bin_command( &setup->tile[x][y], - lp_rast_shade_tile, - lp_rast_arg_inputs(&tri->inputs) ); + lp_bin_command( &setup->bins, x, y, + lp_rast_shade_tile, + lp_rast_arg_inputs(&tri->inputs) ); } else { in = 1; /* shade partial tile */ - lp_bin_command( &setup->tile[x][y], - lp_rast_triangle, - lp_rast_arg_triangle(tri) ); + lp_bin_command( &setup->bins, x, y, + lp_rast_triangle, + lp_rast_arg_triangle(tri) ); } /* Iterate cx values across the region: -- 2.30.2