Mesa (main): isl: Move some genxml surface state helpers into an include file

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Dec 7 01:54:50 UTC 2021


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

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Nov 11 00:19:25 2021 -0800

isl: Move some genxml surface state helpers into an include file

On XeHP, the XY_BLOCK_COPY_BLT command has a number of fields that
describe the layout of the surface, much like SURFACE_STATE does.

Several of them are encoded in such a similar manner that we really
would like to reuse the isl helpers for emitting those.  This commit
moves them into a new isl_genX_helpers.h file which I can include
from the BLORP code.  (The alternative would be to add XY_BLOCK_COPY_BLT
filling commands to isl, but that...seems more like a BLORP feature.)

Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14094>

---

 src/intel/isl/isl_genX_helpers.h  | 199 ++++++++++++++++++++++++++++++++++++++
 src/intel/isl/isl_surface_state.c | 170 +-------------------------------
 src/intel/isl/meson.build         |   1 +
 3 files changed, 204 insertions(+), 166 deletions(-)

diff --git a/src/intel/isl/isl_genX_helpers.h b/src/intel/isl/isl_genX_helpers.h
new file mode 100644
index 00000000000..feb69eaac2e
--- /dev/null
+++ b/src/intel/isl/isl_genX_helpers.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2016 Intel Corporation
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),
+ *  to deal in the Software without restriction, including without limitation
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *  and/or sell copies of the Software, and to permit persons to whom the
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice (including the next
+ *  paragraph) shall be included in all copies or substantial portions of the
+ *  Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ *  IN THE SOFTWARE.
+ */
+
+#ifndef ISL_SURFACE_STATE_H
+#define ISL_SURFACE_STATE_H
+
+#include <stdint.h>
+
+/**
+ * @file isl_surface_state.h
+ *
+ * ============================= GENXML CODE =============================
+ *              [This file is compiled once per generation.]
+ * =======================================================================
+ *
+ * Helpers for encoding SURFACE_STATE and XY_BLOCK_COPY_BLT commands.
+ */
+
+UNUSED static const uint8_t
+isl_encode_halign(uint8_t halign)
+{
+   switch (halign) {
+#if GFX_VERx10 >= 125
+   case  16: return HALIGN_16;
+   case  32: return HALIGN_32;
+   case  64: return HALIGN_64;
+   case 128: return HALIGN_128;
+#elif GFX_VER >= 8
+   case   4: return HALIGN_4;
+   case   8: return HALIGN_8;
+   case  16: return HALIGN_16;
+#elif GFX_VER >= 7
+   case   4: return HALIGN_4;
+   case   8: return HALIGN_8;
+#endif
+   default: unreachable("Invalid halign");
+   }
+}
+
+UNUSED static const uint8_t
+isl_encode_valign(uint8_t valign)
+{
+   switch (valign) {
+#if GFX_VER >= 8
+   case   4: return VALIGN_4;
+   case   8: return VALIGN_8;
+   case  16: return VALIGN_16;
+#elif GFX_VER >= 6
+   case   2: return VALIGN_2;
+   case   4: return VALIGN_4;
+#endif
+   default: unreachable("Invalid valign");
+   }
+}
+
+/**
+ * Get the horizontal and vertical alignment in the units expected by the
+ * hardware.  Note that this does NOT give you the actual hardware enum values
+ * but an index into the isl_encode_[hv]align arrays above.
+ */
+UNUSED static struct isl_extent3d
+isl_get_image_alignment(const struct isl_surf *surf)
+{
+   if (GFX_VERx10 >= 125) {
+      if (surf->tiling == ISL_TILING_64) {
+         /* The hardware ignores the alignment values. Anyway, the surface's
+          * true alignment is likely outside the enum range of HALIGN* and
+          * VALIGN*.
+          */
+         return isl_extent3d(128, 4, 1);
+      } else if (isl_format_get_layout(surf->format)->bpb % 3 == 0) {
+         /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
+          * units of elements for 24, 48, and 96 bpb formats.
+          */
+         return isl_surf_get_image_alignment_el(surf);
+      } else {
+         /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
+          * units of bytes for formats that are powers of two.
+          */
+         const uint32_t bs = isl_format_get_layout(surf->format)->bpb / 8;
+         return isl_extent3d(surf->image_alignment_el.w * bs,
+                             surf->image_alignment_el.h,
+                             surf->image_alignment_el.d);
+      }
+   } else if (GFX_VER >= 9) {
+      if (isl_tiling_is_std_y(surf->tiling) ||
+          surf->dim_layout == ISL_DIM_LAYOUT_GFX9_1D) {
+         /* The hardware ignores the alignment values. Anyway, the surface's
+          * true alignment is likely outside the enum range of HALIGN* and
+          * VALIGN*.
+          */
+         return isl_extent3d(4, 4, 1);
+      } else {
+         /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
+          * of surface elements (not pixels nor samples). For compressed formats,
+          * a "surface element" is defined as a compression block.  For example,
+          * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
+          * format (ETC2 has a block height of 4), then the vertical alignment is
+          * 4 compression blocks or, equivalently, 16 pixels.
+          */
+         return isl_surf_get_image_alignment_el(surf);
+      }
+   } else {
+      /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
+       * units of surface samples.  For example, if SurfaceVerticalAlignment
+       * is VALIGN_4 and the surface is singlesampled, then for any surface
+       * format (compressed or not) the vertical alignment is
+       * 4 pixels.
+       */
+      return isl_surf_get_image_alignment_sa(surf);
+   }
+}
+
+UNUSED static uint32_t
+isl_get_qpitch(const struct isl_surf *surf)
+{
+   switch (surf->dim_layout) {
+   default:
+      unreachable("Bad isl_surf_dim");
+   case ISL_DIM_LAYOUT_GFX4_2D:
+      if (GFX_VER >= 9) {
+         if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) {
+            /* This is rather annoying and completely undocumented.  It
+             * appears that the hardware has a bug (or undocumented feature)
+             * regarding stencil buffers most likely related to the way
+             * W-tiling is handled as modified Y-tiling.  If you bind a 3-D
+             * stencil buffer normally, and use texelFetch on it, the z or
+             * array index will get implicitly multiplied by 2 for no obvious
+             * reason.  The fix appears to be to divide qpitch by 2 for
+             * W-tiled surfaces.
+             */
+            return isl_surf_get_array_pitch_el_rows(surf) / 2;
+         } else {
+            return isl_surf_get_array_pitch_el_rows(surf);
+         }
+      } else {
+         /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch
+          *
+          *    "This field must be set to an integer multiple of the Surface
+          *    Vertical Alignment. For compressed textures (BC*, FXT1,
+          *    ETC*, and EAC* Surface Formats), this field is in units of
+          *    rows in the uncompressed surface, and must be set to an
+          *    integer multiple of the vertical alignment parameter "j"
+          *    defined in the Common Surface Formats section."
+          */
+         return isl_surf_get_array_pitch_sa_rows(surf);
+      }
+   case ISL_DIM_LAYOUT_GFX9_1D:
+      /* QPitch is usually expressed as rows of surface elements (where
+       * a surface element is an compression block or a single surface
+       * sample). Skylake 1D is an outlier.
+       *
+       * From the Skylake BSpec >> Memory Views >> Common Surface
+       * Formats >> Surface Layout and Tiling >> 1D Surfaces:
+       *
+       *    Surface QPitch specifies the distance in pixels between array
+       *    slices.
+       */
+      return isl_surf_get_array_pitch_el(surf);
+   case ISL_DIM_LAYOUT_GFX4_3D:
+      /* QPitch doesn't make sense for ISL_DIM_LAYOUT_GFX4_3D since it uses a
+       * different pitch at each LOD.  Also, the QPitch field is ignored for
+       * these surfaces.  From the Broadwell PRM documentation for QPitch:
+       *
+       *    This field specifies the distance in rows between array slices. It
+       *    is used only in the following cases:
+       *     - Surface Array is enabled OR
+       *     - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled
+       *       Surface Storage Format set to MSFMT_MSS OR
+       *     - Surface Type is SURFTYPE_CUBE
+       *
+       * None of the three conditions above can possibly apply to a 3D surface
+       * so it is safe to just set QPitch to 0.
+       */
+      return 0;
+   }
+}
+
+#endif
diff --git a/src/intel/isl/isl_surface_state.c b/src/intel/isl/isl_surface_state.c
index fcfb4c5cf87..78b460d4f86 100644
--- a/src/intel/isl/isl_surface_state.c
+++ b/src/intel/isl/isl_surface_state.c
@@ -38,45 +38,7 @@ __gen_combine_address(__attribute__((unused)) void *data,
 #include "genxml/genX_pack.h"
 
 #include "isl_priv.h"
-
-#if GFX_VER >= 7
-static const uint8_t isl_encode_halign(uint8_t halign)
-{
-   switch (halign) {
-#if GFX_VERx10 >= 125
-   case  16: return HALIGN_16;
-   case  32: return HALIGN_32;
-   case  64: return HALIGN_64;
-   case 128: return HALIGN_128;
-#elif GFX_VER >= 8
-   case   4: return HALIGN_4;
-   case   8: return HALIGN_8;
-   case  16: return HALIGN_16;
-#else
-   case   4: return HALIGN_4;
-   case   8: return HALIGN_8;
-#endif
-   default: unreachable("Invalid halign");
-   }
-}
-#endif
-
-#if GFX_VER >= 6
-static const uint8_t isl_encode_valign(uint8_t valign)
-{
-   switch (valign) {
-#if GFX_VER >= 8
-   case   4: return VALIGN_4;
-   case   8: return VALIGN_8;
-   case  16: return VALIGN_16;
-#else
-   case   2: return VALIGN_2;
-   case   4: return VALIGN_4;
-#endif
-   default: unreachable("Invalid valign");
-   }
-}
-#endif
+#include "isl_genX_helpers.h"
 
 #if GFX_VER >= 8
 static const uint8_t isl_encode_tiling[] = {
@@ -158,131 +120,6 @@ get_surftype(enum isl_surf_dim dim, isl_surf_usage_flags_t usage)
    }
 }
 
-/**
- * Get the horizontal and vertical alignment in the units expected by the
- * hardware.  Note that this does NOT give you the actual hardware enum values
- * but an index into the isl_encode_[hv]align arrays above.
- */
-UNUSED static struct isl_extent3d
-get_image_alignment(const struct isl_surf *surf)
-{
-   if (GFX_VERx10 >= 125) {
-      if (surf->tiling == ISL_TILING_64) {
-         /* The hardware ignores the alignment values. Anyway, the surface's
-          * true alignment is likely outside the enum range of HALIGN* and
-          * VALIGN*.
-          */
-         return isl_extent3d(128, 4, 1);
-      } else if (isl_format_get_layout(surf->format)->bpb % 3 == 0) {
-         /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
-          * units of elements for 24, 48, and 96 bpb formats.
-          */
-         return isl_surf_get_image_alignment_el(surf);
-      } else {
-         /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
-          * units of bytes for formats that are powers of two.
-          */
-         const uint32_t bs = isl_format_get_layout(surf->format)->bpb / 8;
-         return isl_extent3d(surf->image_alignment_el.w * bs,
-                             surf->image_alignment_el.h,
-                             surf->image_alignment_el.d);
-      }
-   } else if (GFX_VER >= 9) {
-      if (isl_tiling_is_std_y(surf->tiling) ||
-          surf->dim_layout == ISL_DIM_LAYOUT_GFX9_1D) {
-         /* The hardware ignores the alignment values. Anyway, the surface's
-          * true alignment is likely outside the enum range of HALIGN* and
-          * VALIGN*.
-          */
-         return isl_extent3d(4, 4, 1);
-      } else {
-         /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
-          * of surface elements (not pixels nor samples). For compressed formats,
-          * a "surface element" is defined as a compression block.  For example,
-          * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
-          * format (ETC2 has a block height of 4), then the vertical alignment is
-          * 4 compression blocks or, equivalently, 16 pixels.
-          */
-         return isl_surf_get_image_alignment_el(surf);
-      }
-   } else {
-      /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
-       * units of surface samples.  For example, if SurfaceVerticalAlignment
-       * is VALIGN_4 and the surface is singlesampled, then for any surface
-       * format (compressed or not) the vertical alignment is
-       * 4 pixels.
-       */
-      return isl_surf_get_image_alignment_sa(surf);
-   }
-}
-
-#if GFX_VER >= 8
-static uint32_t
-get_qpitch(const struct isl_surf *surf)
-{
-   switch (surf->dim_layout) {
-   default:
-      unreachable("Bad isl_surf_dim");
-   case ISL_DIM_LAYOUT_GFX4_2D:
-      if (GFX_VER >= 9) {
-         if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) {
-            /* This is rather annoying and completely undocumented.  It
-             * appears that the hardware has a bug (or undocumented feature)
-             * regarding stencil buffers most likely related to the way
-             * W-tiling is handled as modified Y-tiling.  If you bind a 3-D
-             * stencil buffer normally, and use texelFetch on it, the z or
-             * array index will get implicitly multiplied by 2 for no obvious
-             * reason.  The fix appears to be to divide qpitch by 2 for
-             * W-tiled surfaces.
-             */
-            return isl_surf_get_array_pitch_el_rows(surf) / 2;
-         } else {
-            return isl_surf_get_array_pitch_el_rows(surf);
-         }
-      } else {
-         /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch
-          *
-          *    "This field must be set to an integer multiple of the Surface
-          *    Vertical Alignment. For compressed textures (BC*, FXT1,
-          *    ETC*, and EAC* Surface Formats), this field is in units of
-          *    rows in the uncompressed surface, and must be set to an
-          *    integer multiple of the vertical alignment parameter "j"
-          *    defined in the Common Surface Formats section."
-          */
-         return isl_surf_get_array_pitch_sa_rows(surf);
-      }
-   case ISL_DIM_LAYOUT_GFX9_1D:
-      /* QPitch is usually expressed as rows of surface elements (where
-       * a surface element is an compression block or a single surface
-       * sample). Skylake 1D is an outlier.
-       *
-       * From the Skylake BSpec >> Memory Views >> Common Surface
-       * Formats >> Surface Layout and Tiling >> 1D Surfaces:
-       *
-       *    Surface QPitch specifies the distance in pixels between array
-       *    slices.
-       */
-      return isl_surf_get_array_pitch_el(surf);
-   case ISL_DIM_LAYOUT_GFX4_3D:
-      /* QPitch doesn't make sense for ISL_DIM_LAYOUT_GFX4_3D since it uses a
-       * different pitch at each LOD.  Also, the QPitch field is ignored for
-       * these surfaces.  From the Broadwell PRM documentation for QPitch:
-       *
-       *    This field specifies the distance in rows between array slices. It
-       *    is used only in the following cases:
-       *     - Surface Array is enabled OR
-       *     - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled
-       *       Surface Storage Format set to MSFMT_MSS OR
-       *     - Surface Type is SURFTYPE_CUBE
-       *
-       * None of the three conditions above can possibly apply to a 3D surface
-       * so it is safe to just set QPitch to 0.
-       */
-      return 0;
-   }
-}
-#endif /* GFX_VER >= 8 */
-
 void
 isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state,
                             const struct isl_surf_fill_state_info *restrict info)
@@ -509,7 +346,8 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state,
 #endif
 
 #if GFX_VER >= 6
-   const struct isl_extent3d image_align = get_image_alignment(info->surf);
+   const struct isl_extent3d image_align =
+      isl_get_image_alignment(info->surf);
    s.SurfaceVerticalAlignment = isl_encode_valign(image_align.height);
 #if GFX_VER >= 7
    s.SurfaceHorizontalAlignment = isl_encode_halign(image_align.width);
@@ -524,7 +362,7 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state,
    }
 
 #if GFX_VER >= 8
-   s.SurfaceQPitch = get_qpitch(info->surf) >> 2;
+   s.SurfaceQPitch = isl_get_qpitch(info->surf) >> 2;
 #elif GFX_VER == 7
    s.SurfaceArraySpacing = info->surf->array_pitch_span ==
                            ISL_ARRAY_PITCH_SPAN_COMPACT;
diff --git a/src/intel/isl/meson.build b/src/intel/isl/meson.build
index b91d8fe4ac1..891360fdd6d 100644
--- a/src/intel/isl/meson.build
+++ b/src/intel/isl/meson.build
@@ -21,6 +21,7 @@
 isl_per_hw_ver_files = files(
   'isl_emit_depth_stencil.c',
   'isl_surface_state.c',
+  'isl_genX_helpers.h',
 )
 
 isl_gfx4_files = files(



More information about the mesa-commit mailing list