Path: blob/21.2-virgl/src/amd/vulkan/radv_image.c
7130 views
/*1* Copyright © 2016 Red Hat.2* Copyright © 2016 Bas Nieuwenhuizen3*4* based in part on anv driver which is:5* Copyright © 2015 Intel Corporation6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the "Software"),9* to deal in the Software without restriction, including without limitation10* the rights to use, copy, modify, merge, publish, distribute, sublicense,11* and/or sell copies of the Software, and to permit persons to whom the12* Software is furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice (including the next15* paragraph) shall be included in all copies or substantial portions of the16* Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR19* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,20* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL21* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER22* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING23* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS24* IN THE SOFTWARE.25*/2627#include "ac_drm_fourcc.h"28#include "util/debug.h"29#include "util/u_atomic.h"30#include "vulkan/util/vk_format.h"31#include "radv_debug.h"32#include "radv_private.h"33#include "radv_radeon_winsys.h"34#include "sid.h"35#include "vk_format.h"36#include "vk_util.h"3738#include "gfx10_format_table.h"3940static const VkImageUsageFlagBits RADV_IMAGE_USAGE_WRITE_BITS =41VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |42VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT;4344static unsigned45radv_choose_tiling(struct radv_device *device, const VkImageCreateInfo *pCreateInfo,46VkFormat format)47{48if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) {49assert(pCreateInfo->samples <= 1);50return RADEON_SURF_MODE_LINEAR_ALIGNED;51}5253/* MSAA resources must be 2D tiled. */54if (pCreateInfo->samples > 1)55return RADEON_SURF_MODE_2D;5657if (!vk_format_is_compressed(format) && !vk_format_is_depth_or_stencil(format) &&58device->physical_device->rad_info.chip_class <= GFX8) {59/* this causes hangs in some VK CTS tests on GFX9. */60/* Textures with a very small height are recommended to be linear. */61if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D ||62/* Only very thin and long 2D textures should benefit from63* linear_aligned. */64(pCreateInfo->extent.width > 8 && pCreateInfo->extent.height <= 2))65return RADEON_SURF_MODE_LINEAR_ALIGNED;66}6768return RADEON_SURF_MODE_2D;69}7071static bool72radv_use_tc_compat_htile_for_image(struct radv_device *device, const VkImageCreateInfo *pCreateInfo,73VkFormat format)74{75/* TC-compat HTILE is only available for GFX8+. */76if (device->physical_device->rad_info.chip_class < GFX8)77return false;7879if ((pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT))80return false;8182if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)83return false;8485/* Do not enable TC-compatible HTILE if the image isn't readable by a86* shader because no texture fetches will happen.87*/88if (!(pCreateInfo->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |89VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))90return false;9192if (device->physical_device->rad_info.chip_class < GFX9) {93/* TC-compat HTILE for MSAA depth/stencil images is broken94* on GFX8 because the tiling doesn't match.95*/96if (pCreateInfo->samples >= 2 && format == VK_FORMAT_D32_SFLOAT_S8_UINT)97return false;9899/* GFX9+ supports compression for both 32-bit and 16-bit depth100* surfaces, while GFX8 only supports 32-bit natively. Though,101* the driver allows TC-compat HTILE for 16-bit depth surfaces102* with no Z planes compression.103*/104if (format != VK_FORMAT_D32_SFLOAT_S8_UINT && format != VK_FORMAT_D32_SFLOAT &&105format != VK_FORMAT_D16_UNORM)106return false;107}108109return true;110}111112static bool113radv_surface_has_scanout(struct radv_device *device, const struct radv_image_create_info *info)114{115if (info->bo_metadata) {116if (device->physical_device->rad_info.chip_class >= GFX9)117return info->bo_metadata->u.gfx9.scanout;118else119return info->bo_metadata->u.legacy.scanout;120}121122return info->scanout;123}124125static bool126radv_image_use_fast_clear_for_image(const struct radv_device *device,127const struct radv_image *image)128{129if (device->instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)130return true;131132if (image->info.samples <= 1 && image->info.width * image->info.height <= 512 * 512) {133/* Do not enable CMASK or DCC for small surfaces where the cost134* of the eliminate pass can be higher than the benefit of fast135* clear. RadeonSI does this, but the image threshold is136* different.137*/138return false;139}140141return image->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT &&142(image->exclusive ||143/* Enable DCC for concurrent images if stores are144* supported because that means we can keep DCC compressed on145* all layouts/queues.146*/147radv_image_use_dcc_image_stores(device, image));148}149150bool151radv_are_formats_dcc_compatible(const struct radv_physical_device *pdev, const void *pNext,152VkFormat format, VkImageCreateFlags flags)153{154bool blendable;155156if (!radv_is_colorbuffer_format_supported(pdev, format, &blendable))157return false;158159if (flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {160const struct VkImageFormatListCreateInfo *format_list =161(const struct VkImageFormatListCreateInfo *)vk_find_struct_const(162pNext, IMAGE_FORMAT_LIST_CREATE_INFO);163164/* We have to ignore the existence of the list if viewFormatCount = 0 */165if (format_list && format_list->viewFormatCount) {166/* compatibility is transitive, so we only need to check167* one format with everything else. */168for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {169if (format_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)170continue;171172if (!radv_dcc_formats_compatible(format, format_list->pViewFormats[i]))173return false;174}175} else {176return false;177}178}179180return true;181}182183static bool184radv_formats_is_atomic_allowed(const void *pNext, VkFormat format, VkImageCreateFlags flags)185{186if (radv_is_atomic_format_supported(format))187return true;188189if (flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {190const struct VkImageFormatListCreateInfo *format_list =191(const struct VkImageFormatListCreateInfo *)vk_find_struct_const(192pNext, IMAGE_FORMAT_LIST_CREATE_INFO);193194/* We have to ignore the existence of the list if viewFormatCount = 0 */195if (format_list && format_list->viewFormatCount) {196for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {197if (radv_is_atomic_format_supported(format_list->pViewFormats[i]))198return true;199}200}201}202203return false;204}205206static bool207radv_use_dcc_for_image(struct radv_device *device, const struct radv_image *image,208const VkImageCreateInfo *pCreateInfo, VkFormat format)209{210/* DCC (Delta Color Compression) is only available for GFX8+. */211if (device->physical_device->rad_info.chip_class < GFX8)212return false;213214if (device->instance->debug_flags & RADV_DEBUG_NO_DCC)215return false;216217if (image->shareable && image->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)218return false;219220/*221* TODO: Enable DCC for storage images on GFX9 and earlier.222*223* Also disable DCC with atomics because even when DCC stores are224* supported atomics will always decompress. So if we are225* decompressing a lot anyway we might as well not have DCC.226*/227if ((pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&228(!radv_image_use_dcc_image_stores(device, image) ||229radv_formats_is_atomic_allowed(pCreateInfo->pNext, format, pCreateInfo->flags)))230return false;231232/* Do not enable DCC for fragment shading rate attachments. */233if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)234return false;235236if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)237return false;238239if (vk_format_is_subsampled(format) || vk_format_get_plane_count(format) > 1)240return false;241242if (!radv_image_use_fast_clear_for_image(device, image) &&243image->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)244return false;245246/* Do not enable DCC for mipmapped arrays because performance is worse. */247if (pCreateInfo->arrayLayers > 1 && pCreateInfo->mipLevels > 1)248return false;249250if (device->physical_device->rad_info.chip_class < GFX10) {251/* TODO: Add support for DCC MSAA on GFX8-9. */252if (pCreateInfo->samples > 1 && !device->physical_device->dcc_msaa_allowed)253return false;254255/* TODO: Add support for DCC layers/mipmaps on GFX9. */256if ((pCreateInfo->arrayLayers > 1 || pCreateInfo->mipLevels > 1) &&257device->physical_device->rad_info.chip_class == GFX9)258return false;259}260261return radv_are_formats_dcc_compatible(device->physical_device, pCreateInfo->pNext, format,262pCreateInfo->flags);263}264265/*266* Whether to enable image stores with DCC compression for this image. If267* this function returns false the image subresource should be decompressed268* before using it with image stores.269*270* Note that this can have mixed performance implications, see271* https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6796#note_643299272*273* This function assumes the image uses DCC compression.274*/275bool276radv_image_use_dcc_image_stores(const struct radv_device *device, const struct radv_image *image)277{278return device->physical_device->rad_info.chip_class >= GFX10;279}280281/*282* Whether to use a predicate to determine whether DCC is in a compressed283* state. This can be used to avoid decompressing an image multiple times.284*/285bool286radv_image_use_dcc_predication(const struct radv_device *device, const struct radv_image *image)287{288return radv_image_has_dcc(image) && !radv_image_use_dcc_image_stores(device, image);289}290291static inline bool292radv_use_fmask_for_image(const struct radv_device *device, const struct radv_image *image)293{294return image->info.samples > 1 && ((image->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) ||295(device->instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS));296}297298static inline bool299radv_use_htile_for_image(const struct radv_device *device, const struct radv_image *image)300{301/* TODO:302* - Investigate about mips+layers.303* - Enable on other gens.304*/305bool use_htile_for_mips =306image->info.array_size == 1 && device->physical_device->rad_info.chip_class >= GFX10;307308/* Do not enable HTILE for very small images because it seems less performant but make sure it's309* allowed with VRS attachments because we need HTILE.310*/311if (image->info.width * image->info.height < 8 * 8 &&312!(device->instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS) &&313!device->attachment_vrs_enabled)314return false;315316return (image->info.levels == 1 || use_htile_for_mips) && !image->shareable;317}318319static bool320radv_use_tc_compat_cmask_for_image(struct radv_device *device, struct radv_image *image)321{322/* TC-compat CMASK is only available for GFX8+. */323if (device->physical_device->rad_info.chip_class < GFX8)324return false;325326if (device->instance->debug_flags & RADV_DEBUG_NO_TC_COMPAT_CMASK)327return false;328329if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT)330return false;331332/* Do not enable TC-compatible if the image isn't readable by a shader333* because no texture fetches will happen.334*/335if (!(image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |336VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))337return false;338339/* If the image doesn't have FMASK, it can't be fetchable. */340if (!radv_image_has_fmask(image))341return false;342343return true;344}345346static uint32_t347si_get_bo_metadata_word1(const struct radv_device *device)348{349return (ATI_VENDOR_ID << 16) | device->physical_device->rad_info.pci_id;350}351352static bool353radv_is_valid_opaque_metadata(const struct radv_device *device, const struct radeon_bo_metadata *md)354{355if (md->metadata[0] != 1 || md->metadata[1] != si_get_bo_metadata_word1(device))356return false;357358if (md->size_metadata < 40)359return false;360361return true;362}363364static void365radv_patch_surface_from_metadata(struct radv_device *device, struct radeon_surf *surface,366const struct radeon_bo_metadata *md)367{368surface->flags = RADEON_SURF_CLR(surface->flags, MODE);369370if (device->physical_device->rad_info.chip_class >= GFX9) {371if (md->u.gfx9.swizzle_mode > 0)372surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);373else374surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);375376surface->u.gfx9.swizzle_mode = md->u.gfx9.swizzle_mode;377} else {378surface->u.legacy.pipe_config = md->u.legacy.pipe_config;379surface->u.legacy.bankw = md->u.legacy.bankw;380surface->u.legacy.bankh = md->u.legacy.bankh;381surface->u.legacy.tile_split = md->u.legacy.tile_split;382surface->u.legacy.mtilea = md->u.legacy.mtilea;383surface->u.legacy.num_banks = md->u.legacy.num_banks;384385if (md->u.legacy.macrotile == RADEON_LAYOUT_TILED)386surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);387else if (md->u.legacy.microtile == RADEON_LAYOUT_TILED)388surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);389else390surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);391}392}393394static VkResult395radv_patch_image_dimensions(struct radv_device *device, struct radv_image *image,396const struct radv_image_create_info *create_info,397struct ac_surf_info *image_info)398{399unsigned width = image->info.width;400unsigned height = image->info.height;401402/*403* minigbm sometimes allocates bigger images which is going to result in404* weird strides and other properties. Lets be lenient where possible and405* fail it on GFX10 (as we cannot cope there).406*407* Example hack: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/1457777/408*/409if (create_info->bo_metadata &&410radv_is_valid_opaque_metadata(device, create_info->bo_metadata)) {411const struct radeon_bo_metadata *md = create_info->bo_metadata;412413if (device->physical_device->rad_info.chip_class >= GFX10) {414width = G_00A004_WIDTH_LO(md->metadata[3]) + (G_00A008_WIDTH_HI(md->metadata[4]) << 2) + 1;415height = G_00A008_HEIGHT(md->metadata[4]) + 1;416} else {417width = G_008F18_WIDTH(md->metadata[4]) + 1;418height = G_008F18_HEIGHT(md->metadata[4]) + 1;419}420}421422if (image->info.width == width && image->info.height == height)423return VK_SUCCESS;424425if (width < image->info.width || height < image->info.height) {426fprintf(stderr,427"The imported image has smaller dimensions than the internal\n"428"dimensions. Using it is going to fail badly, so we reject\n"429"this import.\n"430"(internal dimensions: %d x %d, external dimensions: %d x %d)\n",431image->info.width, image->info.height, width, height);432return VK_ERROR_INVALID_EXTERNAL_HANDLE;433} else if (device->physical_device->rad_info.chip_class >= GFX10) {434fprintf(stderr,435"Tried to import an image with inconsistent width on GFX10.\n"436"As GFX10 has no separate stride fields we cannot cope with\n"437"an inconsistency in width and will fail this import.\n"438"(internal dimensions: %d x %d, external dimensions: %d x %d)\n",439image->info.width, image->info.height, width, height);440return VK_ERROR_INVALID_EXTERNAL_HANDLE;441} else {442fprintf(stderr,443"Tried to import an image with inconsistent width on pre-GFX10.\n"444"As GFX10 has no separate stride fields we cannot cope with\n"445"an inconsistency and would fail on GFX10.\n"446"(internal dimensions: %d x %d, external dimensions: %d x %d)\n",447image->info.width, image->info.height, width, height);448}449image_info->width = width;450image_info->height = height;451452return VK_SUCCESS;453}454455static VkResult456radv_patch_image_from_extra_info(struct radv_device *device, struct radv_image *image,457const struct radv_image_create_info *create_info,458struct ac_surf_info *image_info)459{460VkResult result = radv_patch_image_dimensions(device, image, create_info, image_info);461if (result != VK_SUCCESS)462return result;463464for (unsigned plane = 0; plane < image->plane_count; ++plane) {465if (create_info->bo_metadata) {466radv_patch_surface_from_metadata(device, &image->planes[plane].surface,467create_info->bo_metadata);468}469470if (radv_surface_has_scanout(device, create_info)) {471image->planes[plane].surface.flags |= RADEON_SURF_SCANOUT;472if (device->instance->debug_flags & RADV_DEBUG_NO_DISPLAY_DCC)473image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC;474475image->info.surf_index = NULL;476}477}478return VK_SUCCESS;479}480481static uint64_t482radv_get_surface_flags(struct radv_device *device, const struct radv_image *image,483unsigned plane_id, const VkImageCreateInfo *pCreateInfo,484VkFormat image_format)485{486uint64_t flags;487unsigned array_mode = radv_choose_tiling(device, pCreateInfo, image_format);488VkFormat format = vk_format_get_plane_format(image_format, plane_id);489const struct util_format_description *desc = vk_format_description(format);490bool is_depth, is_stencil;491492is_depth = util_format_has_depth(desc);493is_stencil = util_format_has_stencil(desc);494495flags = RADEON_SURF_SET(array_mode, MODE);496497switch (pCreateInfo->imageType) {498case VK_IMAGE_TYPE_1D:499if (pCreateInfo->arrayLayers > 1)500flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);501else502flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);503break;504case VK_IMAGE_TYPE_2D:505if (pCreateInfo->arrayLayers > 1)506flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);507else508flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);509break;510case VK_IMAGE_TYPE_3D:511flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);512break;513default:514unreachable("unhandled image type");515}516517/* Required for clearing/initializing a specific layer on GFX8. */518flags |= RADEON_SURF_CONTIGUOUS_DCC_LAYERS;519520if (is_depth) {521flags |= RADEON_SURF_ZBUFFER;522523if (radv_use_htile_for_image(device, image) &&524!(device->instance->debug_flags & RADV_DEBUG_NO_HIZ)) {525if (radv_use_tc_compat_htile_for_image(device, pCreateInfo, image_format))526flags |= RADEON_SURF_TC_COMPATIBLE_HTILE;527} else {528flags |= RADEON_SURF_NO_HTILE;529}530}531532if (is_stencil)533flags |= RADEON_SURF_SBUFFER;534535if (device->physical_device->rad_info.chip_class >= GFX9 &&536pCreateInfo->imageType == VK_IMAGE_TYPE_3D &&537vk_format_get_blocksizebits(image_format) == 128 && vk_format_is_compressed(image_format))538flags |= RADEON_SURF_NO_RENDER_TARGET;539540if (!radv_use_dcc_for_image(device, image, pCreateInfo, image_format))541flags |= RADEON_SURF_DISABLE_DCC;542543if (!radv_use_fmask_for_image(device, image))544flags |= RADEON_SURF_NO_FMASK;545546if (pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {547flags |=548RADEON_SURF_PRT | RADEON_SURF_NO_FMASK | RADEON_SURF_NO_HTILE | RADEON_SURF_DISABLE_DCC;549}550551return flags;552}553554static inline unsigned555si_tile_mode_index(const struct radv_image_plane *plane, unsigned level, bool stencil)556{557if (stencil)558return plane->surface.u.legacy.zs.stencil_tiling_index[level];559else560return plane->surface.u.legacy.tiling_index[level];561}562563static unsigned564radv_map_swizzle(unsigned swizzle)565{566switch (swizzle) {567case PIPE_SWIZZLE_Y:568return V_008F0C_SQ_SEL_Y;569case PIPE_SWIZZLE_Z:570return V_008F0C_SQ_SEL_Z;571case PIPE_SWIZZLE_W:572return V_008F0C_SQ_SEL_W;573case PIPE_SWIZZLE_0:574return V_008F0C_SQ_SEL_0;575case PIPE_SWIZZLE_1:576return V_008F0C_SQ_SEL_1;577default: /* PIPE_SWIZZLE_X */578return V_008F0C_SQ_SEL_X;579}580}581582static void583radv_compose_swizzle(const struct util_format_description *desc, const VkComponentMapping *mapping,584enum pipe_swizzle swizzle[4])585{586if (desc->format == PIPE_FORMAT_R64_UINT || desc->format == PIPE_FORMAT_R64_SINT) {587/* 64-bit formats only support storage images and storage images588* require identity component mappings. We use 32-bit589* instructions to access 64-bit images, so we need a special590* case here.591*592* The zw components are 1,0 so that they can be easily be used593* by loads to create the w component, which has to be 0 for594* NULL descriptors.595*/596swizzle[0] = PIPE_SWIZZLE_X;597swizzle[1] = PIPE_SWIZZLE_Y;598swizzle[2] = PIPE_SWIZZLE_1;599swizzle[3] = PIPE_SWIZZLE_0;600} else if (!mapping) {601for (unsigned i = 0; i < 4; i++)602swizzle[i] = desc->swizzle[i];603} else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {604const unsigned char swizzle_xxxx[4] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_0, PIPE_SWIZZLE_0,605PIPE_SWIZZLE_1};606vk_format_compose_swizzles(mapping, swizzle_xxxx, swizzle);607} else {608vk_format_compose_swizzles(mapping, desc->swizzle, swizzle);609}610}611612static void613radv_make_buffer_descriptor(struct radv_device *device, struct radv_buffer *buffer,614VkFormat vk_format, unsigned offset, unsigned range, uint32_t *state)615{616const struct util_format_description *desc;617unsigned stride;618uint64_t gpu_address = radv_buffer_get_va(buffer->bo);619uint64_t va = gpu_address + buffer->offset;620unsigned num_format, data_format;621int first_non_void;622enum pipe_swizzle swizzle[4];623desc = vk_format_description(vk_format);624first_non_void = vk_format_get_first_non_void_channel(vk_format);625stride = desc->block.bits / 8;626627radv_compose_swizzle(desc, NULL, swizzle);628629va += offset;630state[0] = va;631state[1] = S_008F04_BASE_ADDRESS_HI(va >> 32) | S_008F04_STRIDE(stride);632633if (device->physical_device->rad_info.chip_class != GFX8 && stride) {634range /= stride;635}636637state[2] = range;638state[3] = S_008F0C_DST_SEL_X(radv_map_swizzle(swizzle[0])) |639S_008F0C_DST_SEL_Y(radv_map_swizzle(swizzle[1])) |640S_008F0C_DST_SEL_Z(radv_map_swizzle(swizzle[2])) |641S_008F0C_DST_SEL_W(radv_map_swizzle(swizzle[3]));642643if (device->physical_device->rad_info.chip_class >= GFX10) {644const struct gfx10_format *fmt = &gfx10_format_table[vk_format_to_pipe_format(vk_format)];645646/* OOB_SELECT chooses the out-of-bounds check:647* - 0: (index >= NUM_RECORDS) || (offset >= STRIDE)648* - 1: index >= NUM_RECORDS649* - 2: NUM_RECORDS == 0650* - 3: if SWIZZLE_ENABLE == 0: offset >= NUM_RECORDS651* else: swizzle_address >= NUM_RECORDS652*/653state[3] |= S_008F0C_FORMAT(fmt->img_format) |654S_008F0C_OOB_SELECT(V_008F0C_OOB_SELECT_STRUCTURED_WITH_OFFSET) |655S_008F0C_RESOURCE_LEVEL(1);656} else {657num_format = radv_translate_buffer_numformat(desc, first_non_void);658data_format = radv_translate_buffer_dataformat(desc, first_non_void);659660assert(data_format != V_008F0C_BUF_DATA_FORMAT_INVALID);661assert(num_format != ~0);662663state[3] |= S_008F0C_NUM_FORMAT(num_format) | S_008F0C_DATA_FORMAT(data_format);664}665}666667static void668si_set_mutable_tex_desc_fields(struct radv_device *device, struct radv_image *image,669const struct legacy_surf_level *base_level_info, unsigned plane_id,670unsigned base_level, unsigned first_level, unsigned block_width,671bool is_stencil, bool is_storage_image, bool disable_compression,672bool enable_write_compression, uint32_t *state)673{674struct radv_image_plane *plane = &image->planes[plane_id];675uint64_t gpu_address = image->bo ? radv_buffer_get_va(image->bo) + image->offset : 0;676uint64_t va = gpu_address;677enum chip_class chip_class = device->physical_device->rad_info.chip_class;678uint64_t meta_va = 0;679if (chip_class >= GFX9) {680if (is_stencil)681va += plane->surface.u.gfx9.zs.stencil_offset;682else683va += plane->surface.u.gfx9.surf_offset;684} else685va += (uint64_t)base_level_info->offset_256B * 256;686687state[0] = va >> 8;688if (chip_class >= GFX9 || base_level_info->mode == RADEON_SURF_MODE_2D)689state[0] |= plane->surface.tile_swizzle;690state[1] &= C_008F14_BASE_ADDRESS_HI;691state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40);692693if (chip_class >= GFX8) {694state[6] &= C_008F28_COMPRESSION_EN;695state[7] = 0;696if (!disable_compression && radv_dcc_enabled(image, first_level)) {697meta_va = gpu_address + plane->surface.meta_offset;698if (chip_class <= GFX8)699meta_va += plane->surface.u.legacy.color.dcc_level[base_level].dcc_offset;700701unsigned dcc_tile_swizzle = plane->surface.tile_swizzle << 8;702dcc_tile_swizzle &= (1 << plane->surface.meta_alignment_log2) - 1;703meta_va |= dcc_tile_swizzle;704} else if (!disable_compression && radv_image_is_tc_compat_htile(image)) {705meta_va = gpu_address + plane->surface.meta_offset;706}707708if (meta_va) {709state[6] |= S_008F28_COMPRESSION_EN(1);710if (chip_class <= GFX9)711state[7] = meta_va >> 8;712}713}714715if (chip_class >= GFX10) {716state[3] &= C_00A00C_SW_MODE;717718if (is_stencil) {719state[3] |= S_00A00C_SW_MODE(plane->surface.u.gfx9.zs.stencil_swizzle_mode);720} else {721state[3] |= S_00A00C_SW_MODE(plane->surface.u.gfx9.swizzle_mode);722}723724state[6] &= C_00A018_META_DATA_ADDRESS_LO & C_00A018_META_PIPE_ALIGNED;725726if (meta_va) {727struct gfx9_surf_meta_flags meta = {728.rb_aligned = 1,729.pipe_aligned = 1,730};731732if (!(plane->surface.flags & RADEON_SURF_Z_OR_SBUFFER))733meta = plane->surface.u.gfx9.color.dcc;734735if (radv_dcc_enabled(image, first_level) && is_storage_image && enable_write_compression)736state[6] |= S_00A018_WRITE_COMPRESS_ENABLE(1);737738state[6] |= S_00A018_META_PIPE_ALIGNED(meta.pipe_aligned) |739S_00A018_META_DATA_ADDRESS_LO(meta_va >> 8);740}741742state[7] = meta_va >> 16;743} else if (chip_class == GFX9) {744state[3] &= C_008F1C_SW_MODE;745state[4] &= C_008F20_PITCH;746747if (is_stencil) {748state[3] |= S_008F1C_SW_MODE(plane->surface.u.gfx9.zs.stencil_swizzle_mode);749state[4] |= S_008F20_PITCH(plane->surface.u.gfx9.zs.stencil_epitch);750} else {751state[3] |= S_008F1C_SW_MODE(plane->surface.u.gfx9.swizzle_mode);752state[4] |= S_008F20_PITCH(plane->surface.u.gfx9.epitch);753}754755state[5] &=756C_008F24_META_DATA_ADDRESS & C_008F24_META_PIPE_ALIGNED & C_008F24_META_RB_ALIGNED;757if (meta_va) {758struct gfx9_surf_meta_flags meta = {759.rb_aligned = 1,760.pipe_aligned = 1,761};762763if (!(plane->surface.flags & RADEON_SURF_Z_OR_SBUFFER))764meta = plane->surface.u.gfx9.color.dcc;765766state[5] |= S_008F24_META_DATA_ADDRESS(meta_va >> 40) |767S_008F24_META_PIPE_ALIGNED(meta.pipe_aligned) |768S_008F24_META_RB_ALIGNED(meta.rb_aligned);769}770} else {771/* GFX6-GFX8 */772unsigned pitch = base_level_info->nblk_x * block_width;773unsigned index = si_tile_mode_index(plane, base_level, is_stencil);774775state[3] &= C_008F1C_TILING_INDEX;776state[3] |= S_008F1C_TILING_INDEX(index);777state[4] &= C_008F20_PITCH;778state[4] |= S_008F20_PITCH(pitch - 1);779}780}781782static unsigned783radv_tex_dim(VkImageType image_type, VkImageViewType view_type, unsigned nr_layers,784unsigned nr_samples, bool is_storage_image, bool gfx9)785{786if (view_type == VK_IMAGE_VIEW_TYPE_CUBE || view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)787return is_storage_image ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_CUBE;788789/* GFX9 allocates 1D textures as 2D. */790if (gfx9 && image_type == VK_IMAGE_TYPE_1D)791image_type = VK_IMAGE_TYPE_2D;792switch (image_type) {793case VK_IMAGE_TYPE_1D:794return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_1D_ARRAY : V_008F1C_SQ_RSRC_IMG_1D;795case VK_IMAGE_TYPE_2D:796if (nr_samples > 1)797return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY : V_008F1C_SQ_RSRC_IMG_2D_MSAA;798else799return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_2D;800case VK_IMAGE_TYPE_3D:801if (view_type == VK_IMAGE_VIEW_TYPE_3D)802return V_008F1C_SQ_RSRC_IMG_3D;803else804return V_008F1C_SQ_RSRC_IMG_2D_ARRAY;805default:806unreachable("illegal image type");807}808}809810static unsigned811gfx9_border_color_swizzle(const struct util_format_description *desc)812{813unsigned bc_swizzle = V_008F20_BC_SWIZZLE_XYZW;814815if (desc->swizzle[3] == PIPE_SWIZZLE_X) {816/* For the pre-defined border color values (white, opaque817* black, transparent black), the only thing that matters is818* that the alpha channel winds up in the correct place819* (because the RGB channels are all the same) so either of820* these enumerations will work.821*/822if (desc->swizzle[2] == PIPE_SWIZZLE_Y)823bc_swizzle = V_008F20_BC_SWIZZLE_WZYX;824else825bc_swizzle = V_008F20_BC_SWIZZLE_WXYZ;826} else if (desc->swizzle[0] == PIPE_SWIZZLE_X) {827if (desc->swizzle[1] == PIPE_SWIZZLE_Y)828bc_swizzle = V_008F20_BC_SWIZZLE_XYZW;829else830bc_swizzle = V_008F20_BC_SWIZZLE_XWYZ;831} else if (desc->swizzle[1] == PIPE_SWIZZLE_X) {832bc_swizzle = V_008F20_BC_SWIZZLE_YXWZ;833} else if (desc->swizzle[2] == PIPE_SWIZZLE_X) {834bc_swizzle = V_008F20_BC_SWIZZLE_ZYXW;835}836837return bc_swizzle;838}839840bool841vi_alpha_is_on_msb(struct radv_device *device, VkFormat format)842{843const struct util_format_description *desc = vk_format_description(format);844845if (device->physical_device->rad_info.chip_class >= GFX10 && desc->nr_channels == 1)846return desc->swizzle[3] == PIPE_SWIZZLE_X;847848return radv_translate_colorswap(format, false) <= 1;849}850/**851* Build the sampler view descriptor for a texture (GFX10).852*/853static void854gfx10_make_texture_descriptor(struct radv_device *device, struct radv_image *image,855bool is_storage_image, VkImageViewType view_type, VkFormat vk_format,856const VkComponentMapping *mapping, unsigned first_level,857unsigned last_level, unsigned first_layer, unsigned last_layer,858unsigned width, unsigned height, unsigned depth, uint32_t *state,859uint32_t *fmask_state)860{861const struct util_format_description *desc;862enum pipe_swizzle swizzle[4];863unsigned img_format;864unsigned type;865866desc = vk_format_description(vk_format);867img_format = gfx10_format_table[vk_format_to_pipe_format(vk_format)].img_format;868869radv_compose_swizzle(desc, mapping, swizzle);870871type = radv_tex_dim(image->type, view_type, image->info.array_size, image->info.samples,872is_storage_image, device->physical_device->rad_info.chip_class == GFX9);873if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {874height = 1;875depth = image->info.array_size;876} else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {877if (view_type != VK_IMAGE_VIEW_TYPE_3D)878depth = image->info.array_size;879} else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)880depth = image->info.array_size / 6;881882state[0] = 0;883state[1] = S_00A004_FORMAT(img_format) | S_00A004_WIDTH_LO(width - 1);884state[2] = S_00A008_WIDTH_HI((width - 1) >> 2) | S_00A008_HEIGHT(height - 1) |885S_00A008_RESOURCE_LEVEL(1);886state[3] = S_00A00C_DST_SEL_X(radv_map_swizzle(swizzle[0])) |887S_00A00C_DST_SEL_Y(radv_map_swizzle(swizzle[1])) |888S_00A00C_DST_SEL_Z(radv_map_swizzle(swizzle[2])) |889S_00A00C_DST_SEL_W(radv_map_swizzle(swizzle[3])) |890S_00A00C_BASE_LEVEL(image->info.samples > 1 ? 0 : first_level) |891S_00A00C_LAST_LEVEL(image->info.samples > 1 ? util_logbase2(image->info.samples)892: last_level) |893S_00A00C_BC_SWIZZLE(gfx9_border_color_swizzle(desc)) | S_00A00C_TYPE(type);894/* Depth is the the last accessible layer on gfx9+. The hw doesn't need895* to know the total number of layers.896*/897state[4] = S_00A010_DEPTH(type == V_008F1C_SQ_RSRC_IMG_3D ? depth - 1 : last_layer) |898S_00A010_BASE_ARRAY(first_layer);899state[5] = S_00A014_ARRAY_PITCH(0) |900S_00A014_MAX_MIP(image->info.samples > 1 ? util_logbase2(image->info.samples)901: image->info.levels - 1) |902S_00A014_PERF_MOD(4);903state[6] = 0;904state[7] = 0;905906if (radv_dcc_enabled(image, first_level)) {907state[6] |= S_00A018_MAX_UNCOMPRESSED_BLOCK_SIZE(V_028C78_MAX_BLOCK_SIZE_256B) |908S_00A018_MAX_COMPRESSED_BLOCK_SIZE(909image->planes[0].surface.u.gfx9.color.dcc.max_compressed_block_size) |910S_00A018_ALPHA_IS_ON_MSB(vi_alpha_is_on_msb(device, vk_format));911}912913if (radv_image_get_iterate256(device, image)) {914state[6] |= S_00A018_ITERATE_256(1);915}916917/* Initialize the sampler view for FMASK. */918if (fmask_state) {919if (radv_image_has_fmask(image)) {920uint64_t gpu_address = radv_buffer_get_va(image->bo);921uint32_t format;922uint64_t va;923924assert(image->plane_count == 1);925926va = gpu_address + image->offset + image->planes[0].surface.fmask_offset;927928switch (image->info.samples) {929case 2:930format = V_008F0C_GFX10_FORMAT_FMASK8_S2_F2;931break;932case 4:933format = V_008F0C_GFX10_FORMAT_FMASK8_S4_F4;934break;935case 8:936format = V_008F0C_GFX10_FORMAT_FMASK32_S8_F8;937break;938default:939unreachable("invalid nr_samples");940}941942fmask_state[0] = (va >> 8) | image->planes[0].surface.fmask_tile_swizzle;943fmask_state[1] = S_00A004_BASE_ADDRESS_HI(va >> 40) | S_00A004_FORMAT(format) |944S_00A004_WIDTH_LO(width - 1);945fmask_state[2] = S_00A008_WIDTH_HI((width - 1) >> 2) | S_00A008_HEIGHT(height - 1) |946S_00A008_RESOURCE_LEVEL(1);947fmask_state[3] =948S_00A00C_DST_SEL_X(V_008F1C_SQ_SEL_X) | S_00A00C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |949S_00A00C_DST_SEL_Z(V_008F1C_SQ_SEL_X) | S_00A00C_DST_SEL_W(V_008F1C_SQ_SEL_X) |950S_00A00C_SW_MODE(image->planes[0].surface.u.gfx9.color.fmask_swizzle_mode) |951S_00A00C_TYPE(952radv_tex_dim(image->type, view_type, image->info.array_size, 0, false, false));953fmask_state[4] = S_00A010_DEPTH(last_layer) | S_00A010_BASE_ARRAY(first_layer);954fmask_state[5] = 0;955fmask_state[6] = S_00A018_META_PIPE_ALIGNED(1);956fmask_state[7] = 0;957958if (radv_image_is_tc_compat_cmask(image)) {959va = gpu_address + image->offset + image->planes[0].surface.cmask_offset;960961fmask_state[6] |= S_00A018_COMPRESSION_EN(1);962fmask_state[6] |= S_00A018_META_DATA_ADDRESS_LO(va >> 8);963fmask_state[7] |= va >> 16;964}965} else966memset(fmask_state, 0, 8 * 4);967}968}969970/**971* Build the sampler view descriptor for a texture (SI-GFX9)972*/973static void974si_make_texture_descriptor(struct radv_device *device, struct radv_image *image,975bool is_storage_image, VkImageViewType view_type, VkFormat vk_format,976const VkComponentMapping *mapping, unsigned first_level,977unsigned last_level, unsigned first_layer, unsigned last_layer,978unsigned width, unsigned height, unsigned depth, uint32_t *state,979uint32_t *fmask_state)980{981const struct util_format_description *desc;982enum pipe_swizzle swizzle[4];983int first_non_void;984unsigned num_format, data_format, type;985986desc = vk_format_description(vk_format);987988radv_compose_swizzle(desc, mapping, swizzle);989990first_non_void = vk_format_get_first_non_void_channel(vk_format);991992num_format = radv_translate_tex_numformat(vk_format, desc, first_non_void);993if (num_format == ~0) {994num_format = 0;995}996997data_format = radv_translate_tex_dataformat(vk_format, desc, first_non_void);998if (data_format == ~0) {999data_format = 0;1000}10011002/* S8 with either Z16 or Z32 HTILE need a special format. */1003if (device->physical_device->rad_info.chip_class == GFX9 && vk_format == VK_FORMAT_S8_UINT &&1004radv_image_is_tc_compat_htile(image)) {1005if (image->vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT)1006data_format = V_008F14_IMG_DATA_FORMAT_S8_32;1007else if (image->vk_format == VK_FORMAT_D16_UNORM_S8_UINT)1008data_format = V_008F14_IMG_DATA_FORMAT_S8_16;1009}1010type = radv_tex_dim(image->type, view_type, image->info.array_size, image->info.samples,1011is_storage_image, device->physical_device->rad_info.chip_class == GFX9);1012if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {1013height = 1;1014depth = image->info.array_size;1015} else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY || type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {1016if (view_type != VK_IMAGE_VIEW_TYPE_3D)1017depth = image->info.array_size;1018} else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)1019depth = image->info.array_size / 6;10201021state[0] = 0;1022state[1] = (S_008F14_DATA_FORMAT(data_format) | S_008F14_NUM_FORMAT(num_format));1023state[2] = (S_008F18_WIDTH(width - 1) | S_008F18_HEIGHT(height - 1) | S_008F18_PERF_MOD(4));1024state[3] = (S_008F1C_DST_SEL_X(radv_map_swizzle(swizzle[0])) |1025S_008F1C_DST_SEL_Y(radv_map_swizzle(swizzle[1])) |1026S_008F1C_DST_SEL_Z(radv_map_swizzle(swizzle[2])) |1027S_008F1C_DST_SEL_W(radv_map_swizzle(swizzle[3])) |1028S_008F1C_BASE_LEVEL(image->info.samples > 1 ? 0 : first_level) |1029S_008F1C_LAST_LEVEL(image->info.samples > 1 ? util_logbase2(image->info.samples)1030: last_level) |1031S_008F1C_TYPE(type));1032state[4] = 0;1033state[5] = S_008F24_BASE_ARRAY(first_layer);1034state[6] = 0;1035state[7] = 0;10361037if (device->physical_device->rad_info.chip_class == GFX9) {1038unsigned bc_swizzle = gfx9_border_color_swizzle(desc);10391040/* Depth is the last accessible layer on Gfx9.1041* The hw doesn't need to know the total number of layers.1042*/1043if (type == V_008F1C_SQ_RSRC_IMG_3D)1044state[4] |= S_008F20_DEPTH(depth - 1);1045else1046state[4] |= S_008F20_DEPTH(last_layer);10471048state[4] |= S_008F20_BC_SWIZZLE(bc_swizzle);1049state[5] |= S_008F24_MAX_MIP(image->info.samples > 1 ? util_logbase2(image->info.samples)1050: image->info.levels - 1);1051} else {1052state[3] |= S_008F1C_POW2_PAD(image->info.levels > 1);1053state[4] |= S_008F20_DEPTH(depth - 1);1054state[5] |= S_008F24_LAST_ARRAY(last_layer);1055}1056if (!(image->planes[0].surface.flags & RADEON_SURF_Z_OR_SBUFFER) &&1057image->planes[0].surface.meta_offset) {1058state[6] = S_008F28_ALPHA_IS_ON_MSB(vi_alpha_is_on_msb(device, vk_format));1059} else {1060/* The last dword is unused by hw. The shader uses it to clear1061* bits in the first dword of sampler state.1062*/1063if (device->physical_device->rad_info.chip_class <= GFX7 && image->info.samples <= 1) {1064if (first_level == last_level)1065state[7] = C_008F30_MAX_ANISO_RATIO;1066else1067state[7] = 0xffffffff;1068}1069}10701071/* Initialize the sampler view for FMASK. */1072if (fmask_state) {1073if (radv_image_has_fmask(image)) {1074uint32_t fmask_format;1075uint64_t gpu_address = radv_buffer_get_va(image->bo);1076uint64_t va;10771078assert(image->plane_count == 1);10791080va = gpu_address + image->offset + image->planes[0].surface.fmask_offset;10811082if (device->physical_device->rad_info.chip_class == GFX9) {1083fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK;1084switch (image->info.samples) {1085case 2:1086num_format = V_008F14_IMG_NUM_FORMAT_FMASK_8_2_2;1087break;1088case 4:1089num_format = V_008F14_IMG_NUM_FORMAT_FMASK_8_4_4;1090break;1091case 8:1092num_format = V_008F14_IMG_NUM_FORMAT_FMASK_32_8_8;1093break;1094default:1095unreachable("invalid nr_samples");1096}1097} else {1098switch (image->info.samples) {1099case 2:1100fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;1101break;1102case 4:1103fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S4_F4;1104break;1105case 8:1106fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;1107break;1108default:1109assert(0);1110fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;1111}1112num_format = V_008F14_IMG_NUM_FORMAT_UINT;1113}11141115fmask_state[0] = va >> 8;1116fmask_state[0] |= image->planes[0].surface.fmask_tile_swizzle;1117fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) | S_008F14_DATA_FORMAT(fmask_format) |1118S_008F14_NUM_FORMAT(num_format);1119fmask_state[2] = S_008F18_WIDTH(width - 1) | S_008F18_HEIGHT(height - 1);1120fmask_state[3] =1121S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) | S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |1122S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) | S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |1123S_008F1C_TYPE(1124radv_tex_dim(image->type, view_type, image->info.array_size, 0, false, false));1125fmask_state[4] = 0;1126fmask_state[5] = S_008F24_BASE_ARRAY(first_layer);1127fmask_state[6] = 0;1128fmask_state[7] = 0;11291130if (device->physical_device->rad_info.chip_class == GFX9) {1131fmask_state[3] |= S_008F1C_SW_MODE(image->planes[0].surface.u.gfx9.color.fmask_swizzle_mode);1132fmask_state[4] |= S_008F20_DEPTH(last_layer) |1133S_008F20_PITCH(image->planes[0].surface.u.gfx9.color.fmask_epitch);1134fmask_state[5] |= S_008F24_META_PIPE_ALIGNED(1) | S_008F24_META_RB_ALIGNED(1);11351136if (radv_image_is_tc_compat_cmask(image)) {1137va = gpu_address + image->offset + image->planes[0].surface.cmask_offset;11381139fmask_state[5] |= S_008F24_META_DATA_ADDRESS(va >> 40);1140fmask_state[6] |= S_008F28_COMPRESSION_EN(1);1141fmask_state[7] |= va >> 8;1142}1143} else {1144fmask_state[3] |=1145S_008F1C_TILING_INDEX(image->planes[0].surface.u.legacy.color.fmask.tiling_index);1146fmask_state[4] |=1147S_008F20_DEPTH(depth - 1) |1148S_008F20_PITCH(image->planes[0].surface.u.legacy.color.fmask.pitch_in_pixels - 1);1149fmask_state[5] |= S_008F24_LAST_ARRAY(last_layer);11501151if (radv_image_is_tc_compat_cmask(image)) {1152va = gpu_address + image->offset + image->planes[0].surface.cmask_offset;11531154fmask_state[6] |= S_008F28_COMPRESSION_EN(1);1155fmask_state[7] |= va >> 8;1156}1157}1158} else1159memset(fmask_state, 0, 8 * 4);1160}1161}11621163static void1164radv_make_texture_descriptor(struct radv_device *device, struct radv_image *image,1165bool is_storage_image, VkImageViewType view_type, VkFormat vk_format,1166const VkComponentMapping *mapping, unsigned first_level,1167unsigned last_level, unsigned first_layer, unsigned last_layer,1168unsigned width, unsigned height, unsigned depth, uint32_t *state,1169uint32_t *fmask_state)1170{1171if (device->physical_device->rad_info.chip_class >= GFX10) {1172gfx10_make_texture_descriptor(device, image, is_storage_image, view_type, vk_format, mapping,1173first_level, last_level, first_layer, last_layer, width, height,1174depth, state, fmask_state);1175} else {1176si_make_texture_descriptor(device, image, is_storage_image, view_type, vk_format, mapping,1177first_level, last_level, first_layer, last_layer, width, height,1178depth, state, fmask_state);1179}1180}11811182static void1183radv_query_opaque_metadata(struct radv_device *device, struct radv_image *image,1184struct radeon_bo_metadata *md)1185{1186static const VkComponentMapping fixedmapping;1187uint32_t desc[8];11881189assert(image->plane_count == 1);11901191radv_make_texture_descriptor(device, image, false, (VkImageViewType)image->type,1192image->vk_format, &fixedmapping, 0, image->info.levels - 1, 0,1193image->info.array_size - 1, image->info.width, image->info.height,1194image->info.depth, desc, NULL);11951196si_set_mutable_tex_desc_fields(device, image, &image->planes[0].surface.u.legacy.level[0], 0, 0,11970, image->planes[0].surface.blk_w, false, false, false, false,1198desc);11991200ac_surface_get_umd_metadata(&device->physical_device->rad_info, &image->planes[0].surface,1201image->info.levels, desc, &md->size_metadata, md->metadata);1202}12031204void1205radv_init_metadata(struct radv_device *device, struct radv_image *image,1206struct radeon_bo_metadata *metadata)1207{1208struct radeon_surf *surface = &image->planes[0].surface;12091210memset(metadata, 0, sizeof(*metadata));12111212if (device->physical_device->rad_info.chip_class >= GFX9) {1213uint64_t dcc_offset =1214image->offset +1215(surface->display_dcc_offset ? surface->display_dcc_offset : surface->meta_offset);1216metadata->u.gfx9.swizzle_mode = surface->u.gfx9.swizzle_mode;1217metadata->u.gfx9.dcc_offset_256b = dcc_offset >> 8;1218metadata->u.gfx9.dcc_pitch_max = surface->u.gfx9.color.display_dcc_pitch_max;1219metadata->u.gfx9.dcc_independent_64b_blocks = surface->u.gfx9.color.dcc.independent_64B_blocks;1220metadata->u.gfx9.dcc_independent_128b_blocks = surface->u.gfx9.color.dcc.independent_128B_blocks;1221metadata->u.gfx9.dcc_max_compressed_block_size =1222surface->u.gfx9.color.dcc.max_compressed_block_size;1223metadata->u.gfx9.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;1224} else {1225metadata->u.legacy.microtile = surface->u.legacy.level[0].mode >= RADEON_SURF_MODE_1D1226? RADEON_LAYOUT_TILED1227: RADEON_LAYOUT_LINEAR;1228metadata->u.legacy.macrotile = surface->u.legacy.level[0].mode >= RADEON_SURF_MODE_2D1229? RADEON_LAYOUT_TILED1230: RADEON_LAYOUT_LINEAR;1231metadata->u.legacy.pipe_config = surface->u.legacy.pipe_config;1232metadata->u.legacy.bankw = surface->u.legacy.bankw;1233metadata->u.legacy.bankh = surface->u.legacy.bankh;1234metadata->u.legacy.tile_split = surface->u.legacy.tile_split;1235metadata->u.legacy.mtilea = surface->u.legacy.mtilea;1236metadata->u.legacy.num_banks = surface->u.legacy.num_banks;1237metadata->u.legacy.stride = surface->u.legacy.level[0].nblk_x * surface->bpe;1238metadata->u.legacy.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;1239}1240radv_query_opaque_metadata(device, image, metadata);1241}12421243void1244radv_image_override_offset_stride(struct radv_device *device, struct radv_image *image,1245uint64_t offset, uint32_t stride)1246{1247ac_surface_override_offset_stride(&device->physical_device->rad_info, &image->planes[0].surface,1248image->info.levels, offset, stride);1249}12501251static void1252radv_image_alloc_single_sample_cmask(const struct radv_device *device,1253const struct radv_image *image, struct radeon_surf *surf)1254{1255if (!surf->cmask_size || surf->cmask_offset || surf->bpe > 8 || image->info.levels > 1 ||1256image->info.depth > 1 || radv_image_has_dcc(image) ||1257!radv_image_use_fast_clear_for_image(device, image) ||1258(image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT))1259return;12601261assert(image->info.storage_samples == 1);12621263surf->cmask_offset = align64(surf->total_size, 1 << surf->cmask_alignment_log2);1264surf->total_size = surf->cmask_offset + surf->cmask_size;1265surf->alignment_log2 = MAX2(surf->alignment_log2, surf->cmask_alignment_log2);1266}12671268static void1269radv_image_alloc_values(const struct radv_device *device, struct radv_image *image)1270{1271/* images with modifiers can be potentially imported */1272if (image->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)1273return;12741275if (radv_image_has_cmask(image) || radv_image_has_dcc(image)) {1276image->fce_pred_offset = image->size;1277image->size += 8 * image->info.levels;1278}12791280if (radv_image_use_dcc_predication(device, image)) {1281image->dcc_pred_offset = image->size;1282image->size += 8 * image->info.levels;1283}12841285if (radv_image_has_dcc(image) || radv_image_has_cmask(image) || radv_image_has_htile(image)) {1286image->clear_value_offset = image->size;1287image->size += 8 * image->info.levels;1288}12891290if (radv_image_is_tc_compat_htile(image) &&1291device->physical_device->rad_info.has_tc_compat_zrange_bug) {1292/* Metadata for the TC-compatible HTILE hardware bug which1293* have to be fixed by updating ZRANGE_PRECISION when doing1294* fast depth clears to 0.0f.1295*/1296image->tc_compat_zrange_offset = image->size;1297image->size += image->info.levels * 4;1298}1299}13001301/* Determine if the image is affected by the pipe misaligned metadata issue1302* which requires to invalidate L2.1303*/1304static bool1305radv_image_is_pipe_misaligned(const struct radv_device *device, const struct radv_image *image)1306{1307struct radeon_info *rad_info = &device->physical_device->rad_info;1308int log2_samples = util_logbase2(image->info.samples);13091310assert(rad_info->chip_class >= GFX10);13111312for (unsigned i = 0; i < image->plane_count; ++i) {1313VkFormat fmt = vk_format_get_plane_format(image->vk_format, i);1314int log2_bpp = util_logbase2(vk_format_get_blocksize(fmt));1315int log2_bpp_and_samples;13161317if (rad_info->chip_class >= GFX10_3) {1318log2_bpp_and_samples = log2_bpp + log2_samples;1319} else {1320if (vk_format_has_depth(image->vk_format) && image->info.array_size >= 8) {1321log2_bpp = 2;1322}13231324log2_bpp_and_samples = MIN2(6, log2_bpp + log2_samples);1325}13261327int num_pipes = G_0098F8_NUM_PIPES(rad_info->gb_addr_config);1328int overlap = MAX2(0, log2_bpp_and_samples + num_pipes - 8);13291330if (vk_format_has_depth(image->vk_format)) {1331if (radv_image_is_tc_compat_htile(image) && overlap) {1332return true;1333}1334} else {1335int max_compressed_frags = G_0098F8_MAX_COMPRESSED_FRAGS(rad_info->gb_addr_config);1336int log2_samples_frag_diff = MAX2(0, log2_samples - max_compressed_frags);1337int samples_overlap = MIN2(log2_samples, overlap);13381339/* TODO: It shouldn't be necessary if the image has DCC but1340* not readable by shader.1341*/1342if ((radv_image_has_dcc(image) || radv_image_is_tc_compat_cmask(image)) &&1343(samples_overlap > log2_samples_frag_diff)) {1344return true;1345}1346}1347}13481349return false;1350}13511352static bool1353radv_image_is_l2_coherent(const struct radv_device *device, const struct radv_image *image)1354{1355if (device->physical_device->rad_info.chip_class >= GFX10) {1356return !device->physical_device->rad_info.tcc_rb_non_coherent &&1357!radv_image_is_pipe_misaligned(device, image);1358} else if (device->physical_device->rad_info.chip_class == GFX9) {1359if (image->info.samples == 1 &&1360(image->usage &1361(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&1362!vk_format_has_stencil(image->vk_format)) {1363/* Single-sample color and single-sample depth1364* (not stencil) are coherent with shaders on1365* GFX9.1366*/1367return true;1368}1369}13701371return false;1372}13731374static void1375radv_image_reset_layout(struct radv_image *image)1376{1377image->size = 0;1378image->alignment = 1;13791380image->tc_compatible_cmask = 0;1381image->fce_pred_offset = image->dcc_pred_offset = 0;1382image->clear_value_offset = image->tc_compat_zrange_offset = 0;13831384for (unsigned i = 0; i < image->plane_count; ++i) {1385VkFormat format = vk_format_get_plane_format(image->vk_format, i);13861387uint64_t flags = image->planes[i].surface.flags;1388uint64_t modifier = image->planes[i].surface.modifier;1389memset(image->planes + i, 0, sizeof(image->planes[i]));13901391image->planes[i].surface.flags = flags;1392image->planes[i].surface.modifier = modifier;1393image->planes[i].surface.blk_w = vk_format_get_blockwidth(format);1394image->planes[i].surface.blk_h = vk_format_get_blockheight(format);1395image->planes[i].surface.bpe = vk_format_get_blocksize(vk_format_depth_only(format));13961397/* align byte per element on dword */1398if (image->planes[i].surface.bpe == 3) {1399image->planes[i].surface.bpe = 4;1400}1401}1402}14031404VkResult1405radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info,1406const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info,1407struct radv_image *image)1408{1409/* Clear the pCreateInfo pointer so we catch issues in the delayed case when we test in the1410* common internal case. */1411create_info.vk_info = NULL;14121413struct ac_surf_info image_info = image->info;1414VkResult result = radv_patch_image_from_extra_info(device, image, &create_info, &image_info);1415if (result != VK_SUCCESS)1416return result;14171418assert(!mod_info || mod_info->drmFormatModifierPlaneCount >= image->plane_count);14191420radv_image_reset_layout(image);14211422for (unsigned plane = 0; plane < image->plane_count; ++plane) {1423struct ac_surf_info info = image_info;1424uint64_t offset;1425unsigned stride;14261427info.width = vk_format_get_plane_width(image->vk_format, plane, info.width);1428info.height = vk_format_get_plane_height(image->vk_format, plane, info.height);14291430if (create_info.no_metadata_planes || image->plane_count > 1) {1431image->planes[plane].surface.flags |=1432RADEON_SURF_DISABLE_DCC | RADEON_SURF_NO_FMASK | RADEON_SURF_NO_HTILE;1433}14341435device->ws->surface_init(device->ws, &info, &image->planes[plane].surface);14361437if (create_info.bo_metadata && !mod_info &&1438!ac_surface_set_umd_metadata(&device->physical_device->rad_info,1439&image->planes[plane].surface, image_info.storage_samples,1440image_info.levels, create_info.bo_metadata->size_metadata,1441create_info.bo_metadata->metadata))1442return VK_ERROR_INVALID_EXTERNAL_HANDLE;14431444if (!create_info.no_metadata_planes && !create_info.bo_metadata && image->plane_count == 1 &&1445!mod_info)1446radv_image_alloc_single_sample_cmask(device, image, &image->planes[plane].surface);14471448if (mod_info) {1449if (mod_info->pPlaneLayouts[plane].rowPitch % image->planes[plane].surface.bpe ||1450!mod_info->pPlaneLayouts[plane].rowPitch)1451return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;14521453offset = mod_info->pPlaneLayouts[plane].offset;1454stride = mod_info->pPlaneLayouts[plane].rowPitch / image->planes[plane].surface.bpe;1455} else {1456offset = align64(image->size, 1 << image->planes[plane].surface.alignment_log2);1457stride = 0; /* 0 means no override */1458}14591460if (!ac_surface_override_offset_stride(&device->physical_device->rad_info,1461&image->planes[plane].surface, image->info.levels,1462offset, stride))1463return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;14641465/* Validate DCC offsets in modifier layout. */1466if (image->plane_count == 1 && mod_info) {1467unsigned mem_planes = ac_surface_get_nplanes(&image->planes[plane].surface);1468if (mod_info->drmFormatModifierPlaneCount != mem_planes)1469return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;14701471for (unsigned i = 1; i < mem_planes; ++i) {1472if (ac_surface_get_plane_offset(device->physical_device->rad_info.chip_class,1473&image->planes[plane].surface, i,14740) != mod_info->pPlaneLayouts[i].offset)1475return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;1476}1477}14781479image->size = MAX2(image->size, offset + image->planes[plane].surface.total_size);1480image->alignment = MAX2(image->alignment, 1 << image->planes[plane].surface.alignment_log2);14811482image->planes[plane].format = vk_format_get_plane_format(image->vk_format, plane);1483}14841485image->tc_compatible_cmask =1486radv_image_has_cmask(image) && radv_use_tc_compat_cmask_for_image(device, image);14871488radv_image_alloc_values(device, image);14891490assert(image->planes[0].surface.surf_size);1491assert(image->planes[0].surface.modifier == DRM_FORMAT_MOD_INVALID ||1492ac_modifier_has_dcc(image->planes[0].surface.modifier) == radv_image_has_dcc(image));1493return VK_SUCCESS;1494}14951496static void1497radv_destroy_image(struct radv_device *device, const VkAllocationCallbacks *pAllocator,1498struct radv_image *image)1499{1500if ((image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && image->bo)1501device->ws->buffer_destroy(device->ws, image->bo);15021503if (image->owned_memory != VK_NULL_HANDLE) {1504RADV_FROM_HANDLE(radv_device_memory, mem, image->owned_memory);1505radv_free_memory(device, pAllocator, mem);1506}15071508vk_object_base_finish(&image->base);1509vk_free2(&device->vk.alloc, pAllocator, image);1510}15111512static void1513radv_image_print_info(struct radv_device *device, struct radv_image *image)1514{1515fprintf(stderr, "Image:\n");1516fprintf(stderr,1517" Info: size=%" PRIu64 ", alignment=%" PRIu32 ", "1518"width=%" PRIu32 ", height=%" PRIu32 ", "1519"offset=%" PRIu64 ", array_size=%" PRIu32 "\n",1520image->size, image->alignment, image->info.width, image->info.height, image->offset,1521image->info.array_size);1522for (unsigned i = 0; i < image->plane_count; ++i) {1523const struct radv_image_plane *plane = &image->planes[i];1524const struct radeon_surf *surf = &plane->surface;1525const struct util_format_description *desc = vk_format_description(plane->format);1526uint64_t offset = ac_surface_get_plane_offset(device->physical_device->rad_info.chip_class,1527&plane->surface, 0, 0);15281529fprintf(stderr, " Plane[%u]: vkformat=%s, offset=%" PRIu64 "\n", i, desc->name, offset);15301531ac_surface_print_info(stderr, &device->physical_device->rad_info, surf);1532}1533}15341535/**1536* Determine if the given image can be fast cleared.1537*/1538static bool1539radv_image_can_fast_clear(const struct radv_device *device, const struct radv_image *image)1540{1541if (device->instance->debug_flags & RADV_DEBUG_NO_FAST_CLEARS)1542return false;15431544if (vk_format_is_color(image->vk_format)) {1545if (!radv_image_has_cmask(image) && !radv_image_has_dcc(image))1546return false;15471548/* RB+ doesn't work with CMASK fast clear on Stoney. */1549if (!radv_image_has_dcc(image) && device->physical_device->rad_info.family == CHIP_STONEY)1550return false;1551} else {1552if (!radv_image_has_htile(image))1553return false;1554}15551556/* Do not fast clears 3D images. */1557if (image->type == VK_IMAGE_TYPE_3D)1558return false;15591560return true;1561}15621563static uint64_t1564radv_select_modifier(const struct radv_device *dev, VkFormat format,1565const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list)1566{1567const struct radv_physical_device *pdev = dev->physical_device;1568unsigned mod_count;15691570assert(mod_list->drmFormatModifierCount);15711572/* We can allow everything here as it does not affect order and the application1573* is only allowed to specify modifiers that we support. */1574const struct ac_modifier_options modifier_options = {1575.dcc = true,1576.dcc_retile = true,1577};15781579ac_get_supported_modifiers(&pdev->rad_info, &modifier_options, vk_format_to_pipe_format(format),1580&mod_count, NULL);15811582uint64_t *mods = calloc(mod_count, sizeof(*mods));15831584/* If allocations fail, fall back to a dumber solution. */1585if (!mods)1586return mod_list->pDrmFormatModifiers[0];15871588ac_get_supported_modifiers(&pdev->rad_info, &modifier_options, vk_format_to_pipe_format(format),1589&mod_count, mods);15901591for (unsigned i = 0; i < mod_count; ++i) {1592for (uint32_t j = 0; j < mod_list->drmFormatModifierCount; ++j) {1593if (mods[i] == mod_list->pDrmFormatModifiers[j]) {1594free(mods);1595return mod_list->pDrmFormatModifiers[j];1596}1597}1598}1599unreachable("App specified an invalid modifier");1600}16011602VkResult1603radv_image_create(VkDevice _device, const struct radv_image_create_info *create_info,1604const VkAllocationCallbacks *alloc, VkImage *pImage)1605{1606RADV_FROM_HANDLE(radv_device, device, _device);1607const VkImageCreateInfo *pCreateInfo = create_info->vk_info;1608uint64_t modifier = DRM_FORMAT_MOD_INVALID;1609struct radv_image *image = NULL;1610VkFormat format = radv_select_android_external_format(pCreateInfo->pNext, pCreateInfo->format);1611const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list =1612vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);1613const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod =1614vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);1615assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);16161617const unsigned plane_count = vk_format_get_plane_count(format);1618const size_t image_struct_size = sizeof(*image) + sizeof(struct radv_image_plane) * plane_count;16191620radv_assert(pCreateInfo->mipLevels > 0);1621radv_assert(pCreateInfo->arrayLayers > 0);1622radv_assert(pCreateInfo->samples > 0);1623radv_assert(pCreateInfo->extent.width > 0);1624radv_assert(pCreateInfo->extent.height > 0);1625radv_assert(pCreateInfo->extent.depth > 0);16261627image =1628vk_zalloc2(&device->vk.alloc, alloc, image_struct_size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);1629if (!image)1630return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);16311632vk_object_base_init(&device->vk, &image->base, VK_OBJECT_TYPE_IMAGE);16331634image->type = pCreateInfo->imageType;1635image->info.width = pCreateInfo->extent.width;1636image->info.height = pCreateInfo->extent.height;1637image->info.depth = pCreateInfo->extent.depth;1638image->info.samples = pCreateInfo->samples;1639image->info.storage_samples = pCreateInfo->samples;1640image->info.array_size = pCreateInfo->arrayLayers;1641image->info.levels = pCreateInfo->mipLevels;1642image->info.num_channels = vk_format_get_nr_components(format);16431644image->vk_format = format;1645image->tiling = pCreateInfo->tiling;1646image->usage = pCreateInfo->usage;1647image->flags = pCreateInfo->flags;1648image->plane_count = plane_count;16491650image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;1651if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {1652for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i)1653if (pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_EXTERNAL ||1654pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_FOREIGN_EXT)1655image->queue_family_mask |= (1u << RADV_MAX_QUEUE_FAMILIES) - 1u;1656else1657image->queue_family_mask |= 1u << pCreateInfo->pQueueFamilyIndices[i];1658}16591660const VkExternalMemoryImageCreateInfo *external_info =1661vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO);16621663image->shareable = external_info;1664if (!vk_format_is_depth_or_stencil(format) && !image->shareable &&1665!(image->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) &&1666pCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {1667image->info.surf_index = &device->image_mrt_offset_counter;1668}16691670if (mod_list)1671modifier = radv_select_modifier(device, format, mod_list);1672else if (explicit_mod)1673modifier = explicit_mod->drmFormatModifier;16741675for (unsigned plane = 0; plane < image->plane_count; ++plane) {1676image->planes[plane].surface.flags =1677radv_get_surface_flags(device, image, plane, pCreateInfo, format);1678image->planes[plane].surface.modifier = modifier;1679}16801681bool delay_layout =1682external_info && (external_info->handleTypes &1683VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);16841685if (delay_layout) {1686*pImage = radv_image_to_handle(image);1687assert(!(image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT));1688return VK_SUCCESS;1689}16901691VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, image);1692if (result != VK_SUCCESS) {1693radv_destroy_image(device, alloc, image);1694return result;1695}16961697if (image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {1698image->alignment = MAX2(image->alignment, 4096);1699image->size = align64(image->size, image->alignment);1700image->offset = 0;17011702result =1703device->ws->buffer_create(device->ws, image->size, image->alignment, 0,1704RADEON_FLAG_VIRTUAL, RADV_BO_PRIORITY_VIRTUAL, 0, &image->bo);1705if (result != VK_SUCCESS) {1706radv_destroy_image(device, alloc, image);1707return vk_error(device->instance, result);1708}1709}1710image->l2_coherent = radv_image_is_l2_coherent(device, image);17111712if (device->instance->debug_flags & RADV_DEBUG_IMG) {1713radv_image_print_info(device, image);1714}17151716*pImage = radv_image_to_handle(image);17171718return VK_SUCCESS;1719}17201721static void1722radv_image_view_make_descriptor(struct radv_image_view *iview, struct radv_device *device,1723VkFormat vk_format, const VkComponentMapping *components,1724bool is_storage_image, bool disable_compression,1725bool enable_compression, unsigned plane_id,1726unsigned descriptor_plane_id)1727{1728struct radv_image *image = iview->image;1729struct radv_image_plane *plane = &image->planes[plane_id];1730bool is_stencil = iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT;1731uint32_t blk_w;1732union radv_descriptor *descriptor;1733uint32_t hw_level = 0;17341735if (is_storage_image) {1736descriptor = &iview->storage_descriptor;1737} else {1738descriptor = &iview->descriptor;1739}17401741assert(vk_format_get_plane_count(vk_format) == 1);1742assert(plane->surface.blk_w % vk_format_get_blockwidth(plane->format) == 0);1743blk_w = plane->surface.blk_w / vk_format_get_blockwidth(plane->format) *1744vk_format_get_blockwidth(vk_format);17451746if (device->physical_device->rad_info.chip_class >= GFX9)1747hw_level = iview->base_mip;1748radv_make_texture_descriptor(1749device, image, is_storage_image, iview->type, vk_format, components, hw_level,1750hw_level + iview->level_count - 1, iview->base_layer,1751iview->base_layer + iview->layer_count - 1,1752vk_format_get_plane_width(image->vk_format, plane_id, iview->extent.width),1753vk_format_get_plane_height(image->vk_format, plane_id, iview->extent.height),1754iview->extent.depth, descriptor->plane_descriptors[descriptor_plane_id],1755descriptor_plane_id ? NULL : descriptor->fmask_descriptor);17561757const struct legacy_surf_level *base_level_info = NULL;1758if (device->physical_device->rad_info.chip_class <= GFX9) {1759if (is_stencil)1760base_level_info = &plane->surface.u.legacy.zs.stencil_level[iview->base_mip];1761else1762base_level_info = &plane->surface.u.legacy.level[iview->base_mip];1763}17641765bool enable_write_compression = radv_image_use_dcc_image_stores(device, image);1766if (is_storage_image && !(enable_write_compression || enable_compression))1767disable_compression = true;1768si_set_mutable_tex_desc_fields(device, image, base_level_info, plane_id, iview->base_mip,1769iview->base_mip, blk_w, is_stencil, is_storage_image,1770disable_compression, enable_write_compression,1771descriptor->plane_descriptors[descriptor_plane_id]);1772}17731774static unsigned1775radv_plane_from_aspect(VkImageAspectFlags mask)1776{1777switch (mask) {1778case VK_IMAGE_ASPECT_PLANE_1_BIT:1779case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:1780return 1;1781case VK_IMAGE_ASPECT_PLANE_2_BIT:1782case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:1783return 2;1784case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT:1785return 3;1786default:1787return 0;1788}1789}17901791VkFormat1792radv_get_aspect_format(struct radv_image *image, VkImageAspectFlags mask)1793{1794switch (mask) {1795case VK_IMAGE_ASPECT_PLANE_0_BIT:1796return image->planes[0].format;1797case VK_IMAGE_ASPECT_PLANE_1_BIT:1798return image->planes[1].format;1799case VK_IMAGE_ASPECT_PLANE_2_BIT:1800return image->planes[2].format;1801case VK_IMAGE_ASPECT_STENCIL_BIT:1802return vk_format_stencil_only(image->vk_format);1803case VK_IMAGE_ASPECT_DEPTH_BIT:1804return vk_format_depth_only(image->vk_format);1805case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:1806return vk_format_depth_only(image->vk_format);1807default:1808return image->vk_format;1809}1810}18111812/**1813* Determine if the given image view can be fast cleared.1814*/1815static bool1816radv_image_view_can_fast_clear(const struct radv_device *device,1817const struct radv_image_view *iview)1818{1819struct radv_image *image;18201821if (!iview)1822return false;1823image = iview->image;18241825/* Only fast clear if the image itself can be fast cleared. */1826if (!radv_image_can_fast_clear(device, image))1827return false;18281829/* Only fast clear if all layers are bound. */1830if (iview->base_layer > 0 || iview->layer_count != image->info.array_size)1831return false;18321833/* Only fast clear if the view covers the whole image. */1834if (!radv_image_extent_compare(image, &iview->extent))1835return false;18361837return true;1838}18391840void1841radv_image_view_init(struct radv_image_view *iview, struct radv_device *device,1842const VkImageViewCreateInfo *pCreateInfo,1843const struct radv_image_view_extra_create_info *extra_create_info)1844{1845RADV_FROM_HANDLE(radv_image, image, pCreateInfo->image);1846const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;1847uint32_t plane_count = 1;18481849switch (image->type) {1850case VK_IMAGE_TYPE_1D:1851case VK_IMAGE_TYPE_2D:1852assert(range->baseArrayLayer + radv_get_layerCount(image, range) - 1 <=1853image->info.array_size);1854break;1855case VK_IMAGE_TYPE_3D:1856assert(range->baseArrayLayer + radv_get_layerCount(image, range) - 1 <=1857radv_minify(image->info.depth, range->baseMipLevel));1858break;1859default:1860unreachable("bad VkImageType");1861}1862iview->image = image;1863iview->type = pCreateInfo->viewType;1864iview->plane_id = radv_plane_from_aspect(pCreateInfo->subresourceRange.aspectMask);1865iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;1866iview->base_layer = range->baseArrayLayer;1867iview->layer_count = radv_get_layerCount(image, range);1868iview->base_mip = range->baseMipLevel;1869iview->level_count = radv_get_levelCount(image, range);18701871iview->vk_format = pCreateInfo->format;18721873/* If the image has an Android external format, pCreateInfo->format will be1874* VK_FORMAT_UNDEFINED. */1875if (iview->vk_format == VK_FORMAT_UNDEFINED)1876iview->vk_format = image->vk_format;18771878if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {1879iview->vk_format = vk_format_stencil_only(iview->vk_format);1880} else if (iview->aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {1881iview->vk_format = vk_format_depth_only(iview->vk_format);1882}18831884if (device->physical_device->rad_info.chip_class >= GFX9) {1885iview->extent = (VkExtent3D){1886.width = image->info.width,1887.height = image->info.height,1888.depth = image->info.depth,1889};1890} else {1891iview->extent = (VkExtent3D){1892.width = radv_minify(image->info.width, range->baseMipLevel),1893.height = radv_minify(image->info.height, range->baseMipLevel),1894.depth = radv_minify(image->info.depth, range->baseMipLevel),1895};1896}18971898if (iview->vk_format != image->planes[iview->plane_id].format) {1899unsigned view_bw = vk_format_get_blockwidth(iview->vk_format);1900unsigned view_bh = vk_format_get_blockheight(iview->vk_format);1901unsigned img_bw = vk_format_get_blockwidth(image->vk_format);1902unsigned img_bh = vk_format_get_blockheight(image->vk_format);19031904iview->extent.width = round_up_u32(iview->extent.width * view_bw, img_bw);1905iview->extent.height = round_up_u32(iview->extent.height * view_bh, img_bh);19061907/* Comment ported from amdvlk -1908* If we have the following image:1909* Uncompressed pixels Compressed block sizes (4x4)1910* mip0: 22 x 22 6 x 61911* mip1: 11 x 11 3 x 31912* mip2: 5 x 5 2 x 21913* mip3: 2 x 2 1 x 11914* mip4: 1 x 1 1 x 11915*1916* On GFX9 the descriptor is always programmed with the WIDTH and HEIGHT of the base level and1917* the HW is calculating the degradation of the block sizes down the mip-chain as follows1918* (straight-up divide-by-two integer math): mip0: 6x6 mip1: 3x3 mip2: 1x1 mip3: 1x11919*1920* This means that mip2 will be missing texels.1921*1922* Fix this by calculating the base mip's width and height, then convert1923* that, and round it back up to get the level 0 size. Clamp the1924* converted size between the original values, and the physical extent1925* of the base mipmap.1926*1927* On GFX10 we have to take care to not go over the physical extent1928* of the base mipmap as otherwise the GPU computes a different layout.1929* Note that the GPU does use the same base-mip dimensions for both a1930* block compatible format and the compressed format, so even if we take1931* the plain converted dimensions the physical layout is correct.1932*/1933if (device->physical_device->rad_info.chip_class >= GFX9 &&1934vk_format_is_compressed(image->vk_format) && !vk_format_is_compressed(iview->vk_format)) {1935/* If we have multiple levels in the view we should ideally take the last level,1936* but the mip calculation has a max(..., 1) so walking back to the base mip in an1937* useful way is hard. */1938if (iview->level_count > 1) {1939iview->extent.width = iview->image->planes[0].surface.u.gfx9.base_mip_width;1940iview->extent.height = iview->image->planes[0].surface.u.gfx9.base_mip_height;1941} else {1942unsigned lvl_width = radv_minify(image->info.width, range->baseMipLevel);1943unsigned lvl_height = radv_minify(image->info.height, range->baseMipLevel);19441945lvl_width = round_up_u32(lvl_width * view_bw, img_bw);1946lvl_height = round_up_u32(lvl_height * view_bh, img_bh);19471948lvl_width <<= range->baseMipLevel;1949lvl_height <<= range->baseMipLevel;19501951iview->extent.width = CLAMP(lvl_width, iview->extent.width,1952iview->image->planes[0].surface.u.gfx9.base_mip_width);1953iview->extent.height = CLAMP(lvl_height, iview->extent.height,1954iview->image->planes[0].surface.u.gfx9.base_mip_height);1955}1956}1957}19581959iview->support_fast_clear = radv_image_view_can_fast_clear(device, iview);19601961if (vk_format_get_plane_count(image->vk_format) > 1 &&1962iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) {1963plane_count = vk_format_get_plane_count(iview->vk_format);1964}19651966bool disable_compression = extra_create_info ? extra_create_info->disable_compression : false;1967bool enable_compression = extra_create_info ? extra_create_info->enable_compression : false;1968for (unsigned i = 0; i < plane_count; ++i) {1969VkFormat format = vk_format_get_plane_format(iview->vk_format, i);1970radv_image_view_make_descriptor(iview, device, format, &pCreateInfo->components, false,1971disable_compression, enable_compression, iview->plane_id + i,1972i);1973radv_image_view_make_descriptor(iview, device, format, &pCreateInfo->components, true,1974disable_compression, enable_compression, iview->plane_id + i,1975i);1976}1977}19781979bool1980radv_layout_is_htile_compressed(const struct radv_device *device, const struct radv_image *image,1981VkImageLayout layout, bool in_render_loop, unsigned queue_mask)1982{1983switch (layout) {1984case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:1985case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR:1986case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR:1987return radv_image_has_htile(image);1988case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:1989return radv_image_has_htile(image) && queue_mask == (1u << RADV_QUEUE_GENERAL);1990case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:1991case VK_IMAGE_LAYOUT_GENERAL:1992/* It should be safe to enable TC-compat HTILE with1993* VK_IMAGE_LAYOUT_GENERAL if we are not in a render loop and1994* if the image doesn't have the storage bit set. This1995* improves performance for apps that use GENERAL for the main1996* depth pass because this allows compression and this reduces1997* the number of decompressions from/to GENERAL.1998*/1999/* FIXME: Enabling TC-compat HTILE in GENERAL on the compute2000* queue is likely broken for eg. depth/stencil copies.2001*/2002if (radv_image_is_tc_compat_htile(image) && queue_mask & (1u << RADV_QUEUE_GENERAL) &&2003!in_render_loop && !device->instance->disable_tc_compat_htile_in_general) {2004/* GFX10+ supports compressed writes to HTILE. */2005return device->physical_device->rad_info.chip_class >= GFX10 ||2006!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT);2007} else {2008return false;2009}2010case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:2011if (radv_image_is_tc_compat_htile(image) ||2012(radv_image_has_htile(image) &&2013!(image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)))) {2014/* Keep HTILE compressed if the image is only going to2015* be used as a depth/stencil read-only attachment.2016*/2017return true;2018} else {2019return false;2020}2021break;2022default:2023return radv_image_is_tc_compat_htile(image);2024}2025}20262027bool2028radv_layout_can_fast_clear(const struct radv_device *device, const struct radv_image *image,2029unsigned level, VkImageLayout layout, bool in_render_loop,2030unsigned queue_mask)2031{2032if (radv_dcc_enabled(image, level) &&2033!radv_layout_dcc_compressed(device, image, level, layout, in_render_loop, queue_mask))2034return false;20352036if (!(image->usage & RADV_IMAGE_USAGE_WRITE_BITS))2037return false;20382039return layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL &&2040queue_mask == (1u << RADV_QUEUE_GENERAL);2041}20422043bool2044radv_layout_dcc_compressed(const struct radv_device *device, const struct radv_image *image,2045unsigned level, VkImageLayout layout, bool in_render_loop,2046unsigned queue_mask)2047{2048if (!radv_dcc_enabled(image, level))2049return false;20502051if (image->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && queue_mask & (1u << RADV_QUEUE_FOREIGN))2052return true;20532054/* If the image is read-only, we can always just keep it compressed */2055if (!(image->usage & RADV_IMAGE_USAGE_WRITE_BITS))2056return true;20572058/* Don't compress compute transfer dst when image stores are not supported. */2059if ((layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || layout == VK_IMAGE_LAYOUT_GENERAL) &&2060(queue_mask & (1u << RADV_QUEUE_COMPUTE)) && !radv_image_use_dcc_image_stores(device, image))2061return false;20622063return device->physical_device->rad_info.chip_class >= GFX10 || layout != VK_IMAGE_LAYOUT_GENERAL;2064}20652066bool2067radv_layout_fmask_compressed(const struct radv_device *device, const struct radv_image *image,2068VkImageLayout layout, unsigned queue_mask)2069{2070if (!radv_image_has_fmask(image))2071return false;20722073/* Don't compress compute transfer dst because image stores ignore FMASK and it needs to be2074* expanded before.2075*/2076if ((layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || layout == VK_IMAGE_LAYOUT_GENERAL) &&2077(queue_mask & (1u << RADV_QUEUE_COMPUTE)))2078return false;20792080/* Only compress concurrent images if TC-compat CMASK is enabled (no FMASK decompression). */2081return layout != VK_IMAGE_LAYOUT_GENERAL &&2082(queue_mask == (1u << RADV_QUEUE_GENERAL) || radv_image_is_tc_compat_cmask(image));2083}20842085unsigned2086radv_image_queue_family_mask(const struct radv_image *image, uint32_t family, uint32_t queue_family)2087{2088if (!image->exclusive)2089return image->queue_family_mask;2090if (family == VK_QUEUE_FAMILY_EXTERNAL || family == VK_QUEUE_FAMILY_FOREIGN_EXT)2091return ((1u << RADV_MAX_QUEUE_FAMILIES) - 1u) | (1u << RADV_QUEUE_FOREIGN);2092if (family == VK_QUEUE_FAMILY_IGNORED)2093return 1u << queue_family;2094return 1u << family;2095}20962097VkResult2098radv_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,2099const VkAllocationCallbacks *pAllocator, VkImage *pImage)2100{2101#ifdef ANDROID2102const VkNativeBufferANDROID *gralloc_info =2103vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);21042105if (gralloc_info)2106return radv_image_from_gralloc(device, pCreateInfo, gralloc_info, pAllocator, pImage);2107#endif21082109const struct wsi_image_create_info *wsi_info =2110vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);2111bool scanout = wsi_info && wsi_info->scanout;21122113return radv_image_create(device,2114&(struct radv_image_create_info){2115.vk_info = pCreateInfo,2116.scanout = scanout,2117},2118pAllocator, pImage);2119}21202121void2122radv_DestroyImage(VkDevice _device, VkImage _image, const VkAllocationCallbacks *pAllocator)2123{2124RADV_FROM_HANDLE(radv_device, device, _device);2125RADV_FROM_HANDLE(radv_image, image, _image);21262127if (!image)2128return;21292130radv_destroy_image(device, pAllocator, image);2131}21322133void2134radv_GetImageSubresourceLayout(VkDevice _device, VkImage _image,2135const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout)2136{2137RADV_FROM_HANDLE(radv_image, image, _image);2138RADV_FROM_HANDLE(radv_device, device, _device);2139int level = pSubresource->mipLevel;2140int layer = pSubresource->arrayLayer;21412142unsigned plane_id = 0;2143if (vk_format_get_plane_count(image->vk_format) > 1)2144plane_id = radv_plane_from_aspect(pSubresource->aspectMask);21452146struct radv_image_plane *plane = &image->planes[plane_id];2147struct radeon_surf *surface = &plane->surface;21482149if (image->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {2150unsigned mem_plane_id = radv_plane_from_aspect(pSubresource->aspectMask);21512152assert(level == 0);2153assert(layer == 0);21542155pLayout->offset = ac_surface_get_plane_offset(device->physical_device->rad_info.chip_class,2156surface, mem_plane_id, 0);2157pLayout->rowPitch = ac_surface_get_plane_stride(device->physical_device->rad_info.chip_class,2158surface, mem_plane_id);2159pLayout->arrayPitch = 0;2160pLayout->depthPitch = 0;2161pLayout->size = ac_surface_get_plane_size(surface, mem_plane_id);2162} else if (device->physical_device->rad_info.chip_class >= GFX9) {2163uint64_t level_offset = surface->is_linear ? surface->u.gfx9.offset[level] : 0;21642165pLayout->offset = ac_surface_get_plane_offset(device->physical_device->rad_info.chip_class,2166&plane->surface, 0, layer) +2167level_offset;2168if (image->vk_format == VK_FORMAT_R32G32B32_UINT ||2169image->vk_format == VK_FORMAT_R32G32B32_SINT ||2170image->vk_format == VK_FORMAT_R32G32B32_SFLOAT) {2171/* Adjust the number of bytes between each row because2172* the pitch is actually the number of components per2173* row.2174*/2175pLayout->rowPitch = surface->u.gfx9.surf_pitch * surface->bpe / 3;2176} else {2177uint32_t pitch =2178surface->is_linear ? surface->u.gfx9.pitch[level] : surface->u.gfx9.surf_pitch;21792180assert(util_is_power_of_two_nonzero(surface->bpe));2181pLayout->rowPitch = pitch * surface->bpe;2182}21832184pLayout->arrayPitch = surface->u.gfx9.surf_slice_size;2185pLayout->depthPitch = surface->u.gfx9.surf_slice_size;2186pLayout->size = surface->u.gfx9.surf_slice_size;2187if (image->type == VK_IMAGE_TYPE_3D)2188pLayout->size *= u_minify(image->info.depth, level);2189} else {2190pLayout->offset = (uint64_t)surface->u.legacy.level[level].offset_256B * 256 +2191(uint64_t)surface->u.legacy.level[level].slice_size_dw * 4 * layer;2192pLayout->rowPitch = surface->u.legacy.level[level].nblk_x * surface->bpe;2193pLayout->arrayPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;2194pLayout->depthPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;2195pLayout->size = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;2196if (image->type == VK_IMAGE_TYPE_3D)2197pLayout->size *= u_minify(image->info.depth, level);2198}2199}22002201VkResult2202radv_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device, VkImage _image,2203VkImageDrmFormatModifierPropertiesEXT *pProperties)2204{2205RADV_FROM_HANDLE(radv_image, image, _image);22062207pProperties->drmFormatModifier = image->planes[0].surface.modifier;2208return VK_SUCCESS;2209}22102211VkResult2212radv_CreateImageView(VkDevice _device, const VkImageViewCreateInfo *pCreateInfo,2213const VkAllocationCallbacks *pAllocator, VkImageView *pView)2214{2215RADV_FROM_HANDLE(radv_device, device, _device);2216struct radv_image_view *view;22172218view =2219vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);2220if (view == NULL)2221return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);22222223vk_object_base_init(&device->vk, &view->base, VK_OBJECT_TYPE_IMAGE_VIEW);22242225radv_image_view_init(view, device, pCreateInfo, NULL);22262227*pView = radv_image_view_to_handle(view);22282229return VK_SUCCESS;2230}22312232void2233radv_DestroyImageView(VkDevice _device, VkImageView _iview, const VkAllocationCallbacks *pAllocator)2234{2235RADV_FROM_HANDLE(radv_device, device, _device);2236RADV_FROM_HANDLE(radv_image_view, iview, _iview);22372238if (!iview)2239return;22402241vk_object_base_finish(&iview->base);2242vk_free2(&device->vk.alloc, pAllocator, iview);2243}22442245void2246radv_buffer_view_init(struct radv_buffer_view *view, struct radv_device *device,2247const VkBufferViewCreateInfo *pCreateInfo)2248{2249RADV_FROM_HANDLE(radv_buffer, buffer, pCreateInfo->buffer);22502251view->bo = buffer->bo;2252view->range =2253pCreateInfo->range == VK_WHOLE_SIZE ? buffer->size - pCreateInfo->offset : pCreateInfo->range;2254view->vk_format = pCreateInfo->format;22552256radv_make_buffer_descriptor(device, buffer, view->vk_format, pCreateInfo->offset, view->range,2257view->state);2258}22592260VkResult2261radv_CreateBufferView(VkDevice _device, const VkBufferViewCreateInfo *pCreateInfo,2262const VkAllocationCallbacks *pAllocator, VkBufferView *pView)2263{2264RADV_FROM_HANDLE(radv_device, device, _device);2265struct radv_buffer_view *view;22662267view =2268vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);2269if (!view)2270return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);22712272vk_object_base_init(&device->vk, &view->base, VK_OBJECT_TYPE_BUFFER_VIEW);22732274radv_buffer_view_init(view, device, pCreateInfo);22752276*pView = radv_buffer_view_to_handle(view);22772278return VK_SUCCESS;2279}22802281void2282radv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,2283const VkAllocationCallbacks *pAllocator)2284{2285RADV_FROM_HANDLE(radv_device, device, _device);2286RADV_FROM_HANDLE(radv_buffer_view, view, bufferView);22872288if (!view)2289return;22902291vk_object_base_finish(&view->base);2292vk_free2(&device->vk.alloc, pAllocator, view);2293}229422952296