ail: Fix miptree offset generation for compressed textures
For compressed textures, the POT miptree starting size is calculated backwards (POT then minify instead of minify then POT). In addition, the existing POT miptree start level code does not work for compressed textures. Due to the extra block alignment requirement each step of the way, we can no longer get away with nice log-based O(1) math. Switch to a loop. This should be equivalent for uncompressed textures, but yields different results with compression (element size > 1x1). Signed-off-by: Asahi Lina <lina@asahilina.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26614>
This commit is contained in:
committed by
Alyssa Rosenzweig
parent
5382f57e81
commit
2221eb6cec
+25
-21
@@ -25,23 +25,6 @@ ail_initialize_linear(struct ail_layout *layout)
|
||||
layout->size_B = layout->layer_stride_B * layout->depth_px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the minimum integer l such that x 2^-l < y, where x is an integer
|
||||
* and y is a power-of-two.
|
||||
*/
|
||||
static unsigned
|
||||
ail_min_mip_below(unsigned x, unsigned y)
|
||||
{
|
||||
assert(util_is_power_of_two_nonzero(y));
|
||||
|
||||
if (x < y)
|
||||
return 0;
|
||||
else if (util_is_power_of_two_or_zero(x))
|
||||
return util_logbase2(x) - util_logbase2(y) + 1;
|
||||
else
|
||||
return util_logbase2_ceil(x) - util_logbase2(y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the maximum tile size possible for a given block size. This satisfy
|
||||
* width * height * blocksize = 16384 = page size, so each tile is one page.
|
||||
@@ -87,6 +70,9 @@ ail_initialize_twiddled(struct ail_layout *layout)
|
||||
unsigned blocksize_B = ail_get_block_size_B(layout);
|
||||
unsigned w_el = util_format_get_nblocksx(layout->format, layout->width_px);
|
||||
unsigned h_el = util_format_get_nblocksy(layout->format, layout->height_px);
|
||||
unsigned bw_px = util_format_get_blockwidth(layout->format);
|
||||
unsigned bh_px = util_format_get_blockheight(layout->format);
|
||||
bool compressed = util_format_is_compressed(layout->format);
|
||||
|
||||
/* Calculate the tile size used for the large miptree, and the dimensions of
|
||||
* level 0 given that tile size.
|
||||
@@ -100,8 +86,18 @@ ail_initialize_twiddled(struct ail_layout *layout)
|
||||
* power-of-two miptree is used when either the width or the height is
|
||||
* smaller than a single large tile.
|
||||
*/
|
||||
unsigned pot_level = MIN2(ail_min_mip_below(w_el, tilesize_el.width_el),
|
||||
ail_min_mip_below(h_el, tilesize_el.height_el));
|
||||
unsigned pot_level = 0;
|
||||
unsigned pot_w_px = bw_px * w_el;
|
||||
unsigned pot_h_px = bh_px * h_el;
|
||||
do {
|
||||
unsigned pot_w_el = util_format_get_nblocksx(layout->format, pot_w_px);
|
||||
unsigned pot_h_el = util_format_get_nblocksy(layout->format, pot_h_px);
|
||||
if (pot_w_el < tilesize_el.width_el || pot_h_el < tilesize_el.height_el)
|
||||
break;
|
||||
pot_w_px = u_minify(pot_w_px, 1);
|
||||
pot_h_px = u_minify(pot_h_px, 1);
|
||||
pot_level++;
|
||||
} while (1);
|
||||
|
||||
/* First allocate the large miptree. All tiles in the large miptree are of
|
||||
* size tilesize_el and have their dimensions given by stx/sty/sarea.
|
||||
@@ -134,8 +130,16 @@ ail_initialize_twiddled(struct ail_layout *layout)
|
||||
* images, where the round-down error of right-shifting could cause incorrect
|
||||
* tile size calculations.
|
||||
*/
|
||||
unsigned potw_el = util_next_power_of_two(u_minify(w_el, pot_level));
|
||||
unsigned poth_el = util_next_power_of_two(u_minify(h_el, pot_level));
|
||||
unsigned potw_el, poth_el;
|
||||
if (compressed) {
|
||||
/* Compressed formats round then minify instead of minifying then rounding
|
||||
*/
|
||||
potw_el = u_minify(util_next_power_of_two(w_el), pot_level);
|
||||
poth_el = u_minify(util_next_power_of_two(h_el), pot_level);
|
||||
} else {
|
||||
potw_el = util_next_power_of_two(u_minify(w_el, pot_level));
|
||||
poth_el = util_next_power_of_two(u_minify(h_el, pot_level));
|
||||
}
|
||||
|
||||
/* Finally we allocate the POT miptree, starting at level pot_level. Each
|
||||
* level uses the largest power-of-two tile that fits the level.
|
||||
|
||||
Reference in New Issue
Block a user