From dc8fc39adac79cb8cbf59fc7ae5536536dceb52a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Jun 2014 12:12:27 +1000 Subject: [PATCH] softpipe: add layering to the surface tile cache. This adds the layer info to the tile cache. This changes clear_flags to be dynamically allocated as MAX_LAYERS seems like a too big step. Reviewed-by: Roland Scheidegger Signed-off-by: Dave Airlie --- src/gallium/drivers/softpipe/sp_quad_blend.c | 8 +- .../drivers/softpipe/sp_quad_depth_test.c | 2 +- .../drivers/softpipe/sp_quad_depth_test_tmp.h | 2 +- src/gallium/drivers/softpipe/sp_tile_cache.c | 153 +++++++++++------- src/gallium/drivers/softpipe/sp_tile_cache.h | 19 ++- 5 files changed, 112 insertions(+), 72 deletions(-) diff --git a/src/gallium/drivers/softpipe/sp_quad_blend.c b/src/gallium/drivers/softpipe/sp_quad_blend.c index 41149a06b63..ae7ecd0fe85 100644 --- a/src/gallium/drivers/softpipe/sp_quad_blend.c +++ b/src/gallium/drivers/softpipe/sp_quad_blend.c @@ -935,7 +935,7 @@ blend_fallback(struct quad_stage *qs, struct softpipe_cached_tile *tile = sp_get_cached_tile(softpipe->cbuf_cache[cbuf], quads[0]->input.x0, - quads[0]->input.y0); + quads[0]->input.y0, 0); const boolean clamp = bqs->clamp[cbuf]; const float *blend_color; const boolean dual_source_blend = util_blend_state_is_dual(blend, cbuf); @@ -1038,7 +1038,7 @@ blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs, struct softpipe_cached_tile *tile = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], quads[0]->input.x0, - quads[0]->input.y0); + quads[0]->input.y0, 0); for (q = 0; q < nr; q++) { struct quad_header *quad = quads[q]; @@ -1112,7 +1112,7 @@ blend_single_add_one_one(struct quad_stage *qs, struct softpipe_cached_tile *tile = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], quads[0]->input.x0, - quads[0]->input.y0); + quads[0]->input.y0, 0); for (q = 0; q < nr; q++) { struct quad_header *quad = quads[q]; @@ -1180,7 +1180,7 @@ single_output_color(struct quad_stage *qs, struct softpipe_cached_tile *tile = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], quads[0]->input.x0, - quads[0]->input.y0); + quads[0]->input.y0, 0); for (q = 0; q < nr; q++) { struct quad_header *quad = quads[q]; diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index be2504e1884..367218a91b7 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -801,7 +801,7 @@ depth_test_quads_fallback(struct quad_stage *qs, data.format = data.ps->format; data.tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, quads[0]->input.x0, - quads[0]->input.y0); + quads[0]->input.y0, 0); data.clamp = !qs->softpipe->rasterizer->depth_clip; near_val = qs->softpipe->viewport.translate[2] - qs->softpipe->viewport.scale[2]; diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test_tmp.h b/src/gallium/drivers/softpipe/sp_quad_depth_test_tmp.h index 25af415c256..e7b70f7ea65 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test_tmp.h +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test_tmp.h @@ -71,7 +71,7 @@ NAME(struct quad_stage *qs, depth_step = (ushort)(dzdx * scale); - tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, ix, iy); + tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, ix, iy, 0); for (i = 0; i < nr; i++) { const unsigned outmask = quads[i]->inout.mask; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index e68fecc2bb3..ceb66f67502 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -48,20 +48,27 @@ sp_alloc_tile(struct softpipe_tile_cache *tc); * At some point we should investige something more sophisticated, like * a LRU replacement policy. */ -#define CACHE_POS(x, y) \ - (((x) + (y) * 5) % NUM_ENTRIES) - +#define CACHE_POS(x, y, l) \ + (((x) + (y) * 5 + (l) * 10) % NUM_ENTRIES) +static INLINE int addr_to_clear_pos(union tile_address addr) +{ + int pos; + pos = addr.bits.layer * (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE); + pos += addr.bits.y * (MAX_WIDTH / TILE_SIZE); + pos += addr.bits.x; + return pos; +} /** * Is the tile at (x,y) in cleared state? */ static INLINE uint -is_clear_flag_set(const uint *bitvec, union tile_address addr) +is_clear_flag_set(const uint *bitvec, union tile_address addr, unsigned max) { int pos, bit; - pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x; - assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32); + pos = addr_to_clear_pos(addr); + assert(pos / 32 < max); bit = bitvec[pos / 32] & (1 << (pos & 31)); return bit; } @@ -71,11 +78,11 @@ is_clear_flag_set(const uint *bitvec, union tile_address addr) * Mark the tile at (x,y) as not cleared. */ static INLINE void -clear_clear_flag(uint *bitvec, union tile_address addr) +clear_clear_flag(uint *bitvec, union tile_address addr, unsigned max) { int pos; - pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x; - assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32); + pos = addr_to_clear_pos(addr); + assert(pos / 32 < max); bitvec[pos / 32] &= ~(1 << (pos & 31)); } @@ -140,8 +147,15 @@ sp_destroy_tile_cache(struct softpipe_tile_cache *tc) } FREE( tc->tile ); - if (tc->transfer) { - tc->pipe->transfer_unmap(tc->pipe, tc->transfer); + if (tc->num_maps) { + int i; + for (i = 0; i < tc->num_maps; i++) + if (tc->transfer[i]) { + tc->pipe->transfer_unmap(tc->pipe, tc->transfer[i]); + } + FREE(tc->transfer); + FREE(tc->transfer_map); + FREE(tc->clear_flags); } FREE( tc ); @@ -157,26 +171,45 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { struct pipe_context *pipe = tc->pipe; + int i; - if (tc->transfer_map) { + if (tc->num_maps) { if (ps == tc->surface) return; - pipe->transfer_unmap(pipe, tc->transfer); - tc->transfer = NULL; - tc->transfer_map = NULL; + for (i = 0; i < tc->num_maps; i++) { + pipe->transfer_unmap(pipe, tc->transfer[i]); + tc->transfer[i] = NULL; + tc->transfer_map[i] = NULL; + } + FREE(tc->transfer); + FREE(tc->transfer_map); + tc->num_maps = 0; + + if (tc->clear_flags) + FREE(tc->clear_flags); + tc->clear_flags_size = 0; } tc->surface = ps; if (ps) { + tc->num_maps = ps->u.tex.last_layer - ps->u.tex.first_layer + 1; + tc->transfer = CALLOC(tc->num_maps, sizeof(struct pipe_transfer *)); + tc->transfer_map = CALLOC(tc->num_maps, sizeof(void *)); + + tc->clear_flags_size = (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) * tc->num_maps / 32 * sizeof(uint); + tc->clear_flags = CALLOC(1, tc->clear_flags_size); + if (ps->texture->target != PIPE_BUFFER) { - tc->transfer_map = pipe_transfer_map(pipe, ps->texture, - ps->u.tex.level, ps->u.tex.first_layer, - PIPE_TRANSFER_READ_WRITE | - PIPE_TRANSFER_UNSYNCHRONIZED, - 0, 0, ps->width, ps->height, - &tc->transfer); + for (i = 0; i < tc->num_maps; i++) { + tc->transfer_map[i] = pipe_transfer_map(pipe, ps->texture, + ps->u.tex.level, ps->u.tex.first_layer + i, + PIPE_TRANSFER_READ_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED, + 0, 0, ps->width, ps->height, + &tc->transfer[i]); + } } else { /* can't render to buffers */ @@ -307,17 +340,15 @@ clear_tile(struct softpipe_cached_tile *tile, * Actually clear the tiles which were flagged as being in a clear state. */ static void -sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) +sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc, int layer) { - struct pipe_transfer *pt = tc->transfer; - const uint w = tc->transfer->box.width; - const uint h = tc->transfer->box.height; + struct pipe_transfer *pt = tc->transfer[layer]; + const uint w = tc->transfer[layer]->box.width; + const uint h = tc->transfer[layer]->box.height; uint x, y; uint numCleared = 0; assert(pt->resource); - if (!tc->tile) - tc->tile = sp_alloc_tile(tc); /* clear the scratch tile to the clear value */ if (tc->depth_stencil) { @@ -329,28 +360,28 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) /* push the tile to all positions marked as clear */ for (y = 0; y < h; y += TILE_SIZE) { for (x = 0; x < w; x += TILE_SIZE) { - union tile_address addr = tile_address(x, y); + union tile_address addr = tile_address(x, y, layer); - if (is_clear_flag_set(tc->clear_flags, addr)) { + if (is_clear_flag_set(tc->clear_flags, addr, tc->clear_flags_size)) { /* write the scratch tile to the surface */ if (tc->depth_stencil) { - pipe_put_tile_raw(pt, tc->transfer_map, + pipe_put_tile_raw(pt, tc->transfer_map[layer], x, y, TILE_SIZE, TILE_SIZE, tc->tile->data.any, 0/*STRIDE*/); } else { if (util_format_is_pure_uint(tc->surface->format)) { - pipe_put_tile_ui_format(pt, tc->transfer_map, + pipe_put_tile_ui_format(pt, tc->transfer_map[layer], x, y, TILE_SIZE, TILE_SIZE, pt->resource->format, (unsigned *) tc->tile->data.colorui128); } else if (util_format_is_pure_sint(tc->surface->format)) { - pipe_put_tile_i_format(pt, tc->transfer_map, + pipe_put_tile_i_format(pt, tc->transfer_map[layer], x, y, TILE_SIZE, TILE_SIZE, pt->resource->format, (int *) tc->tile->data.colori128); } else { - pipe_put_tile_rgba(pt, tc->transfer_map, + pipe_put_tile_rgba(pt, tc->transfer_map[layer], x, y, TILE_SIZE, TILE_SIZE, (float *) tc->tile->data.color); } @@ -360,8 +391,6 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) } } - /* reset all clear flags to zero */ - memset(tc->clear_flags, 0, sizeof(tc->clear_flags)); #if 0 debug_printf("num cleared: %u\n", numCleared); @@ -371,9 +400,10 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) static void sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos) { + int layer = tc->tile_addrs[pos].bits.layer; if (!tc->tile_addrs[pos].bits.invalid) { if (tc->depth_stencil) { - pipe_put_tile_raw(tc->transfer, tc->transfer_map, + pipe_put_tile_raw(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -381,21 +411,21 @@ sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos) } else { if (util_format_is_pure_uint(tc->surface->format)) { - pipe_put_tile_ui_format(tc->transfer, tc->transfer_map, + pipe_put_tile_ui_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (unsigned *) tc->entries[pos]->data.colorui128); } else if (util_format_is_pure_sint(tc->surface->format)) { - pipe_put_tile_i_format(tc->transfer, tc->transfer_map, + pipe_put_tile_i_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (int *) tc->entries[pos]->data.colori128); } else { - pipe_put_tile_rgba_format(tc->transfer, tc->transfer_map, + pipe_put_tile_rgba_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -414,10 +444,9 @@ sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos) void sp_flush_tile_cache(struct softpipe_tile_cache *tc) { - struct pipe_transfer *pt = tc->transfer; int inuse = 0, pos; - - if (pt) { + int i; + if (tc->num_maps) { /* caching a drawing transfer */ for (pos = 0; pos < Elements(tc->entries); pos++) { struct softpipe_cached_tile *tile = tc->entries[pos]; @@ -426,13 +455,17 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) assert(tc->tile_addrs[pos].bits.invalid); continue; } - sp_flush_tile(tc, pos); ++inuse; } - sp_tile_cache_flush_clear(tc); + if (!tc->tile) + tc->tile = sp_alloc_tile(tc); + for (i = 0; i < tc->num_maps; i++) + sp_tile_cache_flush_clear(tc, i); + /* reset all clear flags to zero */ + memset(tc->clear_flags, 0, tc->clear_flags_size); tc->last_tile_addr.bits.invalid = 1; } @@ -483,12 +516,12 @@ struct softpipe_cached_tile * sp_find_cached_tile(struct softpipe_tile_cache *tc, union tile_address addr ) { - struct pipe_transfer *pt = tc->transfer; + struct pipe_transfer *pt; /* cache pos/entry: */ const int pos = CACHE_POS(addr.bits.x, - addr.bits.y); + addr.bits.y, addr.bits.layer); struct softpipe_cached_tile *tile = tc->entries[pos]; - + int layer; if (!tile) { tile = sp_alloc_tile(tc); tc->entries[pos] = tile; @@ -497,10 +530,11 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, if (addr.value != tc->tile_addrs[pos].value) { assert(pt->resource); + layer = tc->tile_addrs[pos].bits.layer; if (tc->tile_addrs[pos].bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { - pipe_put_tile_raw(pt, tc->transfer_map, + pipe_put_tile_raw(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -508,21 +542,21 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, } else { if (util_format_is_pure_uint(tc->surface->format)) { - pipe_put_tile_ui_format(pt, tc->transfer_map, + pipe_put_tile_ui_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (unsigned *) tile->data.colorui128); } else if (util_format_is_pure_sint(tc->surface->format)) { - pipe_put_tile_i_format(pt, tc->transfer_map, + pipe_put_tile_i_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (int *) tile->data.colori128); } else { - pipe_put_tile_rgba_format(pt, tc->transfer_map, + pipe_put_tile_rgba_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -534,7 +568,10 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, tc->tile_addrs[pos] = addr; - if (is_clear_flag_set(tc->clear_flags, addr)) { + layer = tc->tile_addrs[pos].bits.layer; + pt = tc->transfer[layer]; + + if (is_clear_flag_set(tc->clear_flags, addr, tc->clear_flags_size)) { /* don't get tile from framebuffer, just clear it */ if (tc->depth_stencil) { clear_tile(tile, pt->resource->format, tc->clear_val); @@ -542,12 +579,12 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, else { clear_tile_rgba(tile, pt->resource->format, &tc->clear_color); } - clear_clear_flag(tc->clear_flags, addr); + clear_clear_flag(tc->clear_flags, addr, tc->clear_flags_size); } else { /* get new tile data from transfer */ if (tc->depth_stencil) { - pipe_get_tile_raw(pt, tc->transfer_map, + pipe_get_tile_raw(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -555,21 +592,21 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, } else { if (util_format_is_pure_uint(tc->surface->format)) { - pipe_get_tile_ui_format(pt, tc->transfer_map, + pipe_get_tile_ui_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (unsigned *) tile->data.colorui128); } else if (util_format_is_pure_sint(tc->surface->format)) { - pipe_get_tile_i_format(pt, tc->transfer_map, + pipe_get_tile_i_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tc->surface->format, (int *) tile->data.colori128); } else { - pipe_get_tile_rgba_format(pt, tc->transfer_map, + pipe_get_tile_rgba_format(tc->transfer[layer], tc->transfer_map[layer], tc->tile_addrs[pos].bits.x * TILE_SIZE, tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -606,7 +643,7 @@ sp_tile_cache_clear(struct softpipe_tile_cache *tc, tc->clear_val = clearValue; /* set flags to indicate all the tiles are cleared */ - memset(tc->clear_flags, 255, sizeof(tc->clear_flags)); + memset(tc->clear_flags, 255, tc->clear_flags_size); for (pos = 0; pos < Elements(tc->tile_addrs); pos++) { tc->tile_addrs[pos].bits.invalid = 1; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index c8b03b3afb6..167e1ffcada 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -54,7 +54,8 @@ union tile_address { unsigned x:TILE_ADDR_BITS; /* 16K / TILE_SIZE */ unsigned y:TILE_ADDR_BITS; /* 16K / TILE_SIZE */ unsigned invalid:1; - unsigned pad:15; + unsigned layer:8; + unsigned pad:7; } bits; unsigned value; }; @@ -82,12 +83,14 @@ struct softpipe_tile_cache { struct pipe_context *pipe; struct pipe_surface *surface; /**< the surface we're caching */ - struct pipe_transfer *transfer; - void *transfer_map; + struct pipe_transfer **transfer; + void **transfer_map; + int num_maps; union tile_address tile_addrs[NUM_ENTRIES]; struct softpipe_cached_tile *entries[NUM_ENTRIES]; - uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32]; + uint *clear_flags; + uint clear_flags_size; union pipe_color_union clear_color; /**< for color bufs */ uint64_t clear_val; /**< for z+stencil */ boolean depth_stencil; /**< Is the surface a depth/stencil format? */ @@ -127,14 +130,14 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, static INLINE union tile_address tile_address( unsigned x, - unsigned y ) + unsigned y, unsigned layer ) { union tile_address addr; addr.value = 0; addr.bits.x = x / TILE_SIZE; addr.bits.y = y / TILE_SIZE; - + addr.bits.layer = layer; return addr; } @@ -142,9 +145,9 @@ tile_address( unsigned x, */ static INLINE struct softpipe_cached_tile * sp_get_cached_tile(struct softpipe_tile_cache *tc, - int x, int y ) + int x, int y, int layer ) { - union tile_address addr = tile_address( x, y ); + union tile_address addr = tile_address( x, y, layer ); if (tc->last_tile_addr.value == addr.value) return tc->last_tile; -- 2.30.2