Module: Mesa
Branch: main
Commit: 0e15d5af81bba7c1e798cf10fc838988c86daafd
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=0e15d5af81bba7c1e798cf10fc838988c86daafd

Author: Daniel Stone <[email protected]>
Date:   Fri Aug 27 16:52:31 2021 +0100

fdno/resource: Rewrite layout selection for allocation

The previous code had a number of errors, the most glaring of which was
forcing linear when it was one of the possible layouts requested.

When modifiers are being used, a list of _acceptable_ modifiers is
supplied; it's up to the driver to then make a decision as to which it
thinks is most optimal.

Normally we would select between linear/tiled/UBWC in ascending order of
preference according to what's possible, however we can't use a tiled
layout with explicit modifiers as there is no modifier token defined for
it.

Rewrite the layout-selection mechanism to always try to do the most
optimal thing. If the use flags force us to, or we have a shared
resource without explicit modifiers, we use linear. Failing that, we use
UBWC wherever possible; if this is not possible, we use tiled for
internal resources only or linear for shared resources.

v2 (Rob): respect FD_FORMAT_MOD_QCOM_TILED; do not print perf warning on
user choice of disabling UBWC;

v3: fix several issues breaking CI tests: revert removal of using
MOD_INVALID in various places, and assume implicit modifiers if present;
do not attempt to set UBWC flags when screen->tile_mode(prsc) falls back
to LINEAR (e.g. for small mip-maps levels); use TILED for implicit
modifier case with non-shared resources

v4: fix unintended demotion of UBWC, i.e. only check QCOM_COMPRESSED
modifier and demote UBWC to less optimal format when using explicit
modifiers

Signed-off-by: Daniel Stone <[email protected]>
Tested-by: Heinrich Fink <[email protected]>
Signed-off-by: Heinrich Fink <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12595>

---

 src/gallium/drivers/freedreno/freedreno_resource.c | 138 +++++++++++++--------
 1 file changed, 89 insertions(+), 49 deletions(-)

diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c 
b/src/gallium/drivers/freedreno/freedreno_resource.c
index 9c90055038f..cc4d15f5d60 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -1118,6 +1118,87 @@ alloc_resource_struct(struct pipe_screen *pscreen,
    return rsc;
 }
 
+enum fd_layout_type {
+   ERROR,
+   LINEAR,
+   TILED,
+   UBWC,
+};
+
+static enum fd_layout_type
+get_best_layout(struct fd_screen *screen, struct pipe_resource *prsc,
+                const struct pipe_resource *tmpl, const uint64_t *modifiers,
+                int count)
+{
+   bool implicit_modifiers =
+      (count == 0 ||
+       drm_find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count));
+
+   /* First, find all the conditions which would force us to linear */
+   if (!screen->tile_mode)
+      return LINEAR;
+
+   if (!screen->tile_mode(prsc))
+      return LINEAR;
+
+   if (tmpl->target == PIPE_BUFFER)
+      return LINEAR;
+
+   if (tmpl->bind & PIPE_BIND_LINEAR) {
+      if (tmpl->usage != PIPE_USAGE_STAGING)
+         perf_debug("%" PRSC_FMT ": forcing linear: bind flags",
+                    PRSC_ARGS(prsc));
+      return LINEAR;
+   }
+
+   if (FD_DBG(NOTILE))
+       return LINEAR;
+
+   /* Shared resources with implicit modifiers must always be linear */
+   if (implicit_modifiers && (tmpl->bind & PIPE_BIND_SHARED)) {
+      perf_debug("%" PRSC_FMT
+                 ": forcing linear: shared resource + implicit modifiers",
+                 PRSC_ARGS(prsc));
+      return LINEAR;
+   }
+
+   bool ubwc_ok = is_a6xx(screen);
+   if (FD_DBG(NOUBWC))
+      ubwc_ok = false;
+
+   if (ubwc_ok && !implicit_modifiers &&
+       !drm_find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, count)) {
+      perf_debug("%" PRSC_FMT
+                 ": not using UBWC: not in acceptable modifier set",
+                 PRSC_ARGS(prsc));
+      ubwc_ok = false;
+   }
+
+   if (ubwc_ok)
+      return UBWC;
+
+   /* We can't use tiled with explicit modifiers, as there is no modifier token
+    * defined for it. But we might internally force tiled allocation using a
+    * private modifier token.
+    *
+    * TODO we should probably also limit TILED in a similar way to UBWC above,
+    * once we have a public modifier token defined.
+    */
+   if (implicit_modifiers ||
+       drm_find_modifier(FD_FORMAT_MOD_QCOM_TILED, modifiers, count))
+      return TILED;
+
+   if (!drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count)) {
+      perf_debug("%" PRSC_FMT ": need linear but not in modifier set",
+                 PRSC_ARGS(prsc));
+      return ERROR;
+   }
+
+   perf_debug("%" PRSC_FMT ": not using tiling: explicit modifiers and no 
UBWC",
+              PRSC_ARGS(prsc));
+   return LINEAR;
+}
+
 /**
  * Helper that allocates a resource and resolves its layout (but doesn't
  * allocate its bo).
@@ -1150,61 +1231,20 @@ fd_resource_allocate_and_resolve(struct pipe_screen 
*pscreen,
 
    fd_resource_layout_init(prsc);
 
-#define LINEAR (PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR | 
PIPE_BIND_DISPLAY_TARGET)
-
-   bool linear = drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count);
-   if (linear) {
-      perf_debug("%" PRSC_FMT ": linear: DRM_FORMAT_MOD_LINEAR requested!",
-                 PRSC_ARGS(prsc));
-   } else if (tmpl->bind & LINEAR) {
-      if (tmpl->usage != PIPE_USAGE_STAGING)
-         perf_debug("%" PRSC_FMT ": linear: LINEAR bind requested!",
-                    PRSC_ARGS(prsc));
-      linear = true;
-   }
-
-   if (FD_DBG(NOTILE))
-      linear = true;
-
-   /* Normally, for non-shared buffers, allow buffer compression if
-    * not shared, otherwise only allow if QCOM_COMPRESSED modifier
-    * is requested:
-    *
-    * TODO we should probably also limit tiled in a similar way,
-    * except we don't have a format modifier for tiled.  (We probably
-    * should.)
-    */
-   bool allow_ubwc = false;
-   if (!linear) {
-      allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count);
-      if (!allow_ubwc) {
-         perf_debug("%" PRSC_FMT
-                    ": not UBWC: DRM_FORMAT_MOD_INVALID not requested!",
-                    PRSC_ARGS(prsc));
-      }
-      if (tmpl->bind & PIPE_BIND_SHARED) {
-         allow_ubwc =
-            drm_find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, 
count);
-         if (!allow_ubwc) {
-            perf_debug("%" PRSC_FMT
-                       ": not UBWC: shared and DRM_FORMAT_MOD_QCOM_COMPRESSED "
-                       "not requested!",
-                       PRSC_ARGS(prsc));
-            linear = true;
-         }
-      }
+   enum fd_layout_type layout =
+      get_best_layout(screen, prsc, tmpl, modifiers, count);
+   if (layout == ERROR) {
+      free(prsc);
+      return NULL;
    }
 
-   allow_ubwc &= !FD_DBG(NOUBWC);
-
-   if (screen->tile_mode && (tmpl->target != PIPE_BUFFER) && !linear) {
+   if (layout >= TILED)
       rsc->layout.tile_mode = screen->tile_mode(prsc);
-   }
+   if (layout == UBWC)
+      rsc->layout.ubwc = true;
 
    rsc->internal_format = format;
 
-   rsc->layout.ubwc = rsc->layout.tile_mode && is_a6xx(screen) && allow_ubwc;
-
    if (prsc->target == PIPE_BUFFER) {
       assert(prsc->format == PIPE_FORMAT_R8_UNORM);
       size = prsc->width0;

Reply via email to