From 81f21ff4ef8b5ffb770d0ff3516338ffdfce3e99 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 May 2020 12:21:01 -0700 Subject: [PATCH] freedreno/a6xx: Fix UBWC mipmap sizing. 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: --- src/freedreno/fdl/fd6_layout.c | 31 ++++++------ src/freedreno/fdl/fd6_layout_test.c | 78 +++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 14 deletions(-) diff --git a/src/freedreno/fdl/fd6_layout.c b/src/freedreno/fdl/fd6_layout.c index 336ca673b60..7b544fb7c6f 100644 --- a/src/freedreno/fdl/fd6_layout.c +++ b/src/freedreno/fdl/fd6_layout.c @@ -131,19 +131,31 @@ fdl6_layout(struct fdl_layout *layout, 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); - uint32_t width, height; + uint32_t height; /* 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 { - width = u_minify(width0, 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); - 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); - 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); - /* 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; diff --git a/src/freedreno/fdl/fd6_layout_test.c b/src/freedreno/fdl/fd6_layout_test.c index 45a973964f1..eac84b91055 100644 --- a/src/freedreno/fdl/fd6_layout_test.c +++ b/src/freedreno/fdl/fd6_layout_test.c @@ -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)