From: Marek Olšák Date: Sat, 2 May 2020 16:23:51 +0000 (-0400) Subject: ac/surface,radeonsi: move the set/get_umd_metadata code into ac_surface.c X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c164ea86e193c710d41de769ddfb169ab53ced51;p=mesa.git 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 Reviewed-by: Samuel Pitoiset Part-of: --- diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c index 4da4a7eae4c..5bfea4b5762 100644 --- a/src/amd/common/ac_surface.c +++ b/src/amd/common/ac_surface.c @@ -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; + } +} diff --git a/src/amd/common/ac_surface.h b/src/amd/common/ac_surface.h index ef624a5d576..11e92d12fc5 100644 --- a/src/amd/common/ac_surface.h +++ b/src/amd/common/ac_surface.h @@ -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 diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c index 9753a8d5623..b3052e5cd04 100644 --- a/src/gallium/drivers/radeonsi/si_texture.c +++ b/src/gallium/drivers/radeonsi/si_texture.c @@ -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; }