freedreno/a6xx: Fix UBWC mipmap sizing.
authorEric Anholt <eric@anholt.net>
Wed, 6 May 2020 19:21:01 +0000 (12:21 -0700)
committerMarge Bot <eric+marge@anholt.net>
Wed, 13 May 2020 19:18:16 +0000 (19:18 +0000)
The HW requires a log2 width/height of the level 0 meta_* size in the
descriptors, making it pretty clear that UBWC mipmapping is all
power-of-two sized.  Fixes a bunch of failures in the upcoming unit UBWC
layout unit tests.

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

src/freedreno/fdl/fd6_layout.c
src/freedreno/fdl/fd6_layout_test.c

index 336ca673b606c8e94453079643279ea051c68f1a..7b544fb7c6fd672e97bdd370bf36f74bf7e0a89c 100644 (file)
@@ -131,19 +131,31 @@ fdl6_layout(struct fdl_layout *layout,
 
        uint32_t pitch0 = util_align_npot(width0, fdl6_pitchalign(layout, 0));
 
 
        uint32_t pitch0 = util_align_npot(width0, fdl6_pitchalign(layout, 0));
 
+       uint32_t ubwc_width0 = width0;
+       uint32_t ubwc_height0 = height0;
+       if (mip_levels > 1) {
+               /* With mipmapping enabled, UBWC layout is power-of-two sized,
+                * specified in log2 width/height in the descriptors.
+                */
+               ubwc_width0 = util_next_power_of_two(width0);
+               ubwc_height0 = util_next_power_of_two(height0);
+       }
+       ubwc_width0 = align(DIV_ROUND_UP(ubwc_width0, ta->ubwc_blockwidth),
+                       RGB_TILE_WIDTH_ALIGNMENT);
+       ubwc_height0 = align(DIV_ROUND_UP(ubwc_height0, ta->ubwc_blockheight),
+                       RGB_TILE_HEIGHT_ALIGNMENT);
+
        for (uint32_t level = 0; level < mip_levels; level++) {
                uint32_t depth = u_minify(depth0, level);
                struct fdl_slice *slice = &layout->slices[level];
                struct fdl_slice *ubwc_slice = &layout->ubwc_slices[level];
                uint32_t tile_mode = fdl_tile_mode(layout, level);
        for (uint32_t level = 0; level < mip_levels; level++) {
                uint32_t depth = u_minify(depth0, level);
                struct fdl_slice *slice = &layout->slices[level];
                struct fdl_slice *ubwc_slice = &layout->ubwc_slices[level];
                uint32_t tile_mode = fdl_tile_mode(layout, level);
-               uint32_t width, height;
+               uint32_t height;
 
                /* tiled levels of 3D textures are rounded up to PoT dimensions: */
                if (is_3d && tile_mode) {
 
                /* tiled levels of 3D textures are rounded up to PoT dimensions: */
                if (is_3d && tile_mode) {
-                       width = u_minify(util_next_power_of_two(width0), level);
                        height = u_minify(util_next_power_of_two(height0), level);
                } else {
                        height = u_minify(util_next_power_of_two(height0), level);
                } else {
-                       width = u_minify(width0, level);
                        height = u_minify(height0, level);
                }
 
                        height = u_minify(height0, level);
                }
 
@@ -192,20 +204,11 @@ fdl6_layout(struct fdl_layout *layout,
                        /* with UBWC every level is aligned to 4K */
                        layout->size = align(layout->size, 4096);
 
                        /* with UBWC every level is aligned to 4K */
                        layout->size = align(layout->size, 4096);
 
-                       uint32_t meta_pitch = align(DIV_ROUND_UP(width, ta->ubwc_blockwidth),
+                       uint32_t meta_pitch = align(u_minify(ubwc_width0, level),
                                        RGB_TILE_WIDTH_ALIGNMENT);
                                        RGB_TILE_WIDTH_ALIGNMENT);
-                       uint32_t meta_height = align(DIV_ROUND_UP(height, ta->ubwc_blockheight),
+                       uint32_t meta_height = align(u_minify(ubwc_height0, level),
                                        RGB_TILE_HEIGHT_ALIGNMENT);
 
                                        RGB_TILE_HEIGHT_ALIGNMENT);
 
-                       /* it looks like mipmaps need alignment to power of two
-                        * TODO: needs testing with large npot textures
-                        * (needed for the first level?)
-                        */
-                       if (mip_levels > 1) {
-                               meta_pitch = util_next_power_of_two(meta_pitch);
-                               meta_height = util_next_power_of_two(meta_height);
-                       }
-
                        ubwc_slice->size0 = align(meta_pitch * meta_height, UBWC_PLANE_SIZE_ALIGNMENT);
                        ubwc_slice->pitch = meta_pitch;
                        ubwc_slice->offset = layout->ubwc_layer_size;
                        ubwc_slice->size0 = align(meta_pitch * meta_height, UBWC_PLANE_SIZE_ALIGNMENT);
                        ubwc_slice->pitch = meta_pitch;
                        ubwc_slice->offset = layout->ubwc_layer_size;
index 45a973964f1001bb310150ad0db30853fbdca0cb..eac84b910550d8d9723391ab857519a61939fec4 100644 (file)
@@ -390,6 +390,84 @@ static const struct testcase testcases[] = {
                        },
                },
        },
                        },
                },
        },
+
+       /* UBWC: Pitch comes from POT-aligned level 0. */
+       /* Pitch fixed in this commit, but offsets broken.  Will be fixed in
+        * following commits.
+        */
+#if 0
+       {
+               .format = PIPE_FORMAT_R8G8B8A8_UNORM,
+               .layout = {
+                       .tile_mode = TILE6_3,
+                       .ubwc = true,
+                       .width0 = 2049, .height0 = 128,
+                       .slices = {
+                               { .offset = 0, .pitch = 8448 },
+                               { .offset = 1081344, .pitch = 4352 },
+                               { .offset = 1359872, .pitch = 2304 },
+                               { .offset = 1433600, .pitch = 1280 },
+                               { .offset = 1454080, .pitch = 768 },
+                               { .offset = 1466368, .pitch = 512 },
+                               { .offset = 1474560, .pitch = 256 },
+                               { .offset = 1478656, .pitch = 256 },
+                               { .offset = 1482752, .pitch = 256 },
+                               { .offset = 1486848, .pitch = 256 },
+                               { .offset = 1490944, .pitch = 256 },
+                               { .offset = 1495040, .pitch = 256 },
+                       },
+                       .ubwc_slices = {
+                               { .offset = 0, .pitch = 256 },
+                               { .offset = 16384, .pitch = 128 },
+                               { .offset = 24576, .pitch = 64 },
+                               { .offset = 28672, .pitch = 64 },
+                               { .offset = 32768, .pitch = 64 },
+                               { .offset = 36864, .pitch = 64 },
+                               { .offset = 40960, .pitch = 64 },
+                               { .offset = 45056, .pitch = 64 },
+                               { .offset = 49152, .pitch = 64 },
+                               { .offset = 53248, .pitch = 64 },
+                               { .offset = 57344, .pitch = 64 },
+                               { .offset = 61440, .pitch = 64 },
+                       },
+               },
+       },
+#endif
+       /* UBWC: Height comes from POT-aligned level 0. */
+       {
+               .format = PIPE_FORMAT_R8G8B8A8_UNORM,
+               .layout = {
+                       .tile_mode = TILE6_3,
+                       .ubwc = true,
+                       .width0 = 1024, .height0 = 1025,
+                       .slices = {
+                               { .offset = 0, .pitch = 4096 },
+                               { .offset = 4259840, .pitch = 2048 },
+                               { .offset = 5308416, .pitch = 1024 },
+                               { .offset = 5570560, .pitch = 512 },
+                               { .offset = 5636096, .pitch = 256 },
+                               { .offset = 5652480, .pitch = 256 },
+                               { .offset = 5660672, .pitch = 256 },
+                               { .offset = 5664768, .pitch = 256 },
+                               { .offset = 5668864, .pitch = 256 },
+                               { .offset = 5672960, .pitch = 256 },
+                               { .offset = 5677056, .pitch = 256 },
+                       },
+                       .ubwc_slices = {
+                               { .offset = 0, .pitch = 64 },
+                               { .offset = 32768, .pitch = 64 },
+                               { .offset = 49152, .pitch = 64 },
+                               { .offset = 57344, .pitch = 64 },
+                               { .offset = 61440, .pitch = 64 },
+                               { .offset = 65536, .pitch = 64 },
+                               { .offset = 69632, .pitch = 64 },
+                               { .offset = 73728, .pitch = 64 },
+                               { .offset = 77824, .pitch = 64 },
+                               { .offset = 81920, .pitch = 64 },
+                               { .offset = 86016, .pitch = 64 },
+                       },
+               },
+       },
 };
 
 static bool test_layout(const struct testcase *testcase)
 };
 
 static bool test_layout(const struct testcase *testcase)