[Mesa-dev] [RFC PATCH 1/2] etnaviv: add support for CPU-based super/multi tile tiling/untiling
Boris Brezillon
boris.brezillon at collabora.com
Wed Feb 20 17:01:36 UTC 2019
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 <boris.brezillon at collabora.com>
---
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
More information about the mesa-dev
mailing list