Merge branch 'perf/shrink-miptrees' into 'main'

intel/isl: Omit unused space when sizing mipmaps

See merge request mesa/mesa!39593
This commit is contained in:
Nanley Chery 2026-03-11 06:38:17 +00:00
commit 01ece261a8

View file

@ -3161,13 +3161,13 @@ isl_calc_row_pitch(const struct isl_device *dev,
}
static bool
isl_calc_size(const struct isl_device *dev,
const struct isl_surf_init_info *info,
const struct isl_tile_info *tile_info,
const struct isl_extent4d *phys_total_el,
uint32_t array_pitch_el_rows,
uint32_t row_pitch_B,
uint64_t *out_size_B)
isl_calc_initial_size(const struct isl_device *dev,
const struct isl_surf_init_info *info,
const struct isl_tile_info *tile_info,
const struct isl_extent4d *phys_total_el,
uint32_t array_pitch_el_rows,
uint32_t row_pitch_B,
uint64_t *out_size_B)
{
uint64_t size_B;
if (tile_info->tiling == ISL_TILING_LINEAR) {
@ -3205,50 +3205,6 @@ isl_calc_size(const struct isl_device *dev,
size_B = (uint64_t) total_h_tl * tile_info->phys_extent_B.height *
row_pitch_B;
/* Bspec 57340 (r59562):
*
* When allocating memory, MCS buffer size is extended by 4KB over
* its original calculated size. First 4KB page of the MCS is
* reserved for internal HW usage.
*
* Allocate an extra 4KB page reserved for hardware at the beginning of
* MCS buffer on Xe2. The start address of MCS is the head of the 4KB
* page. Any manipulation on the content of MCS should start after 4KB
* from the start address.
*/
if (dev->info->ver >= 20 && info->usage & ISL_SURF_USAGE_MCS_BIT)
size_B += 4096;
}
/* If for some reason we can't support the appropriate tiling format and
* end up falling to linear or some other format, make sure the image size
* and alignment are aligned to the expected block size so we can at least
* do opaque binds.
*/
if (info->usage & ISL_SURF_USAGE_SPARSE_BIT)
size_B = isl_align(size_B, 64 * 1024);
/* Pre-gfx9: from the Broadwell PRM Vol 5, Surface Layout:
* "In addition to restrictions on maximum height, width, and depth,
* surfaces are also restricted to a maximum size in bytes. This
* maximum is 2 GB for all products and all surface types."
*
* gfx9-10: from the Skylake PRM Vol 5, Maximum Surface Size in Bytes:
* "In addition to restrictions on maximum height, width, and depth,
* surfaces are also restricted to a maximum size of 2^38 bytes.
* All pixels within the surface must be contained within 2^38 bytes
* of the base address."
*
* gfx11+ platforms raised this limit to 2^44 bytes.
*/
uint64_t max_surface_B = 1ull << (ISL_GFX_VER(dev) >= 11 ? 44 :
ISL_GFX_VER(dev) >= 9 ? 38 : 31);
if (size_B > max_surface_B) {
return notify_failure(
info,
"calculated size (%"PRIu64"B) exceeds platform limit of %"PRIu64"B",
size_B, max_surface_B);
}
*out_size_B = size_B;
@ -3371,6 +3327,90 @@ isl_calc_base_alignment(const struct isl_device *dev,
return base_alignment_B;
}
static bool
isl_calc_final_size(const struct isl_device *dev,
const struct isl_surf_init_info *restrict info,
struct isl_surf *surf)
{
/* Remove extra padding if the row-pitch is flexible. A fixed row pitch
* could indicate that an image is being redescribed or imported/exported.
*/
if (info->row_pitch_B == 0) {
uint64_t end_tile_B_max = 0;
for (int lod = 0; lod < surf->levels; lod++) {
uint64_t start_tile_B, end_tile_B;
if (surf->dim == ISL_SURF_DIM_3D) {
int last_z = u_minify(surf->logical_level0_px.d, lod) - 1;
isl_surf_get_image_range_B_tile(surf, lod, 0, last_z,
&start_tile_B, &end_tile_B);
} else {
int last_layer = surf->logical_level0_px.a - 1;
isl_surf_get_image_range_B_tile(surf, lod, last_layer, 0,
&start_tile_B, &end_tile_B);
}
end_tile_B_max = MAX2(end_tile_B_max, end_tile_B);
/* There's no padding if this LOD has a pixel in the last tile. */
if (end_tile_B_max == surf->size_B)
break;
}
uint64_t padding_B = surf->size_B - end_tile_B_max;
if (padding_B > 0) {
print_info(info, "Omitted %ld 4KB page(s) of padding.",
padding_B / 4096);
surf->size_B = end_tile_B_max;
}
}
/* If for some reason we can't support the appropriate tiling format and
* end up falling to linear or some other format, make sure the image size
* and alignment are aligned to the expected block size so we can at least
* do opaque binds.
*/
if (surf->usage & ISL_SURF_USAGE_SPARSE_BIT)
surf->size_B = isl_align(surf->size_B, 64 * 1024);
/* Bspec 57340 (r59562):
*
* When allocating memory, MCS buffer size is extended by 4KB over
* its original calculated size. First 4KB page of the MCS is
* reserved for internal HW usage.
*
* Allocate an extra 4KB page reserved for hardware at the beginning of
* MCS buffer on Xe2. The start address of MCS is the head of the 4KB
* page. Any manipulation on the content of MCS should start after 4KB
* from the start address.
*/
if (dev->info->ver >= 20 && surf->usage & ISL_SURF_USAGE_MCS_BIT)
surf->size_B += 4096;
/* Pre-gfx9: from the Broadwell PRM Vol 5, Surface Layout:
* "In addition to restrictions on maximum height, width, and depth,
* surfaces are also restricted to a maximum size in bytes. This
* maximum is 2 GB for all products and all surface types."
*
* gfx9-10: from the Skylake PRM Vol 5, Maximum Surface Size in Bytes:
* "In addition to restrictions on maximum height, width, and depth,
* surfaces are also restricted to a maximum size of 2^38 bytes.
* All pixels within the surface must be contained within 2^38 bytes
* of the base address."
*
* gfx11+ platforms raised this limit to 2^44 bytes.
*/
uint64_t max_surface_B = 1ull << (ISL_GFX_VER(dev) >= 11 ? 44 :
ISL_GFX_VER(dev) >= 9 ? 38 : 31);
if (surf->size_B > max_surface_B) {
return notify_failure(
info,
"calculated size (%"PRIu64"B) exceeds platform limit of %"PRIu64"B",
surf->size_B, max_surface_B);
}
return true;
}
static bool
isl_surf_init_s_with_tiling(const struct isl_device *dev,
struct isl_surf *surf,
@ -3433,9 +3473,10 @@ isl_surf_init_s_with_tiling(const struct isl_device *dev,
&phys_total_el, &row_pitch_B))
return false;
uint64_t size_B;
if (!isl_calc_size(dev, info, &tile_info, &phys_total_el,
array_pitch_el_rows, row_pitch_B, &size_B))
uint64_t initial_size_B;
if (!isl_calc_initial_size(dev, info, &tile_info, &phys_total_el,
array_pitch_el_rows, row_pitch_B,
&initial_size_B))
return false;
const uint32_t base_alignment_B =
@ -3455,7 +3496,7 @@ isl_surf_init_s_with_tiling(const struct isl_device *dev,
.logical_level0_px = logical_level0_px,
.phys_level0_sa = phys_level0_sa,
.size_B = size_B,
.size_B = initial_size_B,
.alignment_B = base_alignment_B,
.row_pitch_B = row_pitch_B,
.array_pitch_el_rows = array_pitch_el_rows,
@ -3465,7 +3506,7 @@ isl_surf_init_s_with_tiling(const struct isl_device *dev,
.usage = info->usage,
};
return true;
return isl_calc_final_size(dev, info, surf);
}
bool
@ -4724,7 +4765,17 @@ isl_surf_get_image_range_B_tile(const struct isl_surf *surf,
/* We only consider one Z or array slice */
const uint32_t end_z_offset_el = start_z_offset_el;
const uint32_t end_array_slice = start_array_slice;
uint32_t end_array_slice = start_array_slice;
/* Find the last sample */
struct isl_tile_info tile_info;
isl_surf_get_tile_info(surf, &tile_info);
if (surf->msaa_layout == ISL_MSAA_LAYOUT_ARRAY) {
if (tile_info.logical_extent_el.a > 1)
end_array_slice += surf->samples - 1;
else
end_y_offset_el += (surf->samples - 1) * surf->array_pitch_el_rows;
}
UNUSED uint32_t x_offset_el, y_offset_el, z_offset_el, array_slice;
isl_tiling_get_intratile_offset_el(surf->tiling, surf->dim,
@ -4757,9 +4808,6 @@ isl_surf_get_image_range_B_tile(const struct isl_surf *surf,
&z_offset_el,
&array_slice);
struct isl_tile_info tile_info;
isl_surf_get_tile_info(surf, &tile_info);
/* We want the range we return to be exclusive but the tile containing the
* last pixel (what we just calculated) is inclusive. Add one and round up
* to the tile size.