Mesa (main): freedreno/fdl: Add fdl6_view

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Oct 18 16:38:35 UTC 2021


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

Author: Connor Abbott <cwabbott0 at gmail.com>
Date:   Wed Oct 13 17:34:26 2021 +0200

freedreno/fdl: Add fdl6_view

This is mostly based on tu_image_view. The notable difference is that we
don't handle choosing the correct plane out of multiple planes when
indicated by the aspect, which means that there is no equivalent of
VK_IMAGE_ASPECT_PLANE_1 etc. This is expected to be done in the driver,
and note that freedreno gallium handles this very differently anyway.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13359>

---

 src/freedreno/fdl/fd6_view.c         | 346 +++++++++++++++++++++++++++++++++++
 src/freedreno/fdl/freedreno_layout.h |  61 ++++++
 src/freedreno/fdl/meson.build        |   1 +
 3 files changed, 408 insertions(+)

diff --git a/src/freedreno/fdl/fd6_view.c b/src/freedreno/fdl/fd6_view.c
new file mode 100644
index 00000000000..5806b1682d4
--- /dev/null
+++ b/src/freedreno/fdl/fd6_view.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ * Copyright © 2021 Valve 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.
+ *
+ * Authors:
+ *    Rob Clark <robclark at freedesktop.org>
+ */
+
+#include "freedreno_layout.h"
+#include "fd6_format_table.h"
+
+static enum a6xx_tex_swiz
+fdl6_swiz(unsigned char swiz)
+{
+   STATIC_ASSERT((unsigned) A6XX_TEX_X == (unsigned) PIPE_SWIZZLE_X);
+   STATIC_ASSERT((unsigned) A6XX_TEX_Y == (unsigned) PIPE_SWIZZLE_Y);
+   STATIC_ASSERT((unsigned) A6XX_TEX_Z == (unsigned) PIPE_SWIZZLE_Z);
+   STATIC_ASSERT((unsigned) A6XX_TEX_W == (unsigned) PIPE_SWIZZLE_W);
+   STATIC_ASSERT((unsigned) A6XX_TEX_ZERO == (unsigned) PIPE_SWIZZLE_0);
+   STATIC_ASSERT((unsigned) A6XX_TEX_ONE == (unsigned) PIPE_SWIZZLE_1);
+   return (enum a6xx_tex_swiz) swiz;
+}
+
+static enum a6xx_tex_type
+fdl6_tex_type(enum fdl_view_type type, bool storage)
+{
+   STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_1D == (unsigned) A6XX_TEX_1D);
+   STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_2D == (unsigned) A6XX_TEX_2D);
+   STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_CUBE == (unsigned) A6XX_TEX_CUBE);
+   STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_3D == (unsigned) A6XX_TEX_3D);
+
+   return (storage && type == FDL_VIEW_TYPE_CUBE) ?
+      A6XX_TEX_2D : (enum a6xx_tex_type) type;
+}
+
+static uint32_t
+fdl6_texswiz(const struct fdl_view_args *args, bool has_z24uint_s8uint)
+{
+   unsigned char format_swiz[4] =
+      { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W };
+   switch (args->format) {
+   case PIPE_FORMAT_R8G8_R8B8_UNORM:
+   case PIPE_FORMAT_G8R8_B8R8_UNORM:
+   case PIPE_FORMAT_R8_G8B8_420_UNORM:
+   case PIPE_FORMAT_R8_G8_B8_420_UNORM:
+      format_swiz[0] = PIPE_SWIZZLE_Z;
+      format_swiz[1] = PIPE_SWIZZLE_X;
+      format_swiz[2] = PIPE_SWIZZLE_Y;
+      break;
+   case PIPE_FORMAT_DXT1_RGB:
+   case PIPE_FORMAT_DXT1_SRGB:
+      /* same hardware format is used for BC1_RGB / BC1_RGBA */
+      format_swiz[3] = PIPE_SWIZZLE_1;
+      break;
+   case PIPE_FORMAT_X24S8_UINT:
+      if (!has_z24uint_s8uint) {
+         /* using FMT6_8_8_8_8_UINT, so need to pick out the W channel and
+          * swizzle (0,0,1) in the rest (see "Conversion to RGBA").
+          */
+         format_swiz[0] = PIPE_SWIZZLE_W;
+         format_swiz[1] = PIPE_SWIZZLE_0;
+         format_swiz[2] = PIPE_SWIZZLE_0;
+         format_swiz[3] = PIPE_SWIZZLE_1;
+      } else {
+         /* using FMT6_Z24_UINT_S8_UINT, which is (d, s, 0, 1), so need to
+          * swizzle away the d.
+          */
+         format_swiz[0] = PIPE_SWIZZLE_Y;
+         format_swiz[1] = PIPE_SWIZZLE_0;
+      }
+      break;
+   default:
+      break;
+   }
+
+   unsigned char swiz[4];
+   util_format_compose_swizzles(format_swiz, args->swiz, swiz);
+
+   return A6XX_TEX_CONST_0_SWIZ_X(fdl6_swiz(swiz[0])) |
+          A6XX_TEX_CONST_0_SWIZ_Y(fdl6_swiz(swiz[1])) |
+          A6XX_TEX_CONST_0_SWIZ_Z(fdl6_swiz(swiz[2])) |
+          A6XX_TEX_CONST_0_SWIZ_W(fdl6_swiz(swiz[3]));
+}
+
+#define COND(bool, val) ((bool) ? (val) : 0)
+
+void
+fdl6_view_init(struct fdl6_view *view, const struct fdl_layout **layouts,
+               const struct fdl_view_args *args, bool has_z24uint_s8uint)
+{
+   const struct fdl_layout *layout = layouts[0];
+   uint32_t width = u_minify(layout->width0, args->base_miplevel);
+   uint32_t height = u_minify(layout->height0, args->base_miplevel);
+   uint32_t storage_depth = args->layer_count;
+   if (args->type == FDL_VIEW_TYPE_3D) {
+      storage_depth = u_minify(layout->depth0, args->base_miplevel);
+   }
+
+   uint32_t depth = storage_depth;
+   if (args->type == FDL_VIEW_TYPE_CUBE) {
+      /* Cubes are treated as 2D arrays for storage images, so only divide the
+       * depth by 6 for the texture descriptor.
+       */
+      depth /= 6;
+   }
+
+   uint64_t base_addr = args->iova +
+      fdl_surface_offset(layout, args->base_miplevel, args->base_array_layer);
+   uint64_t ubwc_addr = args->iova +
+      fdl_ubwc_offset(layout, args->base_miplevel, args->base_array_layer);
+
+   uint32_t pitch = fdl_pitch(layout, args->base_miplevel);
+   uint32_t ubwc_pitch = fdl_ubwc_pitch(layout, args->base_miplevel);
+   uint32_t layer_size = fdl_layer_stride(layout, args->base_miplevel);
+
+   enum a6xx_format texture_format =
+      fd6_texture_format(args->format, layout->tile_mode);
+   enum a3xx_color_swap swap =
+      fd6_texture_swap(args->format, layout->tile_mode);
+   enum a6xx_tile_mode tile_mode = fdl_tile_mode(layout, args->base_miplevel);
+
+   bool ubwc_enabled = fdl_ubwc_enabled(layout, args->base_miplevel);
+
+   bool is_d24s8 = (args->format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
+                    args->format == PIPE_FORMAT_Z24X8_UNORM ||
+                    args->format == PIPE_FORMAT_X24S8_UINT);
+
+   if (args->format == PIPE_FORMAT_X24S8_UINT && has_z24uint_s8uint)
+      texture_format = FMT6_Z24_UINT_S8_UINT;
+
+   if (texture_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 && !ubwc_enabled)
+      texture_format = FMT6_8_8_8_8_UNORM;
+
+   enum a6xx_format storage_format = texture_format;
+   if (is_d24s8) {
+      if (ubwc_enabled)
+         storage_format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+      else
+         storage_format = FMT6_8_8_8_8_UNORM;
+   }
+
+   memset(view->descriptor, 0, sizeof(view->descriptor));
+
+   view->descriptor[0] =
+      A6XX_TEX_CONST_0_TILE_MODE(tile_mode) |
+      COND(util_format_is_srgb(args->format), A6XX_TEX_CONST_0_SRGB) |
+      A6XX_TEX_CONST_0_FMT(texture_format) |
+      A6XX_TEX_CONST_0_SAMPLES(util_logbase2(layout->nr_samples)) |
+      A6XX_TEX_CONST_0_SWAP(swap) |
+      fdl6_texswiz(args, has_z24uint_s8uint) |
+      A6XX_TEX_CONST_0_MIPLVLS(args->level_count - 1);
+   view->descriptor[1] = A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height);
+   view->descriptor[2] =
+      A6XX_TEX_CONST_2_PITCHALIGN(layout->pitchalign - 6) |
+      A6XX_TEX_CONST_2_PITCH(pitch) |
+      A6XX_TEX_CONST_2_TYPE(fdl6_tex_type(args->type, false));
+   view->descriptor[3] = A6XX_TEX_CONST_3_ARRAY_PITCH(layer_size);
+   view->descriptor[4] = base_addr;
+   view->descriptor[5] = (base_addr >> 32) | A6XX_TEX_CONST_5_DEPTH(depth);
+
+   if (layout->tile_all)
+      view->descriptor[3] |= A6XX_TEX_CONST_3_TILE_ALL;
+
+   if (args->format == PIPE_FORMAT_R8_G8B8_420_UNORM ||
+       args->format == PIPE_FORMAT_R8_G8_B8_420_UNORM) {
+      /* chroma offset re-uses MIPLVLS bits */
+      assert(args->level_count == 1);
+      if (args->chroma_offsets[0] == FDL_CHROMA_LOCATION_MIDPOINT)
+         view->descriptor[0] |= A6XX_TEX_CONST_0_CHROMA_MIDPOINT_X;
+      if (args->chroma_offsets[1] == FDL_CHROMA_LOCATION_MIDPOINT)
+         view->descriptor[0] |= A6XX_TEX_CONST_0_CHROMA_MIDPOINT_Y;
+
+      uint64_t base_addr[3];
+
+      view->descriptor[3] |= A6XX_TEX_CONST_3_TILE_ALL;
+      if (ubwc_enabled) {
+         view->descriptor[3] |= A6XX_TEX_CONST_3_FLAG;
+         /* no separate ubwc base, image must have the expected layout */
+         for (uint32_t i = 0; i < 3; i++) {
+            base_addr[i] = args->iova +
+               fdl_ubwc_offset(layouts[i], args->base_miplevel, args->base_array_layer);
+         }
+      } else {
+         for (uint32_t i = 0; i < 3; i++) {
+            base_addr[i] = args->iova +
+               fdl_surface_offset(layouts[i], args->base_miplevel, args->base_array_layer);
+         }
+      }
+
+      view->descriptor[4] = base_addr[0];
+      view->descriptor[5] |= base_addr[0] >> 32;
+      view->descriptor[6] =
+         A6XX_TEX_CONST_6_PLANE_PITCH(fdl_pitch(layouts[1], args->base_miplevel));
+      view->descriptor[7] = base_addr[1];
+      view->descriptor[8] = base_addr[1] >> 32;
+      view->descriptor[9] = base_addr[2];
+      view->descriptor[10] = base_addr[2] >> 32;
+
+      assert(args->type != FDL_VIEW_TYPE_3D);
+      return;
+   }
+
+   if (ubwc_enabled) {
+      uint32_t block_width, block_height;
+      fdl6_get_ubwc_blockwidth(layout, &block_width, &block_height);
+
+      view->descriptor[3] |= A6XX_TEX_CONST_3_FLAG;
+      view->descriptor[7] = ubwc_addr;
+      view->descriptor[8] = ubwc_addr >> 32;
+      view->descriptor[9] |= A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
+      view->descriptor[10] |=
+         A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(ubwc_pitch) |
+         A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(width, block_width))) |
+         A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(height, block_height)));
+   }
+
+   if (args->type == FDL_VIEW_TYPE_3D) {
+      view->descriptor[3] |=
+         A6XX_TEX_CONST_3_MIN_LAYERSZ(layout->slices[layout->mip_levels - 1].size0);
+   }
+
+   bool samples_average =
+      layout->nr_samples > 1 &&
+      !util_format_is_pure_integer(args->format) &&
+      !util_format_is_depth_or_stencil(args->format);
+
+   view->SP_PS_2D_SRC_INFO =
+      A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(storage_format) |
+      A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(tile_mode) |
+      A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(swap) |
+      COND(ubwc_enabled, A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
+      COND(util_format_is_srgb(args->format), A6XX_SP_PS_2D_SRC_INFO_SRGB) |
+      A6XX_SP_PS_2D_SRC_INFO_SAMPLES(util_logbase2(layout->nr_samples)) |
+      COND(samples_average, A6XX_SP_PS_2D_SRC_INFO_SAMPLES_AVERAGE) |
+      A6XX_SP_PS_2D_SRC_INFO_UNK20 |
+      A6XX_SP_PS_2D_SRC_INFO_UNK22;
+
+   view->SP_PS_2D_SRC_SIZE =
+      A6XX_SP_PS_2D_SRC_SIZE_WIDTH(width) |
+      A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(height);
+
+   /* note: these have same encoding for MRT and 2D (except 2D PITCH src) */
+   view->PITCH = A6XX_RB_DEPTH_BUFFER_PITCH(pitch);
+   view->FLAG_BUFFER_PITCH =
+      A6XX_RB_DEPTH_FLAG_BUFFER_PITCH_PITCH(ubwc_pitch) |
+      A6XX_RB_DEPTH_FLAG_BUFFER_PITCH_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
+
+   view->base_addr = base_addr;
+   view->ubwc_addr = ubwc_addr;
+   view->layer_size = layer_size;
+   view->ubwc_layer_size = layout->ubwc_layer_size;
+
+   enum a6xx_format color_format =
+      fd6_color_format(args->format, layout->tile_mode);
+
+   /* Don't set fields that are only used for attachments/blit dest if COLOR
+    * is unsupported.
+    */
+   if (color_format == FMT6_NONE)
+      return;
+
+   enum a3xx_color_swap color_swap =
+      fd6_color_swap(args->format, layout->tile_mode);
+
+   if (is_d24s8)
+      color_format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+
+   if (color_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 && !ubwc_enabled)
+      color_format = FMT6_8_8_8_8_UNORM;
+
+   memset(view->storage_descriptor, 0, sizeof(view->storage_descriptor));
+
+   view->storage_descriptor[0] =
+      A6XX_IBO_0_FMT(storage_format) |
+      A6XX_IBO_0_TILE_MODE(tile_mode);
+   view->storage_descriptor[1] =
+      A6XX_IBO_1_WIDTH(width) |
+      A6XX_IBO_1_HEIGHT(height);
+   view->storage_descriptor[2] =
+      A6XX_IBO_2_PITCH(pitch) |
+      A6XX_IBO_2_TYPE(fdl6_tex_type(args->type, true));
+   view->storage_descriptor[3] = A6XX_IBO_3_ARRAY_PITCH(layer_size);
+
+   view->storage_descriptor[4] = base_addr;
+   view->storage_descriptor[5] = (base_addr >> 32) | A6XX_IBO_5_DEPTH(storage_depth);
+
+   if (ubwc_enabled) {
+      view->storage_descriptor[3] |= A6XX_IBO_3_FLAG | A6XX_IBO_3_UNK27;
+      view->storage_descriptor[7] |= ubwc_addr;
+      view->storage_descriptor[8] |= ubwc_addr >> 32;
+      view->storage_descriptor[9] = A6XX_IBO_9_FLAG_BUFFER_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
+      view->storage_descriptor[10] =
+         A6XX_IBO_10_FLAG_BUFFER_PITCH(ubwc_pitch);
+   }
+
+   view->width = width;
+   view->height = height;
+   view->need_y2_align =
+      tile_mode == TILE6_LINEAR && args->base_miplevel != layout->mip_levels - 1;
+
+   view->ubwc_enabled = ubwc_enabled;
+
+   view->RB_MRT_BUF_INFO =
+      A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
+      A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(color_format) |
+      A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(color_swap);
+
+   view->SP_FS_MRT_REG =
+      A6XX_SP_FS_MRT_REG_COLOR_FORMAT(color_format) |
+      COND(util_format_is_pure_sint(args->format), A6XX_SP_FS_MRT_REG_COLOR_SINT) |
+      COND(util_format_is_pure_uint(args->format), A6XX_SP_FS_MRT_REG_COLOR_UINT);
+
+   view->RB_2D_DST_INFO =
+      A6XX_RB_2D_DST_INFO_COLOR_FORMAT(color_format) |
+      A6XX_RB_2D_DST_INFO_TILE_MODE(tile_mode) |
+      A6XX_RB_2D_DST_INFO_COLOR_SWAP(color_swap) |
+      COND(ubwc_enabled, A6XX_RB_2D_DST_INFO_FLAGS) |
+      COND(util_format_is_srgb(args->format), A6XX_RB_2D_DST_INFO_SRGB);
+
+   view->RB_BLIT_DST_INFO =
+      A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
+      A6XX_RB_BLIT_DST_INFO_SAMPLES(util_logbase2(layout->nr_samples)) |
+      A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(color_format) |
+      A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(color_swap) |
+      COND(ubwc_enabled, A6XX_RB_BLIT_DST_INFO_FLAGS);
+}
diff --git a/src/freedreno/fdl/freedreno_layout.h b/src/freedreno/fdl/freedreno_layout.h
index 1c0221bb495..a53b9b97978 100644
--- a/src/freedreno/fdl/freedreno_layout.h
+++ b/src/freedreno/fdl/freedreno_layout.h
@@ -256,4 +256,65 @@ void fdl_dump_layout(struct fdl_layout *layout);
 void fdl6_get_ubwc_blockwidth(const struct fdl_layout *layout,
                               uint32_t *blockwidth, uint32_t *blockheight);
 
+enum fdl_view_type {
+   FDL_VIEW_TYPE_1D = 0,
+   FDL_VIEW_TYPE_2D = 1,
+   FDL_VIEW_TYPE_CUBE = 2,
+   FDL_VIEW_TYPE_3D = 3,
+};
+
+enum fdl_chroma_location {
+   FDL_CHROMA_LOCATION_COSITED_EVEN = 0,
+   FDL_CHROMA_LOCATION_MIDPOINT = 1,
+};
+
+struct fdl_view_args {
+   uint64_t iova;
+   uint32_t base_array_layer, base_miplevel;
+   uint32_t layer_count, level_count;
+   unsigned char swiz[4];
+   enum pipe_format format;
+   enum fdl_view_type type;
+   enum fdl_chroma_location chroma_offsets[2];
+};
+
+#define FDL6_TEX_CONST_DWORDS 16
+
+struct fdl6_view {
+   uint64_t base_addr;
+   uint64_t ubwc_addr;
+   uint32_t layer_size;
+   uint32_t ubwc_layer_size;
+
+   uint32_t width, height;
+   bool need_y2_align;
+
+   bool ubwc_enabled;
+
+   uint32_t descriptor[FDL6_TEX_CONST_DWORDS];
+
+   /* Descriptor for use as a storage image as opposed to a sampled image.
+    * This has a few differences for cube maps (e.g. type).
+    */
+   uint32_t storage_descriptor[FDL6_TEX_CONST_DWORDS];
+
+   /* pre-filled register values */
+   uint32_t PITCH;
+   uint32_t FLAG_BUFFER_PITCH;
+
+   uint32_t RB_MRT_BUF_INFO;
+   uint32_t SP_FS_MRT_REG;
+
+   uint32_t SP_PS_2D_SRC_INFO;
+   uint32_t SP_PS_2D_SRC_SIZE;
+
+   uint32_t RB_2D_DST_INFO;
+
+   uint32_t RB_BLIT_DST_INFO;
+};
+
+void
+fdl6_view_init(struct fdl6_view *view, const struct fdl_layout **layouts,
+               const struct fdl_view_args *args, bool has_z24uint_s8uint);
+
 #endif /* FREEDRENO_LAYOUT_H_ */
diff --git a/src/freedreno/fdl/meson.build b/src/freedreno/fdl/meson.build
index bc6c3322b23..479d3dcab16 100644
--- a/src/freedreno/fdl/meson.build
+++ b/src/freedreno/fdl/meson.build
@@ -24,6 +24,7 @@ libfreedreno_layout = static_library(
     'fd5_layout.c',
     'fd6_format_table.c',
     'fd6_layout.c',
+    'fd6_view.c',
     'freedreno_layout.c',
     freedreno_xml_header_files,
   ],



More information about the mesa-commit mailing list