Using the GPU has a cost, it implies preparing the RS/BLT request and then possibly requires extra GPU -> CPU syncs, so let's only use GPU-based tiling/untiling for rather big regions.
While at it, move the "should we use the GPU to tile/untile" logic to its own function to make things more readable. Signed-off-by: Boris Brezillon <[email protected]> --- .../drivers/etnaviv/etnaviv_transfer.c | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c index 38648564b701..a3013e624ead 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -132,6 +132,66 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) slab_free(&ctx->transfer_pool, trans); } +#define GPU_TILING_MIN_SURFACE_SIZE 1024 +#define GPU_TILING_MIN_UNALIGNED_SURFACE_SIZE 8192 + +static bool +etna_transfer_use_gpu(struct etna_context *ctx, struct etna_resource *rsc, + const struct pipe_box *box) +{ + unsigned w_align, h_align; + + /* Always use the GPU to tile/untile when the resource has a Tile Status + * buffer attached. */ + if (rsc->ts_bo) + return true; + + /* Nothing to tile/untile if the resource is using a linear format. */ + if (rsc->layout == ETNA_LAYOUT_LINEAR) + return false; + + /* Do not use the GPU when the resource is using a 1byte/pixel format. */ + if (util_format_get_blocksize(rsc->base.format) == 1) + return false; + + /* HALIGN 4 resources are incompatible with the resolve engine, so fall back + * to using software to detile this resource. */ + if (rsc->halign == TEXTURE_HALIGN_FOUR) + return false; + + /* Using the GPU has a cost, it implies preparing the RS/BLT request and + * then possibly requires extra GPU -> CPU syncs, so let's only use + * GPU-based tiling for rather big regions. Right now the minimum surface + * surface size is arbitrarily set to 1024 pixels. */ + if (box->width * box->height < GPU_TILING_MIN_SURFACE_SIZE) + return false; + + /* No alignment constraints when using BLT. */ + if (ctx->specs.use_blt) + return true; + + if (rsc->layout & ETNA_LAYOUT_BIT_SUPER) { + w_align = h_align = 64; + } else { + w_align = ETNA_RS_WIDTH_MASK + 1; + h_align = ETNA_RS_HEIGHT_MASK + 1; + } + h_align *= ctx->screen->specs.pixel_pipes; + + /* Everything is properly aligned, let's use the RS engine to + * tile/untile. */ + if (!((box->x | box->width) & (w_align - 1)) && + !((box->y | box->height) & (h_align - 1))) + return true; + + /* We want the minimum surface size to be even bigger for unaligned + * requests. */ + if (box->width * box->height < GPU_TILING_MIN_UNALIGNED_SURFACE_SIZE) + return false; + + return true; +} + static void * etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, @@ -179,12 +239,7 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, * render resource. Use the texture resource, which avoids bouncing * pixels between the two resources, and we can de-tile it in s/w. */ rsc = etna_resource(rsc->texture); - } else if (rsc->ts_bo || - (rsc->layout != ETNA_LAYOUT_LINEAR && - util_format_get_blocksize(format) > 1 && - /* HALIGN 4 resources are incompatible with the resolve engine, - * so fall back to using software to detile this resource. */ - rsc->halign != TEXTURE_HALIGN_FOUR)) { + } else if (etna_transfer_use_gpu(ctx, rsc, box)) { /* If the surface has tile status, we need to resolve it first. * The strategy we implement here is to use the RS to copy the * depth buffer, filling in the "holes" where the tile status -- 2.20.1 _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
