v3dv: Update texture padding logic to match v3d changes
authorLucas Fryzek <lfryzek@igalia.com>
Fri, 26 May 2023 18:52:54 +0000 (14:52 -0400)
committerMarge Bot <emma+marge@anholt.net>
Wed, 31 May 2023 05:27:08 +0000 (05:27 +0000)
Piglit tests for v3d highlighted issues with the padding
computation when allocating memory for slices. This change
moves the fixes from v3d to v3dv.

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

src/broadcom/vulkan/v3dv_image.c

index 8e9227d..5474d37 100644 (file)
@@ -70,6 +70,27 @@ v3d_get_ub_pad(uint32_t cpp, 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_plane_slices(struct v3dv_image *image, uint8_t plane,
                        uint32_t plane_offset)
@@ -82,15 +103,6 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
    uint32_t height = image->planes[plane].height;
    uint32_t depth = image->vk.extent.depth;
 
-   /* 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 utile_w = v3d_utile_width(image->planes[plane].cpp);
    uint32_t utile_h = v3d_utile_height(image->planes[plane].cpp);
    uint32_t uif_block_w = utile_w * 2;
@@ -99,6 +111,21 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
    uint32_t block_width = vk_format_get_blockwidth(image->vk.format);
    uint32_t block_height = vk_format_get_blockheight(image->vk.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);
+
    assert(image->vk.samples == VK_SAMPLE_COUNT_1_BIT ||
           image->vk.samples == VK_SAMPLE_COUNT_4_BIT);
    bool msaa = image->vk.samples != VK_SAMPLE_COUNT_1_BIT;
@@ -138,16 +165,6 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
       level_width = DIV_ROUND_UP(level_width, block_width);
       level_height = DIV_ROUND_UP(level_height, block_height);
 
-      /* Converting to the block size may have made it so the level_width
-       * and level height are no longer a POT for mip levels > 1, therefore
-       * if this is a mip level greater than 1 we set level_width and
-       * level_height to the next power of two
-       */
-      if (i > 1) {
-         level_width = util_next_power_of_two(level_width);
-         level_height = util_next_power_of_two(level_height);
-      }
-
       if (!image->tiled) {
          slice->tiling = V3D_TILING_RASTER;
          if (image->vk.image_type == VK_IMAGE_TYPE_1D)