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