panfrost: Choose AFBC when available
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tue, 21 Jul 2020 16:34:33 +0000 (12:34 -0400)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Wed, 12 Aug 2020 13:59:20 +0000 (09:59 -0400)
There are lots of reasons we might fallback on u-interleaved tiling, but
when we can use AFBC, it's a big win.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tested-by: Icecream95 <ixn@keemail.me>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6159>

src/gallium/drivers/panfrost/pan_resource.c
src/panfrost/include/panfrost-quirks.h

index 8226b4b3c3e279b64d7d0d6292c0cdbfc547ac01..7606bfb17b530d52c596c2da22ff472b0334b71a 100644 (file)
@@ -382,7 +382,9 @@ panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size)
  * that the contents frequently change, tiling will be a loss.
  *
  * Due to incomplete information on some platforms, we may need to force tiling
- * in some cases */
+ * in some cases.
+ *
+ * On platforms where it is supported, AFBC is even better. */
 
 static bool
 panfrost_can_linear(struct panfrost_device *dev, const struct panfrost_resource *pres)
@@ -392,6 +394,53 @@ panfrost_can_linear(struct panfrost_device *dev, const struct panfrost_resource
                 (dev->quirks & (MIDGARD_SFBD | IS_BIFROST)));
 }
 
+static bool
+panfrost_should_afbc(struct panfrost_device *dev, const struct panfrost_resource *pres)
+{
+        /* AFBC resources may be rendered to, textured from, or shared across
+         * processes, but may not be used as e.g buffers */
+        const unsigned valid_binding =
+                PIPE_BIND_DEPTH_STENCIL |
+                PIPE_BIND_RENDER_TARGET |
+                PIPE_BIND_BLENDABLE |
+                PIPE_BIND_SAMPLER_VIEW |
+                PIPE_BIND_DISPLAY_TARGET |
+                PIPE_BIND_SCANOUT |
+                PIPE_BIND_SHARED;
+
+        if (pres->base.bind & ~valid_binding)
+                return false;
+
+        /* AFBC introduced with Mali T760 */
+        if (dev->quirks & MIDGARD_NO_AFBC)
+                return false;
+
+        /* AFBC<-->staging is expensive */
+        if (pres->base.usage == PIPE_USAGE_STREAM)
+                return false;
+
+        /* Only a small selection of formats are AFBC'able */
+        if (!panfrost_format_supports_afbc(pres->internal_format))
+                return false;
+
+        /* AFBC does not support layered (GLES3 style) multisampling. Use
+         * EXT_multisampled_render_to_texture instead */
+        if (pres->base.nr_samples > 1)
+                return false;
+
+        /* TODO: Is AFBC of 3D textures possible? */
+        if ((pres->base.target != PIPE_TEXTURE_2D) && (pres->base.target != PIPE_TEXTURE_RECT))
+                return false;
+
+        /* For one tile, AFBC is a loss compared to u-interleaved */
+        if (pres->base.width0 <= 16 && pres->base.height0 <= 16)
+                return false;
+
+        /* Otherwise, we'd prefer AFBC as it is dramatically more efficient
+         * than linear or usually even u-interleaved */
+        return true;
+}
+
 static bool
 panfrost_should_tile(struct panfrost_device *dev, const struct panfrost_resource *pres)
 {
@@ -400,7 +449,9 @@ panfrost_should_tile(struct panfrost_device *dev, const struct panfrost_resource
                 PIPE_BIND_RENDER_TARGET |
                 PIPE_BIND_BLENDABLE |
                 PIPE_BIND_SAMPLER_VIEW |
-                PIPE_BIND_DISPLAY_TARGET;
+                PIPE_BIND_DISPLAY_TARGET |
+                PIPE_BIND_SCANOUT |
+                PIPE_BIND_SHARED;
 
         unsigned bpp = util_format_get_blocksizebits(pres->internal_format);
 
@@ -425,7 +476,13 @@ static uint64_t
 panfrost_best_modifier(struct panfrost_device *dev,
                 const struct panfrost_resource *pres)
 {
-        if (panfrost_should_tile(dev, pres))
+        if (panfrost_should_afbc(dev, pres)) {
+                uint64_t afbc =
+                        AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+                        AFBC_FORMAT_MOD_SPARSE;
+
+                return DRM_FORMAT_MOD_ARM_AFBC(afbc);
+        } else if (panfrost_should_tile(dev, pres))
                 return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
         else
                 return DRM_FORMAT_MOD_LINEAR;
index c4b03a165aa4fc4294aa6be5999a4b18c0b29b44..4b88e83aabe8b42ad9f8ee788c953e738a92a213 100644 (file)
 /* Has some missing formats for typed loads */
 #define MIDGARD_MISSING_LOADS (1 << 9)
 
+/* Lack support for AFBC */
+#define MIDGARD_NO_AFBC (1 << 10)
+
 /* Quirk collections common to particular uarchs */
 
 #define MIDGARD_QUIRKS (MIDGARD_BROKEN_FP16 | HAS_SWIZZLES \
                 | MIDGARD_NO_TYPED_BLEND_STORES \
                 | MIDGARD_MISSING_LOADS)
 
-#define BIFROST_QUIRKS (IS_BIFROST | NO_BLEND_PACKS)
+/* TODO: AFBC on Bifrost */
+#define BIFROST_QUIRKS (IS_BIFROST | NO_BLEND_PACKS | MIDGARD_NO_AFBC)
 
 static inline unsigned
 panfrost_get_quirks(unsigned gpu_id)
@@ -84,10 +88,11 @@ panfrost_get_quirks(unsigned gpu_id)
         case 0x620:
                 return MIDGARD_QUIRKS | MIDGARD_SFBD
                         | MIDGARD_NO_TYPED_BLEND_LOADS
-                        | NO_BLEND_PACKS;
+                        | NO_BLEND_PACKS | MIDGARD_NO_AFBC;
 
         case 0x720:
-                return MIDGARD_QUIRKS | MIDGARD_SFBD | MIDGARD_NO_HIER_TILING;
+                return MIDGARD_QUIRKS | MIDGARD_SFBD | MIDGARD_NO_HIER_TILING
+                        | MIDGARD_NO_AFBC;
 
         case 0x820:
         case 0x830: