ac/surface: add flags to surface metadata

Instead of increasing the version number to describe which fields
are set, use the lower 16 bits for the metadata format version,
and the other bits as flags.
This way the version number defines the layout, and the flags
tell which values are set.

The format version is bumped to 3 (= can have flags), and 2 flags
are defined:
* AC_SURF_METADATA_FLAG_EXTRA_MD_BIT: replaces what was version
  number = 2. This means the metadata contains extra information
  for tools.
* AC_SURF_METADATA_FLAG_FAMILY_OVERRIDEN_BIT: if set, it means the
  surface was allocated from a context that used an overriden gfx
  family. This allows the importer process to fail the import early,
  as the surface is likely to be invalid.
  It also adds an extra dw at the end, to store the fake family.

This is a breaking change for existing code that interpreted
"version > 1" as 2, but only in one case:
AC_SURF_METADATA_FLAG_FAMILY_OVERRIDEN_BIT being set, but not
AC_SURF_METADATA_FLAG_EXTRA_MD_BIT, which produces a version number
of 0x20001 but there's not extra data.
I think this is ok, since both gfx family overriding and extra_md
are debugging tools.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31841>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2024-10-16 10:46:05 +02:00 committed by Marge Bot
parent acc32cadf5
commit 9d0aba1f97
3 changed files with 44 additions and 10 deletions

View file

@ -3492,12 +3492,12 @@ static unsigned eg_tile_split_rev(unsigned eg_tile_split)
#define AMDGPU_TILING_DCC_MAX_COMPRESSED_BLOCK_SIZE_MASK 0x3
/* This should be called before ac_compute_surface. */
void ac_surface_apply_bo_metadata(const struct radeon_info *info, struct radeon_surf *surf,
void ac_surface_apply_bo_metadata(enum amd_gfx_level gfx_level, struct radeon_surf *surf,
uint64_t tiling_flags, enum radeon_surf_mode *mode)
{
bool scanout;
if (info->gfx_level >= GFX12) {
if (gfx_level >= GFX12) {
surf->u.gfx9.swizzle_mode = AMDGPU_TILING_GET(tiling_flags, GFX12_SWIZZLE_MODE);
surf->u.gfx9.color.dcc.max_compressed_block_size =
AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK);
@ -3506,7 +3506,7 @@ void ac_surface_apply_bo_metadata(const struct radeon_info *info, struct radeon_
surf->u.gfx9.color.dcc_number_type =
AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_NUMBER_TYPE);
scanout = AMDGPU_TILING_GET(tiling_flags, GFX12_SCANOUT);
} else if (info->gfx_level >= GFX9) {
} else if (gfx_level >= GFX9) {
surf->u.gfx9.swizzle_mode = AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE);
surf->u.gfx9.color.dcc.independent_64B_blocks =
AMDGPU_TILING_GET(tiling_flags, DCC_INDEPENDENT_64B);
@ -3730,21 +3730,31 @@ void ac_surface_compute_umd_metadata(const struct radeon_info *info, struct rade
/* Metadata image format format version 1 and 2. Version 2 uses the same layout as
* version 1 with some additional fields (used if include_tool_md=true).
* [0] = metadata_format_identifier
* [0] = optional flags | metadata_format_identifier
* [1] = (VENDOR_ID << 16) | PCI_ID
* [2:9] = image descriptor for the whole resource
* [2] is always 0, because the base address is cleared
* [9] is the DCC offset bits [39:8] from the beginning of
* the buffer
* gfx8-: [10:10+LAST_LEVEL] = mipmap level offset bits [39:8] for each level (gfx8-)
* ---- The data below is only set in version=2.
* ---- Optional data (if version == 2 or version > 2 + AC_SURF_METADATA_FLAG_EXTRA_MD_BIT)
* AC_SURF_METADATA_FLAG_EXTRA_MD_BIT is set.
* It shouldn't be used by the driver as it's only present to help
* tools (eg: umr) that would want to access this buffer.
* gfx9+ if valid modifier: [10:11] = modifier
* [12:12+3*nplane] = [offset, stride]
* else: [10]: stride
* ---- Optional data (if version >= 3 + AC_SURF_METADATA_FLAG_FAMILY_OVERRIDEN_BIT)
* [last] = fake family id
*/
metadata[0] = include_tool_md ? 2 : 1; /* metadata image format version */
/* metadata image format version */
metadata[0] = (include_tool_md || info->family_overridden) ? 3 : 1;
if (include_tool_md)
metadata[0] |= 1u << (16 + AC_SURF_METADATA_FLAG_EXTRA_MD_BIT);
if (info->family_overridden)
metadata[0] |= 1u << (16 + AC_SURF_METADATA_FLAG_FAMILY_OVERRIDEN_BIT);
/* Tiling modes are ambiguous without a PCI ID. */
metadata[1] = ac_get_umd_metadata_word1(info);
@ -3781,6 +3791,13 @@ void ac_surface_compute_umd_metadata(const struct radeon_info *info, struct rade
*size_metadata = 11 * 4;
}
}
if (info->family_overridden) {
int n_dw = *size_metadata / 4;
assert(n_dw < 64 - 1);
metadata[n_dw] = info->gfx_level;
*size_metadata += 4;
}
}
static uint32_t ac_surface_get_pitch_align(const struct radeon_info *info,

View file

@ -454,7 +454,9 @@ int ac_compute_surface(struct ac_addrlib *addrlib, const struct radeon_info *inf
void ac_surface_zero_dcc_fields(struct radeon_surf *surf);
unsigned ac_pipe_config_to_num_pipes(unsigned pipe_config);
void ac_surface_apply_bo_metadata(const struct radeon_info *info, struct radeon_surf *surf,
#define AC_SURF_METADATA_FLAG_EXTRA_MD_BIT 0
#define AC_SURF_METADATA_FLAG_FAMILY_OVERRIDEN_BIT 1
void ac_surface_apply_bo_metadata(enum amd_gfx_level gfx_level, struct radeon_surf *surf,
uint64_t tiling_flags, enum radeon_surf_mode *mode);
void ac_surface_compute_bo_metadata(const struct radeon_info *info, struct radeon_surf *surf,
uint64_t *tiling_flags);

View file

@ -1305,17 +1305,32 @@ static void amdgpu_buffer_get_metadata(struct radeon_winsys *rws,
struct amdgpu_winsys *aws = amdgpu_winsys(rws);
struct amdgpu_bo_real *bo = get_real_bo(amdgpu_winsys_bo(_buf));
struct amdgpu_bo_info info = {0};
uint32_t md_version, md_flags;
enum amd_gfx_level gfx_level = aws->info.gfx_level;
int r;
r = amdgpu_bo_query_info(bo->bo_handle, &info);
if (r)
return;
ac_surface_apply_bo_metadata(&aws->info, surf, info.metadata.tiling_info,
&md->mode);
md->size_metadata = info.metadata.size_metadata;
memcpy(md->metadata, info.metadata.umd_metadata, sizeof(md->metadata));
md_version = md->metadata[0] & 0xffff;
if (md_version >= 3 && md->size_metadata > 4) {
md_flags = md->metadata[0] >> 16;
if (md_flags & (1u << AC_SURF_METADATA_FLAG_FAMILY_OVERRIDEN_BIT)) {
/* The overriden gfx_level is always the last dword. */
gfx_level = md->metadata[md->size_metadata / 4 - 1];
/* Fallback to the default value if the value we got is incorrect. */
if (gfx_level < GFX6 || gfx_level >= NUM_GFX_VERSIONS)
gfx_level = aws->info.gfx_level;
}
}
ac_surface_apply_bo_metadata(gfx_level, surf, info.metadata.tiling_info,
&md->mode);
}
static void amdgpu_buffer_set_metadata(struct radeon_winsys *rws,