From 9f6e8e1d6b8696a3ee96cba01b2466ba7a1a8ef6 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 7 Sep 2010 14:02:15 +0100 Subject: llvmpipe: use opcodes instead of function pointers in bins Also, move some state from rasterizer struct to the scene. --- src/gallium/drivers/llvmpipe/lp_rast.c | 203 +++++++++----------- src/gallium/drivers/llvmpipe/lp_rast.h | 77 +++----- src/gallium/drivers/llvmpipe/lp_rast_priv.h | 69 ++++--- src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h | 5 + src/gallium/drivers/llvmpipe/lp_scene.c | 180 ++++++++++------- src/gallium/drivers/llvmpipe/lp_scene.h | 80 +++++--- src/gallium/drivers/llvmpipe/lp_setup.c | 244 ++++++++++++++---------- src/gallium/drivers/llvmpipe/lp_setup_context.h | 13 +- src/gallium/drivers/llvmpipe/lp_setup_line.c | 4 +- src/gallium/drivers/llvmpipe/lp_setup_point.c | 4 +- src/gallium/drivers/llvmpipe/lp_setup_tri.c | 41 ++-- src/gallium/drivers/llvmpipe/lp_setup_vbuf.c | 6 +- src/gallium/drivers/llvmpipe/lp_state_fs.c | 18 +- src/gallium/drivers/llvmpipe/lp_surface.c | 8 +- src/gallium/drivers/llvmpipe/lp_texture.c | 2 +- 15 files changed, 513 insertions(+), 441 deletions(-) (limited to 'src/gallium/drivers/llvmpipe') diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 694b007eb8..6a610aaf29 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -30,6 +30,7 @@ #include "util/u_math.h" #include "util/u_rect.h" #include "util/u_surface.h" +#include "util/u_pack_color.h" #include "lp_scene_queue.h" #include "lp_debug.h" @@ -57,39 +58,12 @@ static void lp_rast_begin( struct lp_rasterizer *rast, struct lp_scene *scene ) { - const struct pipe_framebuffer_state *fb = &scene->fb; - int i; rast->curr_scene = scene; LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); - rast->state.nr_cbufs = scene->fb.nr_cbufs; - - for (i = 0; i < rast->state.nr_cbufs; i++) { - struct pipe_surface *cbuf = scene->fb.cbufs[i]; - llvmpipe_resource_map(cbuf->texture, - cbuf->face, - cbuf->level, - cbuf->zslice, - LP_TEX_USAGE_READ_WRITE, - LP_TEX_LAYOUT_LINEAR); - } - - if (fb->zsbuf) { - struct pipe_surface *zsbuf = scene->fb.zsbuf; - rast->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->level); - rast->zsbuf.blocksize = - util_format_get_blocksize(zsbuf->texture->format); - - rast->zsbuf.map = llvmpipe_resource_map(zsbuf->texture, - zsbuf->face, - zsbuf->level, - zsbuf->zslice, - LP_TEX_USAGE_READ_WRITE, - LP_TEX_LAYOUT_NONE); - } - + lp_scene_begin_rasterization( scene ); lp_scene_bin_iter_begin( scene ); } @@ -97,29 +71,7 @@ lp_rast_begin( struct lp_rasterizer *rast, static void lp_rast_end( struct lp_rasterizer *rast ) { - struct lp_scene *scene = rast->curr_scene; - unsigned i; - - /* Unmap color buffers */ - for (i = 0; i < rast->state.nr_cbufs; i++) { - struct pipe_surface *cbuf = scene->fb.cbufs[i]; - llvmpipe_resource_unmap(cbuf->texture, - cbuf->face, - cbuf->level, - cbuf->zslice); - } - - /* Unmap z/stencil buffer */ - if (rast->zsbuf.map) { - struct pipe_surface *zsbuf = scene->fb.zsbuf; - llvmpipe_resource_unmap(zsbuf->texture, - zsbuf->face, - zsbuf->level, - zsbuf->zslice); - rast->zsbuf.map = NULL; - } - - lp_scene_reset( rast->curr_scene ); + lp_scene_end_rasterization( rast->curr_scene ); rast->curr_scene = NULL; @@ -138,26 +90,23 @@ lp_rast_end( struct lp_rasterizer *rast ) */ static void lp_rast_tile_begin(struct lp_rasterizer_task *task, - unsigned x, unsigned y) + const struct cmd_bin *bin) { - struct lp_rasterizer *rast = task->rast; - struct lp_scene *scene = rast->curr_scene; + const struct lp_scene *scene = task->scene; enum lp_texture_usage usage; - LP_DBG(DEBUG_RAST, "%s %d,%d\n", __FUNCTION__, x, y); - - assert(x % TILE_SIZE == 0); - assert(y % TILE_SIZE == 0); + LP_DBG(DEBUG_RAST, "%s %d,%d\n", __FUNCTION__, bin->x, bin->y); - task->x = x; - task->y = y; + task->bin = bin; + task->x = bin->x * TILE_SIZE; + task->y = bin->y * TILE_SIZE; /* reset pointers to color tile(s) */ memset(task->color_tiles, 0, sizeof(task->color_tiles)); /* get pointer to depth/stencil tile */ { - struct pipe_surface *zsbuf = rast->curr_scene->fb.zsbuf; + struct pipe_surface *zsbuf = task->scene->fb.zsbuf; if (zsbuf) { struct llvmpipe_resource *lpt = llvmpipe_resource(zsbuf->texture); @@ -173,11 +122,14 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, zsbuf->face + zsbuf->zslice, zsbuf->level, usage, - x, y); + task->x, + task->y); /* Get actual pointer to the tile data. Note that depth/stencil * data is tiled differently than color data. */ - task->depth_tile = lp_rast_get_depth_block_pointer(task, x, y); + task->depth_tile = lp_rast_get_depth_block_pointer(task, + task->x, + task->y); assert(task->depth_tile); } @@ -192,11 +144,11 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, * Clear the rasterizer's current color tile. * This is a bin command called during bin processing. */ -void +static void lp_rast_clear_color(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; const uint8_t *clear_color = arg.clear_color; unsigned i; @@ -211,7 +163,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task, clear_color[1] == clear_color[2] && clear_color[2] == clear_color[3]) { /* clear to grayscale value {x, x, x, x} */ - for (i = 0; i < rast->state.nr_cbufs; i++) { + for (i = 0; i < scene->fb.nr_cbufs; i++) { uint8_t *ptr = lp_rast_get_color_tile_pointer(task, i, LP_TEX_USAGE_WRITE_ALL); memset(ptr, clear_color[0], TILE_SIZE * TILE_SIZE * 4); @@ -224,7 +176,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task, * works. */ const unsigned chunk = TILE_SIZE / 4; - for (i = 0; i < rast->state.nr_cbufs; i++) { + for (i = 0; i < scene->fb.nr_cbufs; i++) { uint8_t *c = lp_rast_get_color_tile_pointer(task, i, LP_TEX_USAGE_WRITE_ALL); unsigned j; @@ -246,21 +198,25 @@ lp_rast_clear_color(struct lp_rasterizer_task *task, } + + + + /** * Clear the rasterizer's current z/stencil tile. * This is a bin command called during bin processing. */ -void +static void lp_rast_clear_zstencil(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; unsigned clear_value = arg.clear_zstencil.value; unsigned clear_mask = arg.clear_zstencil.mask; const unsigned height = TILE_SIZE / TILE_VECTOR_HEIGHT; const unsigned width = TILE_SIZE * TILE_VECTOR_HEIGHT; - const unsigned block_size = rast->zsbuf.blocksize; - const unsigned dst_stride = rast->zsbuf.stride * TILE_VECTOR_HEIGHT; + const unsigned block_size = scene->zsbuf.blocksize; + const unsigned dst_stride = scene->zsbuf.stride * TILE_VECTOR_HEIGHT; uint8_t *dst; unsigned i, j; @@ -326,14 +282,13 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, * threading/parallelism. * This is a bin command which is stored in all bins. */ -void +static void lp_rast_store_linear_color( struct lp_rasterizer_task *task ) { - struct lp_rasterizer *rast = task->rast; - struct lp_scene *scene = rast->curr_scene; + const struct lp_scene *scene = task->scene; unsigned buf; - for (buf = 0; buf < rast->state.nr_cbufs; buf++) { + for (buf = 0; buf < scene->fb.nr_cbufs; buf++) { struct pipe_surface *cbuf = scene->fb.cbufs[buf]; const unsigned face_slice = cbuf->face + cbuf->zslice; const unsigned level = cbuf->level; @@ -357,11 +312,11 @@ lp_rast_store_linear_color( struct lp_rasterizer_task *task ) * completely contained inside a triangle. * This is a bin command called during bin processing. */ -void +static void lp_rast_shade_tile(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; const struct lp_rast_shader_inputs *inputs = arg.shade_tile; const struct lp_rast_state *state = inputs->state; struct lp_fragment_shader_variant *variant = state->variant; @@ -383,7 +338,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task, unsigned i; /* color buffer */ - for (i = 0; i < rast->state.nr_cbufs; i++) + for (i = 0; i < scene->fb.nr_cbufs; i++) color[i] = lp_rast_get_color_block_pointer(task, i, tile_x + x, tile_y + y); @@ -413,17 +368,17 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task, * completely contained inside a triangle, and the shader is opaque. * This is a bin command called during bin processing. */ -void +static void lp_rast_shade_tile_opaque(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; unsigned i; LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); /* this will prevent converting the layout from tiled to linear */ - for (i = 0; i < rast->state.nr_cbufs; i++) { + for (i = 0; i < scene->fb.nr_cbufs; i++) { (void)lp_rast_get_color_tile_pointer(task, i, LP_TEX_USAGE_WRITE_ALL); } @@ -445,7 +400,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task, { const struct lp_rast_state *state = inputs->state; struct lp_fragment_shader_variant *variant = state->variant; - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; uint8_t *color[PIPE_MAX_COLOR_BUFS]; void *depth; unsigned i; @@ -460,7 +415,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task, assert((y % 4) == 0); /* color buffer */ - for (i = 0; i < rast->state.nr_cbufs; i++) { + for (i = 0; i < scene->fb.nr_cbufs; i++) { color[i] = lp_rast_get_color_block_pointer(task, i, x, y); assert(lp_check_alignment(color[i], 16)); } @@ -493,7 +448,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task, * This is a bin command put in all bins. * Called per thread. */ -void +static void lp_rast_begin_query(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { @@ -510,7 +465,7 @@ lp_rast_begin_query(struct lp_rasterizer_task *task, * This is a bin command put in all bins. * Called per thread. */ -void +static void lp_rast_end_query(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { @@ -581,10 +536,10 @@ lp_rast_tile_end(struct lp_rasterizer_task *task) { #ifdef DEBUG if (LP_DEBUG & (DEBUG_SHOW_SUBTILES | DEBUG_SHOW_TILES)) { - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; unsigned buf; - for (buf = 0; buf < rast->state.nr_cbufs; buf++) { + for (buf = 0; buf < scene->fb.nr_cbufs; buf++) { uint8_t *color = lp_rast_get_color_block_pointer(task, buf, task->x, task->y); @@ -608,10 +563,44 @@ lp_rast_tile_end(struct lp_rasterizer_task *task) /* debug */ memset(task->color_tiles, 0, sizeof(task->color_tiles)); task->depth_tile = NULL; + + task->bin = NULL; } +static lp_rast_cmd_func dispatch[LP_RAST_OP_MAX] = +{ + lp_rast_clear_color, + lp_rast_clear_zstencil, + lp_rast_triangle_1, + lp_rast_triangle_2, + lp_rast_triangle_3, + lp_rast_triangle_4, + lp_rast_triangle_5, + lp_rast_triangle_6, + lp_rast_triangle_7, + lp_rast_triangle_8, + lp_rast_triangle_3_16, + lp_rast_shade_tile, + lp_rast_shade_tile_opaque, + lp_rast_begin_query, + lp_rast_end_query, +}; +static void +do_rasterize_bin(struct lp_rasterizer_task *task, + const struct cmd_bin *bin) +{ + const struct cmd_block *block; + unsigned k; + + for (block = bin->head; block; block = block->next) { + for (k = 0; k < block->count; k++) { + dispatch[block->cmd[k]]( task, block->arg[k] ); + } + } +} + /** @@ -622,26 +611,25 @@ lp_rast_tile_end(struct lp_rasterizer_task *task) */ static void rasterize_bin(struct lp_rasterizer_task *task, - const struct cmd_bin *bin, - int x, int y) + const struct cmd_bin *bin ) { - const struct cmd_block_list *commands = &bin->commands; - struct cmd_block *block; - unsigned k; - - lp_rast_tile_begin( task, x * TILE_SIZE, y * TILE_SIZE ); + lp_rast_tile_begin( task, bin ); - /* simply execute each of the commands in the block list */ - for (block = commands->head; block; block = block->next) { - for (k = 0; k < block->count; k++) { - block->cmd[k]( task, block->arg[k] ); - } - } + do_rasterize_bin(task, bin); lp_rast_tile_end(task); -} + /* Debug/Perf flags: + */ + if (bin->head->count == 1) { + if (bin->head->cmd[0] == LP_RAST_OP_SHADE_TILE_OPAQUE) + LP_COUNT(nr_pure_shade_opaque_64); + else if (bin->head->cmd[0] == LP_RAST_OP_SHADE_TILE) + LP_COUNT(nr_pure_shade_64); + } +} + /* An empty bin is one that just loads the contents of the tile and * stores them again unchanged. This typically happens when bins have @@ -653,11 +641,10 @@ rasterize_bin(struct lp_rasterizer_task *task, static boolean is_empty_bin( const struct cmd_bin *bin ) { - return bin->commands.head == NULL; + return bin->head == NULL; } - /** * Rasterize/execute all bins within a scene. * Called per thread. @@ -666,6 +653,7 @@ static void rasterize_scene(struct lp_rasterizer_task *task, struct lp_scene *scene) { + task->scene = scene; /* loop over scene bins, rasterize each */ #if 0 { @@ -680,12 +668,11 @@ rasterize_scene(struct lp_rasterizer_task *task, #else { struct cmd_bin *bin; - int x, y; assert(scene); - while ((bin = lp_scene_bin_iter_next(scene, &x, &y))) { + while ((bin = lp_scene_bin_iter_next(scene))) { if (!is_empty_bin( bin )) - rasterize_bin(task, bin, x, y); + rasterize_bin(task, bin); } } #endif @@ -693,6 +680,8 @@ rasterize_scene(struct lp_rasterizer_task *task, if (scene->fence) { lp_fence_signal(scene->fence); } + + task->scene = NULL; } @@ -712,8 +701,6 @@ lp_rast_queue_scene( struct lp_rasterizer *rast, rasterize_scene( &rast->tasks[0], scene ); - lp_scene_reset( scene ); - lp_rast_end( rast ); rast->curr_scene = NULL; diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 4697054e8d..5f3059e794 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -79,8 +79,8 @@ struct lp_rast_state { */ struct lp_rast_shader_inputs { float facing; /** Positive for front-facing, negative for back-facing */ - boolean opaque:1; /** Is opaque */ boolean disable:1; /** Partially binned, disable this command */ + boolean opaque:1; /** Is opaque */ float (*a0)[4]; float (*dadx)[4]; @@ -205,18 +205,18 @@ lp_rast_arg_clearzs( unsigned value, unsigned mask ) static INLINE union lp_rast_cmd_arg -lp_rast_arg_null( void ) +lp_rast_arg_query( struct llvmpipe_query *pq ) { union lp_rast_cmd_arg arg; - arg.set_state = NULL; + arg.query_obj = pq; return arg; } static INLINE union lp_rast_cmd_arg -lp_rast_arg_query( struct llvmpipe_query *pq ) +lp_rast_arg_null( void ) { union lp_rast_cmd_arg arg; - arg.query_obj = pq; + arg.set_state = NULL; return arg; } @@ -226,54 +226,23 @@ lp_rast_arg_query( struct llvmpipe_query *pq ) * These get put into bins by the setup code and are called when * the bins are executed. */ - -void lp_rast_clear_color( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_clear_zstencil( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_triangle_1( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_2( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_3( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_4( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_5( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_6( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_7( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); -void lp_rast_triangle_8( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_shade_tile( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_shade_tile_opaque( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_fence( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_store_linear_color( struct lp_rasterizer_task *); - - -void lp_rast_begin_query(struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_restart_query(struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void lp_rast_end_query(struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); - -void -lp_rast_triangle_3_16(struct lp_rasterizer_task *task, - const union lp_rast_cmd_arg arg); - +#define LP_RAST_OP_CLEAR_COLOR 0x0 +#define LP_RAST_OP_CLEAR_ZSTENCIL 0x1 +#define LP_RAST_OP_TRIANGLE_1 0x2 +#define LP_RAST_OP_TRIANGLE_2 0x3 +#define LP_RAST_OP_TRIANGLE_3 0x4 +#define LP_RAST_OP_TRIANGLE_4 0x5 +#define LP_RAST_OP_TRIANGLE_5 0x6 +#define LP_RAST_OP_TRIANGLE_6 0x7 +#define LP_RAST_OP_TRIANGLE_7 0x8 +#define LP_RAST_OP_TRIANGLE_8 0x9 +#define LP_RAST_OP_TRIANGLE_3_16 0xa +#define LP_RAST_OP_SHADE_TILE 0xb +#define LP_RAST_OP_SHADE_TILE_OPAQUE 0xc +#define LP_RAST_OP_BEGIN_QUERY 0xd +#define LP_RAST_OP_END_QUERY 0xe + +#define LP_RAST_OP_MAX 0xf +#define LP_RAST_OP_MASK 0xff #endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index 6bc1015912..b1b4546bb8 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -69,13 +69,16 @@ extern const struct lp_rast_state *jit_state; struct lp_rasterizer; - +struct cmd_bin; /** * Per-thread rasterization state */ struct lp_rasterizer_task { + const struct cmd_bin *bin; + + struct lp_scene *scene; unsigned x, y; /**< Pos of this tile in framebuffer, in pixels */ uint8_t *color_tiles[PIPE_MAX_COLOR_BUFS]; @@ -105,33 +108,9 @@ struct lp_rasterizer { boolean exit_flag; - /* Framebuffer stuff - */ - struct { - uint8_t *map; - unsigned stride; - unsigned blocksize; - } zsbuf; - - struct { - unsigned nr_cbufs; - unsigned clear_color; - unsigned clear_depth; - char clear_stencil; - } state; - /** The incoming queue of scenes ready to rasterize */ struct lp_scene_queue *full_scenes; - /** - * The outgoing queue of processed scenes to return to setup module - * - * XXX: while scenes are per-context but the rasterizer is - * (potentially) shared, these empty scenes should be returned to - * the context which created them rather than retained here. - */ - /* struct lp_scene_queue *empty_scenes; */ - /** The scene currently being rasterized by the threads */ struct lp_scene *curr_scene; @@ -165,13 +144,13 @@ static INLINE void * lp_rast_get_depth_block_pointer(struct lp_rasterizer_task *task, unsigned x, unsigned y) { - const struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; void *depth; assert((x % TILE_VECTOR_WIDTH) == 0); assert((y % TILE_VECTOR_HEIGHT) == 0); - if (!rast->zsbuf.map) { + if (!scene->zsbuf.map) { /* Either out of memory or no zsbuf. Can't tell without access * to the state. Just use dummy tile memory, but don't print * the oom warning as this most likely because there is no @@ -180,9 +159,9 @@ lp_rast_get_depth_block_pointer(struct lp_rasterizer_task *task, return lp_dummy_tile; } - depth = (rast->zsbuf.map + - rast->zsbuf.stride * y + - rast->zsbuf.blocksize * x * TILE_VECTOR_HEIGHT); + depth = (scene->zsbuf.map + + scene->zsbuf.stride * y + + scene->zsbuf.blocksize * x * TILE_VECTOR_HEIGHT); assert(lp_check_alignment(depth, 16)); return depth; @@ -196,14 +175,14 @@ static INLINE uint8_t * lp_rast_get_color_tile_pointer(struct lp_rasterizer_task *task, unsigned buf, enum lp_texture_usage usage) { - struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; assert(task->x % TILE_SIZE == 0); assert(task->y % TILE_SIZE == 0); - assert(buf < rast->state.nr_cbufs); + assert(buf < scene->fb.nr_cbufs); if (!task->color_tiles[buf]) { - struct pipe_surface *cbuf = rast->curr_scene->fb.cbufs[buf]; + struct pipe_surface *cbuf = scene->fb.cbufs[buf]; struct llvmpipe_resource *lpt; assert(cbuf); lpt = llvmpipe_resource(cbuf->texture); @@ -264,7 +243,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, const struct lp_rast_shader_inputs *inputs, unsigned x, unsigned y ) { - const struct lp_rasterizer *rast = task->rast; + const struct lp_scene *scene = task->scene; const struct lp_rast_state *state = inputs->state; struct lp_fragment_shader_variant *variant = state->variant; uint8_t *color[PIPE_MAX_COLOR_BUFS]; @@ -272,7 +251,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, unsigned i; /* color buffer */ - for (i = 0; i < rast->state.nr_cbufs; i++) + for (i = 0; i < scene->fb.nr_cbufs; i++) color[i] = lp_rast_get_color_block_pointer(task, i, x, y); depth = lp_rast_get_depth_block_pointer(task, x, y); @@ -292,5 +271,25 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, END_JIT_CALL(); } +void lp_rast_triangle_1( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_2( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_3( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_4( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_5( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_6( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_7( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); +void lp_rast_triangle_8( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); + +void lp_rast_triangle_3_16( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); + #endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h b/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h index eca25bbf2a..52b9012036 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h @@ -162,6 +162,11 @@ TAG(lp_rast_triangle)(struct lp_rasterizer_task *task, unsigned outmask, inmask, partmask, partial_mask; unsigned j = 0; + if (tri->inputs.disable) { + /* This triangle was partially binned and has been disabled */ + return; + } + outmask = 0; /* outside one or more trivial reject planes */ partmask = 0; /* outside one or more trivial accept planes */ diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 67bc7475f5..2a26896e62 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -30,10 +30,10 @@ #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_simple_list.h" +#include "util/u_format.h" #include "lp_scene.h" -#include "lp_debug.h" -#include "lp_scene_queue.h" #include "lp_fence.h" +#include "lp_debug.h" #define RESOURCE_REF_SZ 32 @@ -51,15 +51,14 @@ struct resource_ref { * \param queue the queue to put newly rendered/emptied scenes into */ struct lp_scene * -lp_scene_create( struct pipe_context *pipe, - struct lp_scene_queue *queue ) +lp_scene_create( struct pipe_context *pipe ) { struct lp_scene *scene = CALLOC_STRUCT(lp_scene); if (!scene) return NULL; scene->pipe = pipe; - scene->empty_queue = queue; + scene->data.head = &scene->data.first; pipe_mutex_init(scene->mutex); @@ -73,9 +72,8 @@ lp_scene_create( struct pipe_context *pipe, void lp_scene_destroy(struct lp_scene *scene) { - lp_scene_reset(scene); - pipe_mutex_destroy(scene->mutex); + assert(scene->data.head == &scene->data.first); FREE(scene); } @@ -92,8 +90,7 @@ lp_scene_is_empty(struct lp_scene *scene ) for (y = 0; y < TILES_Y; y++) { for (x = 0; x < TILES_X; x++) { const struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); - const struct cmd_block_list *list = &bin->commands; - if (list->head) { + if (bin->head) { return FALSE; } } @@ -103,8 +100,8 @@ lp_scene_is_empty(struct lp_scene *scene ) /* Returns true if there has ever been a failed allocation attempt in - * this scene. Used in triangle/rectangle emit to avoid having to - * check success at each bin. + * this scene. Used in triangle emit to avoid having to check success + * at each bin. */ boolean lp_scene_is_oom(struct lp_scene *scene) @@ -120,31 +117,90 @@ void lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y) { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); - struct cmd_block_list *list = &bin->commands; - list->head = list->tail; - if (list->tail) { - list->tail->next = NULL; - list->tail->count = 0; + bin->head = bin->tail; + if (bin->tail) { + bin->tail->next = NULL; + bin->tail->count = 0; + } +} + + +void +lp_scene_begin_rasterization(struct lp_scene *scene) +{ + const struct pipe_framebuffer_state *fb = &scene->fb; + int i; + + //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); + + for (i = 0; i < scene->fb.nr_cbufs; i++) { + struct pipe_surface *cbuf = scene->fb.cbufs[i]; + scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture, + cbuf->level); + + scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture, + cbuf->face, + cbuf->level, + cbuf->zslice, + LP_TEX_USAGE_READ_WRITE, + LP_TEX_LAYOUT_LINEAR); + } + + if (fb->zsbuf) { + struct pipe_surface *zsbuf = scene->fb.zsbuf; + scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->level); + scene->zsbuf.blocksize = + util_format_get_blocksize(zsbuf->texture->format); + + scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture, + zsbuf->face, + zsbuf->level, + zsbuf->zslice, + LP_TEX_USAGE_READ_WRITE, + LP_TEX_LAYOUT_NONE); } } + + /** - * Free all the temporary data in a scene. May be called from the - * rasterizer thread(s). + * Free all the temporary data in a scene. */ void -lp_scene_reset(struct lp_scene *scene ) +lp_scene_end_rasterization(struct lp_scene *scene ) { int i, j; + /* Unmap color buffers */ + for (i = 0; i < scene->fb.nr_cbufs; i++) { + if (scene->cbufs[i].map) { + struct pipe_surface *cbuf = scene->fb.cbufs[i]; + llvmpipe_resource_unmap(cbuf->texture, + cbuf->face, + cbuf->level, + cbuf->zslice); + scene->cbufs[i].map = NULL; + } + } + + /* Unmap z/stencil buffer */ + if (scene->zsbuf.map) { + struct pipe_surface *zsbuf = scene->fb.zsbuf; + llvmpipe_resource_unmap(zsbuf->texture, + zsbuf->face, + zsbuf->level, + zsbuf->zslice); + scene->zsbuf.map = NULL; + } + /* Reset all command lists: */ for (i = 0; i < scene->tiles_x; i++) { for (j = 0; j < scene->tiles_y; j++) { struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); - memset(bin, 0, sizeof *bin); + bin->head = bin->tail = NULL; } } @@ -186,10 +242,12 @@ lp_scene_reset(struct lp_scene *scene ) for (block = list->head; block; block = tmp) { tmp = block->next; - FREE(block); + if (block != &list->first) + FREE(block); } - list->head = NULL; + list->head = &list->first; + list->head->next = NULL; } lp_fence_reference(&scene->fence, NULL); @@ -200,6 +258,8 @@ lp_scene_reset(struct lp_scene *scene ) scene->has_depthstencil_clear = FALSE; scene->alloc_failed = FALSE; + + util_unreference_framebuffer_state( &scene->fb ); } @@ -213,13 +273,13 @@ lp_scene_new_cmd_block( struct lp_scene *scene, { struct cmd_block *block = lp_scene_alloc(scene, sizeof(struct cmd_block)); if (block) { - if (bin->commands.tail) { - bin->commands.tail->next = block; - bin->commands.tail = block; + if (bin->tail) { + bin->tail->next = block; + bin->tail = block; } else { - bin->commands.head = block; - bin->commands.tail = block; + bin->head = block; + bin->tail = block; } //memset(block, 0, sizeof *block); block->next = NULL; @@ -269,27 +329,14 @@ lp_scene_data_size( const struct lp_scene *scene ) } -/** Return number of bytes used for a single bin */ -static unsigned -lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y ) -{ - struct cmd_bin *bin = lp_scene_get_bin((struct lp_scene *) scene, x, y); - const struct cmd_block *cmd; - unsigned size = 0; - for (cmd = bin->commands.head; cmd; cmd = cmd->next) { - size += (cmd->count * - (sizeof(lp_rast_cmd) + sizeof(union lp_rast_cmd_arg))); - } - return size; -} - /** * Add a reference to a resource by the scene. */ boolean lp_scene_add_resource_reference(struct lp_scene *scene, - struct pipe_resource *resource) + struct pipe_resource *resource, + boolean initializing_scene) { struct resource_ref *ref, **last = &scene->resources; int i; @@ -327,7 +374,17 @@ lp_scene_add_resource_reference(struct lp_scene *scene, add_new_ref: pipe_resource_reference(&ref->resource[ref->count++], resource); scene->resource_reference_size += llvmpipe_resource_size(resource); - return scene->resource_reference_size < LP_SCENE_MAX_RESOURCE_SIZE; + + /* Heuristic to advise scene flushes. This isn't helpful in the + * initial setup of the scene, but after that point flush on the + * next resource added which exceeds 64MB in referenced texture + * data. + */ + if (!initializing_scene && + scene->resource_reference_size < LP_SCENE_MAX_RESOURCE_SIZE) + return FALSE; + + return TRUE; } @@ -384,7 +441,7 @@ lp_scene_bin_iter_begin( struct lp_scene *scene ) * of work (a bin) to work on. */ struct cmd_bin * -lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y ) +lp_scene_bin_iter_next( struct lp_scene *scene ) { struct cmd_bin *bin = NULL; @@ -401,8 +458,6 @@ lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y ) } bin = lp_scene_get_bin(scene, scene->curr_x, scene->curr_y); - *bin_x = scene->curr_x; - *bin_y = scene->curr_y; end: /*printf("return bin %p at %d, %d\n", (void *) bin, *bin_x, *bin_y);*/ @@ -426,34 +481,13 @@ void lp_scene_begin_binning( struct lp_scene *scene, } -void lp_scene_rasterize( struct lp_scene *scene, - struct lp_rasterizer *rast ) +void lp_scene_end_binning( struct lp_scene *scene ) { - if (0) { - unsigned x, y; + if (LP_DEBUG & DEBUG_SCENE) { debug_printf("rasterize scene:\n"); - debug_printf(" data size: %u\n", lp_scene_data_size(scene)); - for (y = 0; y < scene->tiles_y; y++) { - for (x = 0; x < scene->tiles_x; x++) { - debug_printf(" bin %u, %u size: %u\n", x, y, - lp_scene_bin_size(scene, x, y)); - } - } + debug_printf(" scene_size: %u\n", + scene->scene_size); + debug_printf(" data size: %u\n", + lp_scene_data_size(scene)); } - - /* Enqueue the scene for rasterization, then immediately wait for - * it to finish. - */ - lp_rast_queue_scene( rast, scene ); - - /* Currently just wait for the rasterizer to finish. Some - * threading interactions need to be worked out, particularly once - * transfers become per-context: - */ - lp_rast_finish( rast ); - - util_unreference_framebuffer_state( &scene->fb ); - - /* put scene into the empty list */ - lp_scene_enqueue( scene->empty_queue, scene ); } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index d4f7b047c2..cc19def3b1 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -63,11 +63,12 @@ struct lp_scene_queue; /* switch to a non-pointer value for this: */ -typedef void (*lp_rast_cmd)( struct lp_rasterizer_task *, - const union lp_rast_cmd_arg ); +typedef void (*lp_rast_cmd_func)( struct lp_rasterizer_task *, + const union lp_rast_cmd_arg ); + struct cmd_block { - lp_rast_cmd cmd[CMD_BLOCK_MAX]; + uint8_t cmd[CMD_BLOCK_MAX]; union lp_rast_cmd_arg arg[CMD_BLOCK_MAX]; unsigned count; struct cmd_block *next; @@ -90,7 +91,10 @@ struct data_block { * For each screen tile we have one of these bins. */ struct cmd_bin { - struct cmd_block_list commands; + ushort x; + ushort y; + struct cmd_block *head; + struct cmd_block *tail; }; @@ -100,8 +104,12 @@ struct cmd_bin { * * Examples include triangle data and state data. The commands in * the per-tile bins will point to chunks of data in this structure. + * + * Include the first block of data statically to ensure we can always + * initiate a scene without relying on malloc succeeding. */ struct data_block_list { + struct data_block first; struct data_block *head; }; @@ -119,6 +127,15 @@ struct lp_scene { struct pipe_context *pipe; struct lp_fence *fence; + /* Framebuffer mappings - valid only between begin_rasterization() + * and end_rasterization(). + */ + struct { + uint8_t *map; + unsigned stride; + unsigned blocksize; + } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS]; + /** the framebuffer to render the scene into */ struct pipe_framebuffer_state fb; @@ -137,7 +154,6 @@ struct lp_scene { unsigned resource_reference_size; boolean alloc_failed; - boolean has_depthstencil_clear; /** @@ -149,26 +165,19 @@ struct lp_scene { int curr_x, curr_y; /**< for iterating over bins */ pipe_mutex mutex; - /* Where to place this scene once it has been rasterized: - */ - struct lp_scene_queue *empty_queue; - struct cmd_bin tile[TILES_X][TILES_Y]; struct data_block_list data; }; -struct lp_scene *lp_scene_create(struct pipe_context *pipe, - struct lp_scene_queue *empty_queue); +struct lp_scene *lp_scene_create(struct pipe_context *pipe); void lp_scene_destroy(struct lp_scene *scene); boolean lp_scene_is_empty(struct lp_scene *scene ); boolean lp_scene_is_oom(struct lp_scene *scene ); -void lp_scene_reset(struct lp_scene *scene ); - struct data_block *lp_scene_new_data_block( struct lp_scene *scene ); @@ -176,7 +185,8 @@ struct cmd_block *lp_scene_new_cmd_block( struct lp_scene *scene, struct cmd_bin *bin ); boolean lp_scene_add_resource_reference(struct lp_scene *scene, - struct pipe_resource *resource); + struct pipe_resource *resource, + boolean initializing_scene); boolean lp_scene_is_resource_referenced(const struct lp_scene *scene, const struct pipe_resource *resource ); @@ -193,8 +203,9 @@ lp_scene_alloc( struct lp_scene *scene, unsigned size) struct data_block *block = list->head; assert(size <= DATA_BLOCK_SIZE); + assert(block != NULL); - if (block == NULL || block->used + size > DATA_BLOCK_SIZE) { + if (block->used + size > DATA_BLOCK_SIZE) { block = lp_scene_new_data_block( scene ); if (!block) { /* out of memory */ @@ -220,8 +231,9 @@ lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, struct data_block_list *list = &scene->data; struct data_block *block = list->head; - if (block == NULL || - block->used + size + alignment - 1 > DATA_BLOCK_SIZE) { + assert(block != NULL); + + if (block->used + size + alignment - 1 > DATA_BLOCK_SIZE) { block = lp_scene_new_data_block( scene ); if (!block) return NULL; @@ -264,15 +276,16 @@ lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y); */ static INLINE boolean lp_scene_bin_command( struct lp_scene *scene, - unsigned x, unsigned y, - lp_rast_cmd cmd, - union lp_rast_cmd_arg arg ) + unsigned x, unsigned y, + unsigned cmd, + union lp_rast_cmd_arg arg ) { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); - struct cmd_block *tail = bin->commands.tail; + struct cmd_block *tail = bin->tail; assert(x < scene->tiles_x); assert(y < scene->tiles_y); + assert(cmd <= LP_RAST_OP_END_QUERY); if (tail == NULL || tail->count == CMD_BLOCK_MAX) { tail = lp_scene_new_cmd_block( scene, bin ); @@ -284,7 +297,7 @@ lp_scene_bin_command( struct lp_scene *scene, { unsigned i = tail->count; - tail->cmd[i] = cmd; + tail->cmd[i] = cmd & LP_RAST_OP_MASK; tail->arg[i] = arg; tail->count++; } @@ -297,7 +310,7 @@ lp_scene_bin_command( struct lp_scene *scene, */ static INLINE boolean lp_scene_bin_everywhere( struct lp_scene *scene, - lp_rast_cmd cmd, + unsigned cmd, const union lp_rast_cmd_arg arg ) { unsigned i, j; @@ -323,17 +336,30 @@ void lp_scene_bin_iter_begin( struct lp_scene *scene ); struct cmd_bin * -lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y ); +lp_scene_bin_iter_next( struct lp_scene *scene ); -void -lp_scene_rasterize( struct lp_scene *scene, - struct lp_rasterizer *rast ); +/* Begin/end binning of a scene + */ void lp_scene_begin_binning( struct lp_scene *scene, struct pipe_framebuffer_state *fb ); +void +lp_scene_end_binning( struct lp_scene *scene ); + + +/* Begin/end rasterization of a scene + */ +void +lp_scene_begin_rasterization(struct lp_scene *scene); + +void +lp_scene_end_rasterization(struct lp_scene *scene ); + + + #endif /* LP_BIN_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 4cb6166bad..f653dd5f0b 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -42,7 +42,6 @@ #include "lp_context.h" #include "lp_memory.h" #include "lp_scene.h" -#include "lp_scene_queue.h" #include "lp_texture.h" #include "lp_debug.h" #include "lp_fence.h" @@ -57,16 +56,31 @@ #include "draw/draw_vbuf.h" -static void set_scene_state( struct lp_setup_context *, enum setup_state ); +static void set_scene_state( struct lp_setup_context *, enum setup_state, + const char *reason); +static boolean try_update_scene_state( struct lp_setup_context *setup ); -struct lp_scene * -lp_setup_get_current_scene(struct lp_setup_context *setup) +static void +lp_setup_get_empty_scene(struct lp_setup_context *setup) { - if (!setup->scene) { - set_scene_state( setup, SETUP_EMPTY ); + assert(setup->scene == NULL); + + setup->scene_idx++; + setup->scene_idx %= Elements(setup->scenes); + + setup->scene = setup->scenes[setup->scene_idx]; + + if (setup->scene->fence) { + if (LP_DEBUG & DEBUG_SETUP) + debug_printf("%s: wait for scene %d\n", + __FUNCTION__, setup->scene->fence->id); + + lp_fence_wait(setup->scene->fence); } - return setup->scene; + + lp_scene_begin_binning(setup->scene, &setup->fb); + } @@ -76,7 +90,7 @@ first_triangle( struct lp_setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { - set_scene_state( setup, SETUP_ACTIVE ); + assert(setup->state == SETUP_ACTIVE); lp_setup_choose_triangle( setup ); setup->triangle( setup, v0, v1, v2 ); } @@ -86,7 +100,7 @@ first_line( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { - set_scene_state( setup, SETUP_ACTIVE ); + assert(setup->state == SETUP_ACTIVE); lp_setup_choose_line( setup ); setup->line( setup, v0, v1 ); } @@ -95,12 +109,12 @@ static void first_point( struct lp_setup_context *setup, const float (*v0)[4]) { - set_scene_state( setup, SETUP_ACTIVE ); + assert(setup->state == SETUP_ACTIVE); lp_setup_choose_point( setup ); setup->point( setup, v0 ); } -static void reset_context( struct lp_setup_context *setup ) +static void lp_setup_reset( struct lp_setup_context *setup ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -130,19 +144,23 @@ static void reset_context( struct lp_setup_context *setup ) static void lp_setup_rasterize_scene( struct lp_setup_context *setup ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_scene *scene = setup->scene; struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); + lp_scene_end_binning(scene); + lp_fence_reference(&setup->last_fence, scene->fence); if (setup->last_fence) setup->last_fence->issued = TRUE; pipe_mutex_lock(screen->rast_mutex); - lp_scene_rasterize(scene, screen->rast); + lp_rast_queue_scene(screen->rast, scene); + lp_rast_finish(screen->rast); pipe_mutex_unlock(screen->rast_mutex); - reset_context( setup ); + lp_scene_end_rasterization(setup->scene); + lp_setup_reset( setup ); LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); } @@ -152,8 +170,10 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup ) static void begin_binning( struct lp_setup_context *setup ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_scene *scene = setup->scene; boolean need_zsload = FALSE; + boolean ok; + unsigned i, j; assert(scene); assert(scene->fence == NULL); @@ -162,6 +182,17 @@ begin_binning( struct lp_setup_context *setup ) */ scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); + /* Initialize the bin flags and x/y coords: + */ + for (i = 0; i < scene->tiles_x; i++) { + for (j = 0; j < scene->tiles_y; j++) { + scene->tile[i][j].x = i; + scene->tile[i][j].y = j; + } + } + + ok = try_update_scene_state(setup); + assert(ok); if (setup->fb.zsbuf && ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && @@ -175,7 +206,7 @@ begin_binning( struct lp_setup_context *setup ) if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) { ok = lp_scene_bin_everywhere( scene, - lp_rast_clear_color, + LP_RAST_OP_CLEAR_COLOR, setup->clear.color ); assert(ok); } @@ -186,22 +217,26 @@ begin_binning( struct lp_setup_context *setup ) if (!need_zsload) scene->has_depthstencil_clear = TRUE; ok = lp_scene_bin_everywhere( scene, - lp_rast_clear_zstencil, + LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( - setup->clear.zsmask, - setup->clear.zsvalue)); + setup->clear.zsvalue, + setup->clear.zsmask)); assert(ok); } } if (setup->active_query) { ok = lp_scene_bin_everywhere( scene, - lp_rast_begin_query, + LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(setup->active_query) ); assert(ok); } + setup->clear.flags = 0; + setup->clear.zsmask = 0; + setup->clear.zsvalue = 0; + LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); } @@ -217,50 +252,53 @@ execute_clears( struct lp_setup_context *setup ) LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); begin_binning( setup ); - lp_setup_rasterize_scene( setup ); } +const char *states[] = { + "FLUSHED", + "EMPTY ", + "CLEARED", + "ACTIVE " +}; + static void set_scene_state( struct lp_setup_context *setup, - enum setup_state new_state ) + enum setup_state new_state, + const char *reason) { unsigned old_state = setup->state; if (old_state == new_state) return; - - LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state); - - switch (new_state) { - case SETUP_EMPTY: - assert(old_state == SETUP_FLUSHED); - assert(setup->scene == NULL); + + if (LP_DEBUG & DEBUG_SETUP) { + debug_printf("%s old %s new %s%s%s\n", + __FUNCTION__, + states[old_state], + states[new_state], + (new_state == SETUP_FLUSHED) ? ": " : "", + (new_state == SETUP_FLUSHED) ? reason : ""); + } - /* wait for a free/empty scene - */ - setup->scene = lp_scene_dequeue(setup->empty_scenes, TRUE); - lp_scene_begin_binning(setup->scene, - &setup->fb ); - break; + /* wait for a free/empty scene + */ + if (old_state == SETUP_FLUSHED) + lp_setup_get_empty_scene(setup); + switch (new_state) { case SETUP_CLEARED: - assert(old_state == SETUP_EMPTY); - assert(setup->scene != NULL); break; case SETUP_ACTIVE: - assert(old_state == SETUP_EMPTY || - old_state == SETUP_CLEARED); - assert(setup->scene != NULL); begin_binning( setup ); break; case SETUP_FLUSHED: if (old_state == SETUP_CLEARED) execute_clears( setup ); - else - lp_setup_rasterize_scene( setup ); + + lp_setup_rasterize_scene( setup ); assert(setup->scene == NULL); break; @@ -281,9 +319,7 @@ lp_setup_flush( struct lp_setup_context *setup, struct pipe_fence_handle **fence, const char *reason) { - LP_DBG(DEBUG_SETUP, "%s %s\n", __FUNCTION__, reason); - - set_scene_state( setup, SETUP_FLUSHED ); + set_scene_state( setup, SETUP_FLUSHED, reason ); if (fence) { lp_fence_reference((struct lp_fence **)fence, setup->last_fence); @@ -299,7 +335,7 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup, /* Flush any old scene. */ - set_scene_state( setup, SETUP_FLUSHED ); + set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); /* * Ensure the old scene is not reused. @@ -325,30 +361,34 @@ lp_setup_try_clear( struct lp_setup_context *setup, unsigned stencil, unsigned flags ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); uint32_t zsmask = 0; uint32_t zsvalue = 0; - uint8_t clear_color[4]; + union lp_rast_cmd_arg color_arg; unsigned i; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); if (flags & PIPE_CLEAR_COLOR) { for (i = 0; i < 4; i++) - clear_color[i] = float_to_ubyte(color[i]); + color_arg.clear_color[i] = float_to_ubyte(color[i]); } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { + unsigned zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; + unsigned smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; + zsvalue = util_pack_z_stencil(setup->fb.zsbuf->format, depth, stencil); zsmask = util_pack_uint_z_stencil(setup->fb.zsbuf->format, - 0xffffffff, - 0xff); + zmask, + smask); } if (setup->state == SETUP_ACTIVE) { + struct lp_scene *scene = setup->scene; + /* Add the clear to existing scene. In the unusual case where * both color and depth-stencil are being cleared when there's * already been some rendering, we could discard the currently @@ -357,15 +397,15 @@ lp_setup_try_clear( struct lp_setup_context *setup, */ if (flags & PIPE_CLEAR_COLOR) { if (!lp_scene_bin_everywhere( scene, - lp_rast_clear_color, - setup->clear.color )) + LP_RAST_OP_CLEAR_COLOR, + color_arg )) return FALSE; } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { if (!lp_scene_bin_everywhere( scene, - lp_rast_clear_zstencil, - lp_rast_arg_clearzs(zsmask, zsvalue) )) + LP_RAST_OP_CLEAR_ZSTENCIL, + lp_rast_arg_clearzs(zsvalue, zsmask) )) return FALSE; } } @@ -375,7 +415,7 @@ lp_setup_try_clear( struct lp_setup_context *setup, * buffers which the app or state-tracker might issue * separately. */ - set_scene_state( setup, SETUP_CLEARED ); + set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); setup->clear.flags |= flags; @@ -387,11 +427,11 @@ lp_setup_try_clear( struct lp_setup_context *setup, if (flags & PIPE_CLEAR_COLOR) { memcpy(setup->clear.color.clear_color, - clear_color, - sizeof clear_color); + &color_arg, + sizeof color_arg); } } - + return TRUE; } @@ -677,21 +717,20 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup, static boolean try_update_scene_state( struct lp_setup_context *setup ) { - struct lp_scene *scene; - - LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - - scene = lp_setup_get_current_scene(setup); + boolean new_scene = (setup->fs.stored == NULL); + struct lp_scene *scene = setup->scene; - assert(setup->fs.current.variant); + assert(scene); if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { uint8_t *stored; unsigned i, j; stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); - if (!stored) + if (!stored) { + assert(!new_scene); return FALSE; + } /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { @@ -722,8 +761,10 @@ try_update_scene_state( struct lp_setup_context *setup ) void *stored; stored = lp_scene_alloc(scene, current_size); - if (!stored) + if (!stored) { + assert(!new_scene); return FALSE; + } memcpy(stored, current_data, @@ -756,8 +797,10 @@ try_update_scene_state( struct lp_setup_context *setup ) * and append it to the bin's setup data buffer. */ stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); - if (!stored) + if (!stored) { + assert(!new_scene); return FALSE; + } memcpy(stored, &setup->fs.current, @@ -770,8 +813,11 @@ try_update_scene_state( struct lp_setup_context *setup ) for (i = 0; i < Elements(setup->fs.current_tex); i++) { if (setup->fs.current_tex[i]) { if (!lp_scene_add_resource_reference(scene, - setup->fs.current_tex[i])) + setup->fs.current_tex[i], + new_scene)) { + assert(!new_scene); return FALSE; + } } } } @@ -792,7 +838,8 @@ try_update_scene_state( struct lp_setup_context *setup ) } void -lp_setup_update_state( struct lp_setup_context *setup ) +lp_setup_update_state( struct lp_setup_context *setup, + boolean update_scene ) { /* Some of the 'draw' pipeline stages may have changed some driver state. * Make sure we've processed those state changes before anything else. @@ -814,13 +861,19 @@ lp_setup_update_state( struct lp_setup_context *setup ) assert(lp->dirty == 0); } - /* XXX: only call into update_scene_state() if we already have a + if (update_scene) + set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ ); + + /* Only call into update_scene_state() if we already have a * scene: */ - if (!try_update_scene_state(setup)) { - set_scene_state( setup, SETUP_FLUSHED ); - if (!try_update_scene_state(setup)) - assert(0); + if (update_scene && setup->scene) { + assert(setup->state == SETUP_ACTIVE); + if (!try_update_scene_state(setup)) { + lp_setup_flush_and_restart(setup); + if (!try_update_scene_state(setup)) + assert(0); + } } } @@ -833,7 +886,7 @@ lp_setup_destroy( struct lp_setup_context *setup ) { uint i; - reset_context( setup ); + lp_setup_reset( setup ); util_unreference_framebuffer_state(&setup->fb); @@ -844,15 +897,15 @@ lp_setup_destroy( struct lp_setup_context *setup ) pipe_resource_reference(&setup->constants.current, NULL); /* free the scenes in the 'empty' queue */ - while (1) { - struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes, FALSE); - if (!scene) - break; + for (i = 0; i < Elements(setup->scenes); i++) { + struct lp_scene *scene = setup->scenes[i]; + + if (scene->fence) + lp_fence_wait(scene->fence); + lp_scene_destroy(scene); } - lp_scene_queue_destroy(setup->empty_scenes); - FREE( setup ); } @@ -879,9 +932,6 @@ lp_setup_create( struct pipe_context *pipe, */ setup->pipe = pipe; - setup->empty_scenes = lp_scene_queue_create(); - if (!setup->empty_scenes) - goto fail; setup->num_threads = screen->num_threads; setup->vbuf = draw_vbuf_stage(draw, &setup->base); @@ -893,9 +943,7 @@ lp_setup_create( struct pipe_context *pipe, /* create some empty scenes */ for (i = 0; i < MAX_SCENES; i++) { - setup->scenes[i] = lp_scene_create( pipe, setup->empty_scenes ); - - lp_scene_enqueue(setup->empty_scenes, setup->scenes[i]); + setup->scenes[i] = lp_scene_create( pipe ); } setup->triangle = first_triangle; @@ -910,9 +958,6 @@ fail: if (setup->vbuf) ; - if (setup->empty_scenes) - lp_scene_queue_destroy(setup->empty_scenes); - FREE(setup); return NULL; } @@ -930,12 +975,13 @@ lp_setup_begin_query(struct lp_setup_context *setup, if (setup->scene) { if (!lp_scene_bin_everywhere(setup->scene, - lp_rast_begin_query, + LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { + lp_setup_flush_and_restart(setup); if (!lp_scene_bin_everywhere(setup->scene, - lp_rast_begin_query, + LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(pq))) { assert(0); return; @@ -969,7 +1015,9 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) */ lp_fence_reference(&pq->fence, setup->scene->fence); - if (!lp_scene_bin_everywhere(setup->scene, lp_rast_end_query, dummy)) { + if (!lp_scene_bin_everywhere(setup->scene, + LP_RAST_OP_END_QUERY, + dummy)) { lp_setup_flush(setup, 0, NULL, __FUNCTION__); } } @@ -985,8 +1033,8 @@ lp_setup_flush_and_restart(struct lp_setup_context *setup) if (0) debug_printf("%s\n", __FUNCTION__); assert(setup->state == SETUP_ACTIVE); - set_scene_state(setup, SETUP_FLUSHED); - set_scene_state(setup, SETUP_EMPTY); - set_scene_state(setup, SETUP_ACTIVE); - lp_setup_update_state(setup); + set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__); + lp_setup_update_state(setup, TRUE); } + + diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 3126cf112c..80b356476a 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -49,8 +49,6 @@ #define LP_SETUP_NEW_SCISSOR 0x08 -struct lp_scene_queue; - /** Max number of scenes */ #define MAX_SCENES 2 @@ -84,9 +82,9 @@ struct lp_setup_context */ struct draw_stage *vbuf; unsigned num_threads; + unsigned scene_idx; struct lp_scene *scenes[MAX_SCENES]; /**< all the scenes */ struct lp_scene *scene; /**< current scene being built */ - struct lp_scene_queue *empty_scenes; /**< queue of empty scenes */ struct lp_fence *last_fence; struct llvmpipe_query *active_query; @@ -115,7 +113,6 @@ struct lp_setup_context enum setup_state { SETUP_FLUSHED, /**< scene is null */ - SETUP_EMPTY, /**< scene exists but has only state changes */ SETUP_CLEARED, /**< scene exists but has only clears */ SETUP_ACTIVE /**< scene exists and has at least one draw/query */ } state; @@ -161,14 +158,15 @@ void lp_setup_choose_triangle( struct lp_setup_context *setup ); void lp_setup_choose_line( struct lp_setup_context *setup ); void lp_setup_choose_point( struct lp_setup_context *setup ); -struct lp_scene *lp_setup_get_current_scene(struct lp_setup_context *setup); - void lp_setup_init_vbuf(struct lp_setup_context *setup); -void lp_setup_update_state( struct lp_setup_context *setup ); +void lp_setup_update_state( struct lp_setup_context *setup, + boolean update_scene); void lp_setup_destroy( struct lp_setup_context *setup ); +void lp_setup_flush_and_restart(struct lp_setup_context *setup); + void lp_setup_print_triangle(struct lp_setup_context *setup, const float (*v0)[4], @@ -196,4 +194,3 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, void lp_setup_flush_and_restart(struct lp_setup_context *setup); #endif - diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c index c9d3d7a456..9f090d1992 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_line.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c @@ -268,7 +268,7 @@ try_setup_line( struct lp_setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_scene *scene = setup->scene; struct lp_rast_triangle *line; struct lp_line_info info; float width = MAX2(1.0, setup->line_width); @@ -585,6 +585,8 @@ try_setup_line( struct lp_setup_context *setup, line->inputs.facing = 1.0F; line->inputs.state = setup->fs.stored; + line->inputs.disable = FALSE; + line->inputs.opaque = FALSE; for (i = 0; i < 4; i++) { struct lp_rast_plane *plane = &line->plane[i]; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c index fd6b53e2bb..5538987151 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c @@ -229,7 +229,7 @@ try_setup_point( struct lp_setup_context *setup, const int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset) - fixed_width/2; const int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset) - fixed_width/2; - struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_scene *scene = setup->scene; struct lp_rast_triangle *point; unsigned bytes; struct u_rect bbox; @@ -289,6 +289,8 @@ try_setup_point( struct lp_setup_context *setup, point->inputs.facing = 1.0F; point->inputs.state = setup->fs.stored; + point->inputs.disable = FALSE; + point->inputs.opaque = FALSE; { point->plane[0].dcdx = -1; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index d8dd9ab7ca..e3cc3f494c 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -160,16 +160,17 @@ lp_setup_print_triangle(struct lp_setup_context *setup, } -lp_rast_cmd lp_rast_tri_tab[9] = { - NULL, /* should be impossible */ - lp_rast_triangle_1, - lp_rast_triangle_2, - lp_rast_triangle_3, - lp_rast_triangle_4, - lp_rast_triangle_5, - lp_rast_triangle_6, - lp_rast_triangle_7, - lp_rast_triangle_8 +static unsigned +lp_rast_tri_tab[9] = { + 0, /* should be impossible */ + LP_RAST_OP_TRIANGLE_1, + LP_RAST_OP_TRIANGLE_2, + LP_RAST_OP_TRIANGLE_3, + LP_RAST_OP_TRIANGLE_4, + LP_RAST_OP_TRIANGLE_5, + LP_RAST_OP_TRIANGLE_6, + LP_RAST_OP_TRIANGLE_7, + LP_RAST_OP_TRIANGLE_8 }; @@ -199,12 +200,12 @@ lp_setup_whole_tile(struct lp_setup_context *setup, LP_COUNT(nr_shade_opaque_64); return lp_scene_bin_command( scene, tx, ty, - lp_rast_shade_tile_opaque, - lp_rast_arg_inputs(inputs) ); + LP_RAST_OP_SHADE_TILE_OPAQUE, + lp_rast_arg_inputs(inputs) ); } else { LP_COUNT(nr_shade_64); return lp_scene_bin_command( scene, tx, ty, - lp_rast_shade_tile, + LP_RAST_OP_SHADE_TILE, lp_rast_arg_inputs(inputs) ); } } @@ -222,8 +223,7 @@ do_triangle_ccw(struct lp_setup_context *setup, const float (*v2)[4], boolean frontfacing ) { - struct lp_scene *scene = lp_setup_get_current_scene(setup); - struct lp_fragment_shader_variant *variant = setup->fs.current.variant; + struct lp_scene *scene = setup->scene; struct lp_rast_triangle *tri; int x[3]; int y[3]; @@ -236,7 +236,7 @@ do_triangle_ccw(struct lp_setup_context *setup, unsigned tri_bytes; int i; int nr_planes = 3; - + if (0) lp_setup_print_triangle(setup, v0, v1, v2); @@ -280,13 +280,13 @@ do_triangle_ccw(struct lp_setup_context *setup, bbox.y1 < bbox.y0) { if (0) debug_printf("empty bounding box\n"); LP_COUNT(nr_culled_tris); - return FALSE; + return TRUE; } if (!u_rect_test_intersection(&setup->draw_region, &bbox)) { if (0) debug_printf("offscreen\n"); LP_COUNT(nr_culled_tris); - return FALSE; + return TRUE; } u_rect_find_intersection(&setup->draw_region, &bbox); @@ -355,11 +355,10 @@ do_triangle_ccw(struct lp_setup_context *setup, lp_setup_tri_coef( setup, &tri->inputs, &info ); tri->inputs.facing = frontfacing ? 1.0F : -1.0F; - tri->inputs.opaque = variant->opaque; tri->inputs.disable = FALSE; + tri->inputs.opaque = setup->fs.current.variant->opaque; tri->inputs.state = setup->fs.stored; - for (i = 0; i < 3; i++) { struct lp_rast_plane *plane = &tri->plane[i]; @@ -496,7 +495,7 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, int mask = (ix0 & 3) | ((iy0 & 3) << 4); return lp_scene_bin_command( scene, ix0/4, iy0/4, - lp_rast_triangle_3_16, + LP_RAST_OP_TRIANGLE_3_16, lp_rast_arg_triangle(tri, mask) ); } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c index 51948f5bf2..6308561f24 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -64,7 +64,7 @@ lp_setup_get_vertex_info(struct vbuf_render *vbr) /* Vertex size/info depends on the latest state. * The draw module may have issued additional state-change commands. */ - lp_setup_update_state(setup); + lp_setup_update_state(setup, FALSE); return setup->vertex_info; } @@ -141,7 +141,7 @@ lp_setup_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) const boolean flatshade_first = setup->flatshade_first; unsigned i; - lp_setup_update_state(setup); + lp_setup_update_state(setup, TRUE); switch (setup->prim) { case PIPE_PRIM_POINTS: @@ -338,7 +338,7 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) const boolean flatshade_first = setup->flatshade_first; unsigned i; - lp_setup_update_state(setup); + lp_setup_update_state(setup, TRUE); switch (setup->prim) { case PIPE_PRIM_POINTS: diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index d43b2f6358..8f3976c0f9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -824,13 +824,6 @@ generate_variant(struct llvmpipe_context *lp, memcpy(&variant->key, key, shader->variant_key_size); - if (gallivm_debug & GALLIVM_DEBUG_IR) { - lp_debug_fs_variant(variant); - } - - generate_fragment(lp, shader, variant, RAST_WHOLE); - generate_fragment(lp, shader, variant, RAST_EDGE_TEST); - /* * Determine whether we are touching all channels in the color buffer. */ @@ -854,6 +847,14 @@ generate_variant(struct llvmpipe_context *lp, !shader->info.uses_kill ? TRUE : FALSE; + + if (gallivm_debug & GALLIVM_DEBUG_IR) { + lp_debug_fs_variant(variant); + } + + generate_fragment(lp, shader, variant, RAST_WHOLE); + generate_fragment(lp, shader, variant, RAST_EDGE_TEST); + return variant; } @@ -900,6 +901,9 @@ llvmpipe_create_fs_state(struct pipe_context *pipe, debug_printf("\n"); } + /* Keep a copy of the tokens in shader->base.tokens */ + shader->base.tokens = tgsi_dup_tokens(templ->tokens); + return shader; } diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 63ddc669c2..164242eda6 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -68,16 +68,16 @@ lp_resource_copy(struct pipe_context *pipe, 0, /* flush_flags */ FALSE, /* read_only */ TRUE, /* cpu_access */ - FALSE, - "blit dst"); /* do_not_block */ + FALSE, /* do_not_block */ + "blit dest"); llvmpipe_flush_resource(pipe, src, subsrc.face, subsrc.level, 0, /* flush_flags */ TRUE, /* read_only */ TRUE, /* cpu_access */ - FALSE, - "blit src"); /* do_not_block */ + FALSE, /* do_not_block */ + "blit src"); /* printf("surface copy from %u to %u: %u,%u to %u,%u %u x %u\n", diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 5832ea2744..a4b9f2590a 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -585,7 +585,7 @@ llvmpipe_get_transfer(struct pipe_context *pipe, read_only, TRUE, /* cpu_access */ do_not_block, - "transfer dest")) { + __FUNCTION__)) { /* * It would have blocked, but state tracker requested no to. */ -- cgit v1.2.3