Sometimes using CPU based untiling/tiling makes, like when updating a really small region of the texture atlas which is not RS-aligned. CPU-based support for simple tile layout was already supported, but not the multi/super tile cases. Make the etna_texture_[un]tile() more generic to support those cases.
Signed-off-by: Boris Brezillon <[email protected]> --- src/gallium/drivers/etnaviv/etnaviv_tiling.c | 85 ++++++++++++++++--- src/gallium/drivers/etnaviv/etnaviv_tiling.h | 10 ++- .../drivers/etnaviv/etnaviv_transfer.c | 16 ++-- 3 files changed, 84 insertions(+), 27 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_tiling.c b/src/gallium/drivers/etnaviv/etnaviv_tiling.c index f4f85c1d6e6c..7e2b8bd48d3a 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_tiling.c +++ b/src/gallium/drivers/etnaviv/etnaviv_tiling.c @@ -32,39 +32,95 @@ #define TEX_TILE_WIDTH (4) #define TEX_TILE_HEIGHT (4) #define TEX_TILE_WORDS (TEX_TILE_WIDTH * TEX_TILE_HEIGHT) +#define TEX_SUPERTILE_WIDTH (64) +#define TEX_SUPERTILE_HEIGHT (64) +#define TEX_SUPERTILE_TWIDTH (16) +#define TEX_SUPERTILE_THEIGHT (16) +#define TEX_SUPERTILE_WORDS (TEX_SUPERTILE_WIDTH * TEX_SUPERTILE_HEIGHT) +#define TEX_TILES_PER_SUPERTILE (TEX_SUPERTILE_TWIDTH * TEX_SUPERTILE_THEIGHT) + +static unsigned tile_buf_offset(enum etna_surface_layout tlayout, + unsigned tx, unsigned ty, + unsigned tstride, unsigned th, + unsigned elmtsize) +{ + unsigned offs = 0, tile; + unsigned tiles_per_line = (tstride / elmtsize) / TEX_TILE_WIDTH; + + /* Multi tile layouts are described here: + * https://github.com/laanwj/etna_viv/blob/master/doc/hardware.md#multi-tiling + */ + if (tlayout & ETNA_LAYOUT_BIT_MULTI) { + if ((((tx / (TEX_TILE_WIDTH * 2)) & 1) ^ ((ty / TEX_TILE_HEIGHT) & 1))) { + offs += ((tstride / elmtsize) * (th / 2)); + if ((tx / (TEX_TILE_WIDTH * 2)) & 1) + tx -= TEX_TILE_WIDTH * 2; + else + tx += TEX_TILE_HEIGHT * 2; + } + + ty = ((ty / 2) & ~(TEX_TILE_HEIGHT - 1)) + + (ty % TEX_TILE_HEIGHT); + } + + if (tlayout & ETNA_LAYOUT_BIT_SUPER) { + /* We use the supertile layout described here: + * https://github.com/laanwj/etna_viv/blob/master/doc/hardware.md#supertiling + * FIXME: According to + * https://github.com/laanwj/etna_viv/blob/master/tools/detiler.py + * another layout exists. We should probably support CPU-based detiling + * for this layout too and determine the layout to used based on HW + * features. */ + tile = (ty / TEX_SUPERTILE_HEIGHT) * tiles_per_line * + TEX_SUPERTILE_THEIGHT; + ty &= TEX_SUPERTILE_HEIGHT - 1; + tile += (tx / TEX_SUPERTILE_WIDTH) * TEX_TILES_PER_SUPERTILE; + tx &= TEX_SUPERTILE_WIDTH - 1; + tile += (ty / (4 * TEX_TILE_HEIGHT)) * 16 * 4; + ty &= (4 * TEX_TILE_HEIGHT) - 1; + tile += (ty / TEX_TILE_HEIGHT) * 2; + tile += ((tx / TEX_TILE_WIDTH) & ~0x1) * 4; + tile += (tx / TEX_TILE_WIDTH) & 0x1; + } else { + tile = (ty / TEX_TILE_HEIGHT) * tiles_per_line; + tile += tx / TEX_TILE_WIDTH; + } + + offs += tile * TEX_TILE_WORDS; + ty &= TEX_TILE_HEIGHT - 1; + tx &= TEX_TILE_WIDTH - 1; + offs += (ty * TEX_TILE_WIDTH) + tx; + + return offs; +} #define DO_TILE(type) \ src_stride /= sizeof(type); \ - dst_stride = (dst_stride * TEX_TILE_HEIGHT) / sizeof(type); \ for (unsigned srcy = 0; srcy < height; ++srcy) { \ - unsigned dsty = basey + srcy; \ - unsigned ty = (dsty / TEX_TILE_HEIGHT) * dst_stride + \ - (dsty % TEX_TILE_HEIGHT) * TEX_TILE_WIDTH; \ for (unsigned srcx = 0; srcx < width; ++srcx) { \ - unsigned dstx = basex + srcx; \ - ((type *)dest)[ty + (dstx / TEX_TILE_WIDTH) * TEX_TILE_WORDS + \ - (dstx % TEX_TILE_WIDTH)] = \ + unsigned destoffs = tile_buf_offset(baselayout, basex + srcx, \ + basey + srcy, dst_stride, \ + baseh, elmtsize); \ + ((type *)dest)[destoffs] = \ ((type *)src)[srcy * src_stride + srcx]; \ } \ } #define DO_UNTILE(type) \ - src_stride = (src_stride * TEX_TILE_HEIGHT) / sizeof(type); \ dst_stride /= sizeof(type); \ for (unsigned dsty = 0; dsty < height; ++dsty) { \ - unsigned srcy = basey + dsty; \ - unsigned sy = (srcy / TEX_TILE_HEIGHT) * src_stride + \ - (srcy % TEX_TILE_HEIGHT) * TEX_TILE_WIDTH; \ for (unsigned dstx = 0; dstx < width; ++dstx) { \ - unsigned srcx = basex + dstx; \ + unsigned srcoffs = tile_buf_offset(baselayout, basex + dstx, \ + basey + dsty, src_stride, \ + baseh, elmtsize); \ ((type *)dest)[dsty * dst_stride + dstx] = \ - ((type *)src)[sy + (srcx / TEX_TILE_WIDTH) * TEX_TILE_WORDS + \ - (srcx % TEX_TILE_WIDTH)]; \ + ((type *)src)[srcoffs]; \ } \ } void etna_texture_tile(void *dest, void *src, unsigned basex, unsigned basey, + enum etna_surface_layout baselayout, unsigned int baseh, unsigned dst_stride, unsigned width, unsigned height, unsigned src_stride, unsigned elmtsize) { @@ -81,6 +137,7 @@ etna_texture_tile(void *dest, void *src, unsigned basex, unsigned basey, void etna_texture_untile(void *dest, void *src, unsigned basex, unsigned basey, + enum etna_surface_layout baselayout, unsigned int baseh, unsigned src_stride, unsigned width, unsigned height, unsigned dst_stride, unsigned elmtsize) { diff --git a/src/gallium/drivers/etnaviv/etnaviv_tiling.h b/src/gallium/drivers/etnaviv/etnaviv_tiling.h index 3c69e22463dc..f18ba09796f5 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_tiling.h +++ b/src/gallium/drivers/etnaviv/etnaviv_tiling.h @@ -43,12 +43,14 @@ enum etna_surface_layout { void etna_texture_tile(void *dest, void *src, unsigned basex, unsigned basey, - unsigned dst_stride, unsigned width, unsigned height, - unsigned src_stride, unsigned elmtsize); + enum etna_surface_layout baselayout, unsigned int baseh, + unsigned dst_stride, unsigned width, unsigned height, + unsigned src_stride, unsigned elmtsize); void etna_texture_untile(void *dest, void *src, unsigned basex, unsigned basey, - unsigned src_stride, unsigned width, unsigned height, - unsigned dst_stride, unsigned elmtsize); + enum etna_surface_layout baselayout, unsigned int baseh, + unsigned src_stride, unsigned width, unsigned height, + unsigned dst_stride, unsigned elmtsize); /* XXX from/to supertiling (can have different layouts, may be better * to leave to RS) */ diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c index 30ae3bfc39dd..38648564b701 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -93,10 +93,11 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) struct etna_resource_level *res_level = &rsc->levels[ptrans->level]; void *mapped = etna_bo_map(rsc->bo) + res_level->offset; - if (rsc->layout == ETNA_LAYOUT_TILED) { + if (rsc->layout & ETNA_LAYOUT_BIT_TILE) { etna_texture_tile( mapped + ptrans->box.z * res_level->layer_stride, trans->staging, ptrans->box.x, ptrans->box.y, + rsc->layout, res_level->padded_height, res_level->stride, ptrans->box.width, ptrans->box.height, ptrans->stride, util_format_get_blocksize(rsc->base.format)); } else if (rsc->layout == ETNA_LAYOUT_LINEAR) { @@ -106,8 +107,6 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) ptrans->box.height, ptrans->box.depth, trans->staging, ptrans->stride, ptrans->layer_stride, 0, 0, 0 /* src x,y,z */); - } else { - BUG("unsupported tiling %i", rsc->layout); } FREE(trans->staging); @@ -359,11 +358,13 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, goto fail; if (usage & PIPE_TRANSFER_READ) { - if (rsc->layout == ETNA_LAYOUT_TILED) { + if (rsc->layout & ETNA_LAYOUT_BIT_TILE) { etna_texture_untile(trans->staging, mapped + ptrans->box.z * res_level->layer_stride, - ptrans->box.x, ptrans->box.y, res_level->stride, - ptrans->box.width, ptrans->box.height, ptrans->stride, + ptrans->box.x, ptrans->box.y, + rsc->layout, res_level->padded_height, + res_level->stride, ptrans->box.width, + ptrans->box.height, ptrans->stride, util_format_get_blocksize(rsc->base.format)); } else if (rsc->layout == ETNA_LAYOUT_LINEAR) { util_copy_box(trans->staging, rsc->base.format, ptrans->stride, @@ -372,9 +373,6 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, ptrans->box.depth, mapped, res_level->stride, res_level->layer_stride, ptrans->box.x, ptrans->box.y, ptrans->box.z); - } else { - /* TODO supertiling */ - BUG("unsupported tiling %i for reading", rsc->layout); } } -- 2.20.1 _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
