ac/surface,radeonsi: move the set/get_umd_metadata code into ac_surface.c

The indentation is on purpose. The whole file will be reindented to this
code style some other time.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4863>
This commit is contained in:
Marek Olšák 2020-05-02 12:23:51 -04:00 committed by Marge Bot
parent 7691de0dce
commit c164ea86e1
3 changed files with 185 additions and 147 deletions

View file

@ -1913,6 +1913,14 @@ int ac_compute_surface(ADDR_HANDLE addrlib, const struct radeon_info *info,
return 0;
}
/* This is meant to be used for disabling DCC. */
void ac_surface_zero_dcc_fields(struct radeon_surf *surf)
{
surf->dcc_offset = 0;
surf->display_dcc_offset = 0;
surf->dcc_retile_map_offset = 0;
}
static unsigned eg_tile_split(unsigned tile_split)
{
switch (tile_split) {
@ -2026,3 +2034,158 @@ void ac_surface_get_bo_metadata(const struct radeon_info *info,
*tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 1); /* THIN_MICRO_TILING */
}
}
static uint32_t ac_get_umd_metadata_word1(const struct radeon_info *info)
{
return (ATI_VENDOR_ID << 16) | info->pci_id;
}
/* This should be called after ac_compute_surface. */
bool ac_surface_set_umd_metadata(const struct radeon_info *info,
struct radeon_surf *surf,
unsigned num_storage_samples,
unsigned num_mipmap_levels,
unsigned size_metadata,
uint32_t metadata[64])
{
uint32_t *desc = &metadata[2];
uint64_t offset;
if (info->chip_class >= GFX9)
offset = surf->u.gfx9.surf_offset;
else
offset = surf->u.legacy.level[0].offset;
if (offset || /* Non-zero planes ignore metadata. */
size_metadata < 10 * 4 || /* at least 2(header) + 8(desc) dwords */
metadata[0] == 0 || /* invalid version number */
metadata[1] != ac_get_umd_metadata_word1(info)) /* invalid PCI ID */ {
/* Disable DCC because it might not be enabled. */
ac_surface_zero_dcc_fields(surf);
/* Don't report an error if the texture comes from an incompatible driver,
* but this might not work.
*/
return true;
}
/* Validate that sample counts and the number of mipmap levels match. */
unsigned desc_last_level = G_008F1C_LAST_LEVEL(desc[3]);
unsigned type = G_008F1C_TYPE(desc[3]);
if (type == V_008F1C_SQ_RSRC_IMG_2D_MSAA || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
unsigned log_samples = util_logbase2(MAX2(1, num_storage_samples));
if (desc_last_level != log_samples) {
fprintf(stderr,
"amdgpu: invalid MSAA texture import, "
"metadata has log2(samples) = %u, the caller set %u\n",
desc_last_level, log_samples);
return false;
}
} else {
if (desc_last_level != num_mipmap_levels - 1) {
fprintf(stderr,
"amdgpu: invalid mipmapped texture import, "
"metadata has last_level = %u, the caller set %u\n",
desc_last_level, num_mipmap_levels - 1);
return false;
}
}
if (info->chip_class >= GFX8 && G_008F28_COMPRESSION_EN(desc[6])) {
/* Read DCC information. */
switch (info->chip_class) {
case GFX8:
surf->dcc_offset = (uint64_t)desc[7] << 8;
break;
case GFX9:
surf->dcc_offset =
((uint64_t)desc[7] << 8) | ((uint64_t)G_008F24_META_DATA_ADDRESS(desc[5]) << 40);
surf->u.gfx9.dcc.pipe_aligned = G_008F24_META_PIPE_ALIGNED(desc[5]);
surf->u.gfx9.dcc.rb_aligned = G_008F24_META_RB_ALIGNED(desc[5]);
/* If DCC is unaligned, this can only be a displayable image. */
if (!surf->u.gfx9.dcc.pipe_aligned && !surf->u.gfx9.dcc.rb_aligned)
assert(surf->is_displayable);
break;
case GFX10:
surf->dcc_offset =
((uint64_t)G_00A018_META_DATA_ADDRESS_LO(desc[6]) << 8) | ((uint64_t)desc[7] << 16);
surf->u.gfx9.dcc.pipe_aligned = G_00A018_META_PIPE_ALIGNED(desc[6]);
break;
default:
assert(0);
return false;
}
} else {
/* Disable DCC. dcc_offset is always set by texture_from_handle
* and must be cleared here.
*/
ac_surface_zero_dcc_fields(surf);
}
return true;
}
void ac_surface_get_umd_metadata(const struct radeon_info *info,
struct radeon_surf *surf,
unsigned num_mipmap_levels,
uint32_t desc[8],
unsigned *size_metadata, uint32_t metadata[64])
{
/* Clear the base address and set the relative DCC offset. */
desc[0] = 0;
desc[1] &= C_008F14_BASE_ADDRESS_HI;
switch (info->chip_class) {
case GFX6:
case GFX7:
break;
case GFX8:
desc[7] = surf->dcc_offset >> 8;
break;
case GFX9:
desc[7] = surf->dcc_offset >> 8;
desc[5] &= C_008F24_META_DATA_ADDRESS;
desc[5] |= S_008F24_META_DATA_ADDRESS(surf->dcc_offset >> 40);
break;
case GFX10:
desc[6] &= C_00A018_META_DATA_ADDRESS_LO;
desc[6] |= S_00A018_META_DATA_ADDRESS_LO(surf->dcc_offset >> 8);
desc[7] = surf->dcc_offset >> 16;
break;
default:
assert(0);
}
/* Metadata image format format version 1:
* [0] = 1 (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
* [10:10+LAST_LEVEL] = mipmap level offset bits [39:8] for each level
*/
metadata[0] = 1; /* metadata image format version 1 */
/* Tiling modes are ambiguous without a PCI ID. */
metadata[1] = ac_get_umd_metadata_word1(info);
/* Dwords [2:9] contain the image descriptor. */
memcpy(&metadata[2], desc, 8 * 4);
*size_metadata = 10 * 4;
/* Dwords [10:..] contain the mipmap level offsets. */
if (info->chip_class <= GFX8) {
for (unsigned i = 0; i < num_mipmap_levels; i++)
metadata[10 + i] = surf->u.legacy.level[i].offset >> 8;
*size_metadata += num_mipmap_levels * 4;
}
}

View file

@ -289,6 +289,7 @@ int ac_compute_surface(ADDR_HANDLE addrlib, const struct radeon_info *info,
const struct ac_surf_config * config,
enum radeon_surf_mode mode,
struct radeon_surf *surf);
void ac_surface_zero_dcc_fields(struct radeon_surf *surf);
void ac_surface_set_bo_metadata(const struct radeon_info *info,
struct radeon_surf *surf, uint64_t tiling_flags,
@ -296,6 +297,18 @@ void ac_surface_set_bo_metadata(const struct radeon_info *info,
void ac_surface_get_bo_metadata(const struct radeon_info *info,
struct radeon_surf *surf, uint64_t *tiling_flags);
bool ac_surface_set_umd_metadata(const struct radeon_info *info,
struct radeon_surf *surf,
unsigned num_storage_samples,
unsigned num_mipmap_levels,
unsigned size_metadata,
uint32_t metadata[64]);
void ac_surface_get_umd_metadata(const struct radeon_info *info,
struct radeon_surf *surf,
unsigned num_mipmap_levels,
uint32_t desc[8],
unsigned *size_metadata, uint32_t metadata[64]);
#ifdef __cplusplus
}
#endif

View file

@ -380,13 +380,6 @@ static bool si_can_disable_dcc(struct si_texture *tex)
!(tex->buffer.external_usage & PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
}
static void si_texture_zero_dcc_fields(struct si_texture *tex)
{
tex->surface.dcc_offset = 0;
tex->surface.display_dcc_offset = 0;
tex->surface.dcc_retile_map_offset = 0;
}
static bool si_texture_discard_dcc(struct si_screen *sscreen, struct si_texture *tex)
{
if (!si_can_disable_dcc(tex))
@ -395,7 +388,7 @@ static bool si_texture_discard_dcc(struct si_screen *sscreen, struct si_texture
assert(tex->dcc_separate_buffer == NULL);
/* Disable DCC. */
si_texture_zero_dcc_fields(tex);
ac_surface_zero_dcc_fields(&tex->surface);
/* Notify all contexts about the change. */
p_atomic_inc(&sscreen->dirty_tex_counter);
@ -555,11 +548,6 @@ static void si_reallocate_texture_inplace(struct si_context *sctx, struct si_tex
p_atomic_inc(&sctx->screen->dirty_tex_counter);
}
static uint32_t si_get_bo_metadata_word1(struct si_screen *sscreen)
{
return (ATI_VENDOR_ID << 16) | sscreen->info.pci_id;
}
static void si_set_tex_bo_metadata(struct si_screen *sscreen, struct si_texture *tex)
{
struct pipe_resource *res = &tex->buffer.b.b;
@ -570,21 +558,6 @@ static void si_set_tex_bo_metadata(struct si_screen *sscreen, struct si_texture
assert(tex->dcc_separate_buffer == NULL);
assert(tex->surface.fmask_size == 0);
/* Metadata image format format version 1:
* [0] = 1 (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
* [10:10+LAST_LEVEL] = mipmap level offset bits [39:8] for each level
*/
md.metadata[0] = 1; /* metadata image format version 1 */
/* TILE_MODE_INDEX is ambiguous without a PCI ID. */
md.metadata[1] = si_get_bo_metadata_word1(sscreen);
static const unsigned char swizzle[] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z,
PIPE_SWIZZLE_W};
bool is_array = util_texture_is_array(res->target);
@ -593,130 +566,15 @@ static void si_set_tex_bo_metadata(struct si_screen *sscreen, struct si_texture
sscreen->make_texture_descriptor(sscreen, tex, true, res->target, res->format, swizzle, 0,
res->last_level, 0, is_array ? res->array_size - 1 : 0,
res->width0, res->height0, res->depth0, desc, NULL);
si_set_mutable_tex_desc_fields(sscreen, tex, &tex->surface.u.legacy.level[0], 0, 0,
tex->surface.blk_w, false, false, desc);
/* Clear the base address and set the relative DCC offset. */
desc[0] = 0;
desc[1] &= C_008F14_BASE_ADDRESS_HI;
switch (sscreen->info.chip_class) {
case GFX6:
case GFX7:
break;
case GFX8:
desc[7] = tex->surface.dcc_offset >> 8;
break;
case GFX9:
desc[7] = tex->surface.dcc_offset >> 8;
desc[5] &= C_008F24_META_DATA_ADDRESS;
desc[5] |= S_008F24_META_DATA_ADDRESS(tex->surface.dcc_offset >> 40);
break;
case GFX10:
desc[6] &= C_00A018_META_DATA_ADDRESS_LO;
desc[6] |= S_00A018_META_DATA_ADDRESS_LO(tex->surface.dcc_offset >> 8);
desc[7] = tex->surface.dcc_offset >> 16;
break;
default:
assert(0);
}
/* Dwords [2:9] contain the image descriptor. */
memcpy(&md.metadata[2], desc, sizeof(desc));
md.size_metadata = 10 * 4;
/* Dwords [10:..] contain the mipmap level offsets. */
if (sscreen->info.chip_class <= GFX8) {
for (unsigned i = 0; i <= res->last_level; i++)
md.metadata[10 + i] = tex->surface.u.legacy.level[i].offset >> 8;
md.size_metadata += (1 + res->last_level) * 4;
}
ac_surface_get_umd_metadata(&sscreen->info, &tex->surface,
tex->buffer.b.b.last_level + 1,
desc, &md.size_metadata, md.metadata);
sscreen->ws->buffer_set_metadata(tex->buffer.buf, &md, &tex->surface);
}
static bool si_read_tex_bo_metadata(struct si_screen *sscreen, struct si_texture *tex,
uint64_t offset, struct radeon_bo_metadata *md)
{
uint32_t *desc = &md->metadata[2];
if (offset || /* Non-zero planes ignore metadata. */
md->size_metadata < 10 * 4 || /* at least 2(header) + 8(desc) dwords */
md->metadata[0] == 0 || /* invalid version number */
md->metadata[1] != si_get_bo_metadata_word1(sscreen)) /* invalid PCI ID */ {
/* Disable DCC because it might not be enabled. */
si_texture_zero_dcc_fields(tex);
/* Don't report an error if the texture comes from an incompatible driver,
* but this might not work.
*/
return true;
}
/* Validate that sample counts and the number of mipmap levels match. */
unsigned last_level = G_008F1C_LAST_LEVEL(desc[3]);
unsigned type = G_008F1C_TYPE(desc[3]);
if (type == V_008F1C_SQ_RSRC_IMG_2D_MSAA || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
unsigned log_samples = util_logbase2(MAX2(1, tex->buffer.b.b.nr_storage_samples));
if (last_level != log_samples) {
fprintf(stderr,
"radeonsi: invalid MSAA texture import, "
"metadata has log2(samples) = %u, the caller set %u\n",
last_level, log_samples);
return false;
}
} else {
if (last_level != tex->buffer.b.b.last_level) {
fprintf(stderr,
"radeonsi: invalid mipmapped texture import, "
"metadata has last_level = %u, the caller set %u\n",
last_level, tex->buffer.b.b.last_level);
return false;
}
}
if (sscreen->info.chip_class >= GFX8 && G_008F28_COMPRESSION_EN(desc[6])) {
/* Read DCC information. */
switch (sscreen->info.chip_class) {
case GFX8:
tex->surface.dcc_offset = (uint64_t)desc[7] << 8;
break;
case GFX9:
tex->surface.dcc_offset =
((uint64_t)desc[7] << 8) | ((uint64_t)G_008F24_META_DATA_ADDRESS(desc[5]) << 40);
tex->surface.u.gfx9.dcc.pipe_aligned = G_008F24_META_PIPE_ALIGNED(desc[5]);
tex->surface.u.gfx9.dcc.rb_aligned = G_008F24_META_RB_ALIGNED(desc[5]);
/* If DCC is unaligned, this can only be a displayable image. */
if (!tex->surface.u.gfx9.dcc.pipe_aligned && !tex->surface.u.gfx9.dcc.rb_aligned)
assert(tex->surface.is_displayable);
break;
case GFX10:
tex->surface.dcc_offset =
((uint64_t)G_00A018_META_DATA_ADDRESS_LO(desc[6]) << 8) | ((uint64_t)desc[7] << 16);
tex->surface.u.gfx9.dcc.pipe_aligned = G_00A018_META_PIPE_ALIGNED(desc[6]);
break;
default:
assert(0);
return false;
}
} else {
/* Disable DCC. dcc_offset is always set by texture_from_handle
* and must be cleared here.
*/
si_texture_zero_dcc_fields(tex);
}
return true;
}
static bool si_has_displayable_dcc(struct si_texture *tex)
{
struct si_screen *sscreen = (struct si_screen *)tex->buffer.b.b.screen;
@ -1582,7 +1440,11 @@ static struct pipe_resource *si_texture_from_winsys_buffer(struct si_screen *ssc
next_plane = next_plane->next;
}
if (!si_read_tex_bo_metadata(sscreen, tex, offset, &metadata)) {
if (!ac_surface_set_umd_metadata(&sscreen->info, &tex->surface,
tex->buffer.b.b.nr_storage_samples,
tex->buffer.b.b.last_level + 1,
metadata.size_metadata,
metadata.metadata)) {
si_texture_reference(&tex, NULL);
return NULL;
}