v3d: Add support for ASTC texture compression
authorLucas Fryzek <lfryzek@igalia.com>
Fri, 26 May 2023 15:41:52 +0000 (11:41 -0400)
committerMarge Bot <emma+marge@anholt.net>
Wed, 31 May 2023 05:27:08 +0000 (05:27 +0000)
Add proper support for ASTC texture compression in the v3d
gallium driver, instead of relying on the fallback software
conversion from gallium, as the hardware has native support
for ASTC compressed textures.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23260>

src/gallium/drivers/v3d/v3d_resource.c
src/gallium/drivers/v3d/v3dx_format_table.c

index b93336a..b7298f5 100644 (file)
@@ -526,6 +526,27 @@ v3d_get_ub_pad(struct v3d_resource *rsc, uint32_t height)
         return 0;
 }
 
+/**
+ * Computes the dimension with required padding for mip levels.
+ *
+ * This padding is required for width and height dimensions when the mip
+ * level is greater than 1, and for the depth dimension when the mip level
+ * is greater than 0. This function expects to be passed a mip level >= 1.
+ *
+ * Note: Hardware documentation seems to suggest that the third argument
+ * should be the utile dimensions, but through testing it was found that
+ * the block dimension should be used instead.
+ */
+static uint32_t
+v3d_get_dimension_mpad(uint32_t dimension, uint32_t level, uint32_t block_dimension)
+{
+        assert(level >= 1);
+        uint32_t pot_dim = u_minify(dimension, 1);
+        pot_dim = util_next_power_of_two(DIV_ROUND_UP(pot_dim, block_dimension));
+        uint32_t padded_dim = block_dimension * pot_dim;
+        return u_minify(padded_dim, level - 1);
+}
+
 static void
 v3d_setup_slices(struct v3d_resource *rsc, uint32_t winsys_stride,
                  bool uif_top)
@@ -534,14 +555,6 @@ v3d_setup_slices(struct v3d_resource *rsc, uint32_t winsys_stride,
         uint32_t width = prsc->width0;
         uint32_t height = prsc->height0;
         uint32_t depth = prsc->depth0;
-        /* Note that power-of-two padding is based on level 1.  These are not
-         * equivalent to just util_next_power_of_two(dimension), because at a
-         * level 0 dimension of 9, the level 1 power-of-two padded value is 4,
-         * not 8.
-         */
-        uint32_t pot_width = 2 * util_next_power_of_two(u_minify(width, 1));
-        uint32_t pot_height = 2 * util_next_power_of_two(u_minify(height, 1));
-        uint32_t pot_depth = 2 * util_next_power_of_two(u_minify(depth, 1));
         uint32_t offset = 0;
         uint32_t utile_w = v3d_utile_width(rsc->cpp);
         uint32_t utile_h = v3d_utile_height(rsc->cpp);
@@ -549,6 +562,21 @@ v3d_setup_slices(struct v3d_resource *rsc, uint32_t winsys_stride,
         uint32_t uif_block_h = utile_h * 2;
         uint32_t block_width = util_format_get_blockwidth(prsc->format);
         uint32_t block_height = util_format_get_blockheight(prsc->format);
+
+        /* Note that power-of-two padding is based on level 1.  These are not
+         * equivalent to just util_next_power_of_two(dimension), because at a
+         * level 0 dimension of 9, the level 1 power-of-two padded value is 4,
+         * not 8. Additionally the pot padding is based on the block size.
+         */
+        uint32_t pot_width = 2 * v3d_get_dimension_mpad(width,
+                                                        1,
+                                                        block_width);
+        uint32_t pot_height = 2 * v3d_get_dimension_mpad(height,
+                                                         1,
+                                                         block_height);
+        uint32_t pot_depth = 2 * v3d_get_dimension_mpad(depth,
+                                                        1,
+                                                        1);
         bool msaa = prsc->nr_samples > 1;
 
         /* MSAA textures/renderbuffers are always laid out as single-level
index 9920aa8..78f6d95 100644 (file)
@@ -185,6 +185,36 @@ static const struct v3d_format format_table[] = {
         FORMAT(DXT3_SRGBA,        NO,           BC2,         SWIZ_XYZW, 16, 0),
         FORMAT(DXT5_RGBA,         NO,           BC3,         SWIZ_XYZW, 16, 0),
         FORMAT(DXT5_SRGBA,        NO,           BC3,         SWIZ_XYZW, 16, 0),
+
+        /* Compressed: ASTC */
+        FORMAT(ASTC_4x4,          NO,           ASTC_4X4,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_4x4_SRGB,     NO,           ASTC_4X4,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_5x4,          NO,           ASTC_5X4,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_5x4_SRGB,     NO,           ASTC_5X4,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_5x5,          NO,           ASTC_5X5,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_5x5_SRGB,     NO,           ASTC_5X5,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_6x5,          NO,           ASTC_6X5,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_6x5_SRGB,     NO,           ASTC_6X5,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_6x6,          NO,           ASTC_6X6,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_6x6_SRGB,     NO,           ASTC_6X6,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_8x5,          NO,           ASTC_8X5,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_8x5_SRGB,     NO,           ASTC_8X5,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_8x6,          NO,           ASTC_8X6,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_8x6_SRGB,     NO,           ASTC_8X6,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_8x8,          NO,           ASTC_8X8,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_8x8_SRGB,     NO,           ASTC_8X8,    SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x5,         NO,           ASTC_10X5,   SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x5_SRGB,    NO,           ASTC_10X5,   SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x6,         NO,           ASTC_10X6,   SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x6_SRGB,    NO,           ASTC_10X6,   SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x8,         NO,           ASTC_10X8,   SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x8_SRGB,    NO,           ASTC_10X8,   SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x10,        NO,           ASTC_10X10,  SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_10x10_SRGB,   NO,           ASTC_10X10,  SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_12x10,        NO,           ASTC_12X10,  SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_12x10_SRGB,   NO,           ASTC_12X10,  SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_12x12,        NO,           ASTC_12X12,  SWIZ_XYZW, 16, 1),
+        FORMAT(ASTC_12x12_SRGB,   NO,           ASTC_12X12,  SWIZ_XYZW, 16, 1),
 };
 
 const struct v3d_format *