X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_scene.c;h=ed998246fb9364e98a6fdb9f09a01d0399b6af85;hb=437ab1d6df7282770ee869180446db36c2dbdfa8;hp=67bc7475f50dc0952f417dba2160b8930a8d9508;hpb=6419ecd02ce43a2614822e228f306d4db589f317;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 67bc7475f50..ed998246fb9 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,16 @@ 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 = + CALLOC_STRUCT(data_block); pipe_mutex_init(scene->mutex); @@ -73,9 +74,10 @@ lp_scene_create( struct pipe_context *pipe, void lp_scene_destroy(struct lp_scene *scene) { - lp_scene_reset(scene); - + lp_fence_reference(&scene->fence, NULL); pipe_mutex_destroy(scene->mutex); + assert(scene->data.head->next == NULL); + FREE(scene->data.head); FREE(scene); } @@ -92,8 +94,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 +104,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 +121,91 @@ 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->last_state = NULL; + 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]; + assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer); + scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture, + cbuf->u.tex.level); + + scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture, + cbuf->u.tex.level, + cbuf->u.tex.first_layer, + LP_TEX_USAGE_READ_WRITE, + LP_TEX_LAYOUT_LINEAR); + } + + if (fb->zsbuf) { + struct pipe_surface *zsbuf = scene->fb.zsbuf; + assert(zsbuf->u.tex.first_layer == zsbuf->u.tex.last_layer); + scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->u.tex.level); + scene->zsbuf.blocksize = + util_format_get_blocksize(zsbuf->texture->format); + + scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture, + zsbuf->u.tex.level, + zsbuf->u.tex.first_layer, + 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->u.tex.level, + cbuf->u.tex.first_layer); + 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->u.tex.level, + zsbuf->u.tex.first_layer); + 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 = NULL; + bin->tail = NULL; + bin->last_state = NULL; } } @@ -164,7 +225,7 @@ lp_scene_reset(struct lp_scene *scene ) if (LP_DEBUG & DEBUG_SETUP) debug_printf("resource %d: %p %dx%d sz %d\n", j, - ref->resource[i], + (void *) ref->resource[i], ref->resource[i]->width0, ref->resource[i]->height0, llvmpipe_resource_size(ref->resource[i])); @@ -184,12 +245,13 @@ lp_scene_reset(struct lp_scene *scene ) struct data_block_list *list = &scene->data; struct data_block *block, *tmp; - for (block = list->head; block; block = tmp) { + for (block = list->head->next; block; block = tmp) { tmp = block->next; - FREE(block); + FREE(block); } - list->head = NULL; + list->head->next = NULL; + list->head->used = 0; } lp_fence_reference(&scene->fence, NULL); @@ -200,6 +262,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 +277,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 +333,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; @@ -297,6 +348,7 @@ lp_scene_add_resource_reference(struct lp_scene *scene, /* Look at existing resource blocks: */ for (ref = scene->resources; ref; ref = ref->next) { + last = &ref->next; /* Search for this resource: */ @@ -304,30 +356,40 @@ lp_scene_add_resource_reference(struct lp_scene *scene, if (ref->resource[i] == resource) return TRUE; - /* If the block is half-empty, this is the last block. Append - * the reference here. - */ - if (ref->count < RESOURCE_REF_SZ) - goto add_new_ref; - - last = &ref->next; + if (ref->count < RESOURCE_REF_SZ) { + /* If the block is half-empty, then append the reference here. + */ + break; + } } - /* Otherwise, need to create a new block: + /* Create a new block if no half-empty block was found. */ - *last = lp_scene_alloc(scene, sizeof(struct resource_ref)); - if (*last) { + if (!ref) { + assert(*last == NULL); + *last = lp_scene_alloc(scene, sizeof *ref); + if (*last == NULL) + return FALSE; + ref = *last; memset(ref, 0, sizeof *ref); - goto add_new_ref; } - return FALSE; - -add_new_ref: + /* Append the reference to the reference block. + */ 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 +446,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 +463,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 +486,16 @@ 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 ); + if (0) + lp_debug_bins( scene ); + } }