From 7ef648c0f309c323b0d3c20dec9c58b2cbf70e58 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Sun, 19 Apr 2020 15:44:17 +1200 Subject: [PATCH] panfrost: Tiled to linear layout conversion Tiling is expensive, so this patch converts textures that appear to be used for streaming to a linear layout. Performance of mpv is significantly improved, with software-decoded 1080p mp4 playback on RK3288 going from 30fps to 50fps when testing with `--untimed --no-audio`. To keep things simple, conversion only happens when updating the whole texture and no mipmapping is used. v2: Make it clear that the heuristic doesn't rely on a texture being uninitialized, since layout switching code can get confusing (Alyssa). Reviewed-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/panfrost/pan_resource.c | 51 +++++++++++++++++---- src/gallium/drivers/panfrost/pan_resource.h | 8 ++++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 84f82ab7689..8c1cda9513d 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -427,6 +427,7 @@ panfrost_resource_create_bo(struct panfrost_device *dev, struct panfrost_resourc /* Set the layout appropriately */ assert(!(must_tile && !can_tile)); /* must_tile => can_tile */ pres->layout = ((can_tile && should_tile) || must_tile) ? MALI_TEXTURE_TILED : MALI_TEXTURE_LINEAR; + pres->layout_constant = must_tile || !can_tile; size_t bo_size; @@ -725,14 +726,48 @@ panfrost_transfer_unmap(struct pipe_context *pctx, } else if (prsrc->layout == MALI_TEXTURE_TILED) { assert(transfer->box.depth == 1); - panfrost_store_tiled_image( - bo->cpu + prsrc->slices[transfer->level].offset, - trans->map, - transfer->box.x, transfer->box.y, - transfer->box.width, transfer->box.height, - prsrc->slices[transfer->level].stride, - transfer->stride, - prsrc->internal_format); + /* Do we overwrite the entire resource? If so, + * we don't need an intermediate blit so it's a + * good time to switch the layout. */ + + bool discards_content = prsrc->base.last_level == 0 + && transfer->box.width == prsrc->base.width0 + && transfer->box.height == prsrc->base.height0 + && transfer->box.x == 0 + && transfer->box.y == 0 + && !prsrc->layout_constant; + + /* It also serves as a good heuristic for + * streaming textures (e.g. in video players), + * but we could do better */ + + if (discards_content) + ++prsrc->layout_updates; + + if (prsrc->layout_updates >= LAYOUT_CONVERT_THRESHOLD) + { + prsrc->layout = MALI_TEXTURE_LINEAR; + + util_copy_rect( + bo->cpu + prsrc->slices[0].offset, + prsrc->base.format, + prsrc->slices[0].stride, + 0, 0, + transfer->box.width, + transfer->box.height, + trans->map, + transfer->stride, + 0, 0); + } else { + panfrost_store_tiled_image( + bo->cpu + prsrc->slices[transfer->level].offset, + trans->map, + transfer->box.x, transfer->box.y, + transfer->box.width, transfer->box.height, + prsrc->slices[transfer->level].stride, + transfer->stride, + prsrc->internal_format); + } } } } diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h index 0a25e305de0..c6226cbe272 100644 --- a/src/gallium/drivers/panfrost/pan_resource.h +++ b/src/gallium/drivers/panfrost/pan_resource.h @@ -34,6 +34,8 @@ #include "drm-uapi/drm.h" #include "util/u_range.h" +#define LAYOUT_CONVERT_THRESHOLD 8 + struct panfrost_resource { struct pipe_resource base; struct { @@ -57,9 +59,15 @@ struct panfrost_resource { /* Internal layout (tiled?) */ enum mali_texture_layout layout; + /* Whether the layout can be changed */ + bool layout_constant; + /* Is transaciton elimination enabled? */ bool checksummed; + /* Used to decide when to convert to another layout */ + uint16_t layout_updates; + enum pipe_format internal_format; /* Cached min/max values for index buffers */ -- 2.30.2