Path: blob/21.2-virgl/src/amd/vulkan/radv_formats.c
7206 views
/*1* Copyright © 2016 Red Hat.2* Copyright © 2016 Bas Nieuwenhuizen3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21* IN THE SOFTWARE.22*/2324#include "radv_debug.h"25#include "radv_private.h"2627#include "sid.h"28#include "vk_format.h"2930#include "vk_util.h"3132#include "ac_drm_fourcc.h"33#include "util/format_r11g11b10f.h"34#include "util/format_rgb9e5.h"35#include "util/format_srgb.h"36#include "util/half_float.h"37#include "vulkan/util/vk_format.h"3839uint32_t40radv_translate_buffer_dataformat(const struct util_format_description *desc, int first_non_void)41{42unsigned type;43int i;4445assert(util_format_get_num_planes(desc->format) == 1);4647if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT)48return V_008F0C_BUF_DATA_FORMAT_10_11_11;4950if (first_non_void < 0)51return V_008F0C_BUF_DATA_FORMAT_INVALID;52type = desc->channel[first_non_void].type;5354if (type == UTIL_FORMAT_TYPE_FIXED)55return V_008F0C_BUF_DATA_FORMAT_INVALID;56if (desc->nr_channels == 4 && desc->channel[0].size == 10 && desc->channel[1].size == 10 &&57desc->channel[2].size == 10 && desc->channel[3].size == 2)58return V_008F0C_BUF_DATA_FORMAT_2_10_10_10;5960/* See whether the components are of the same size. */61for (i = 0; i < desc->nr_channels; i++) {62if (desc->channel[first_non_void].size != desc->channel[i].size)63return V_008F0C_BUF_DATA_FORMAT_INVALID;64}6566switch (desc->channel[first_non_void].size) {67case 8:68switch (desc->nr_channels) {69case 1:70return V_008F0C_BUF_DATA_FORMAT_8;71case 2:72return V_008F0C_BUF_DATA_FORMAT_8_8;73case 4:74return V_008F0C_BUF_DATA_FORMAT_8_8_8_8;75}76break;77case 16:78switch (desc->nr_channels) {79case 1:80return V_008F0C_BUF_DATA_FORMAT_16;81case 2:82return V_008F0C_BUF_DATA_FORMAT_16_16;83case 4:84return V_008F0C_BUF_DATA_FORMAT_16_16_16_16;85}86break;87case 32:88/* From the Southern Islands ISA documentation about MTBUF:89* 'Memory reads of data in memory that is 32 or 64 bits do not90* undergo any format conversion.'91*/92if (type != UTIL_FORMAT_TYPE_FLOAT && !desc->channel[first_non_void].pure_integer)93return V_008F0C_BUF_DATA_FORMAT_INVALID;9495switch (desc->nr_channels) {96case 1:97return V_008F0C_BUF_DATA_FORMAT_32;98case 2:99return V_008F0C_BUF_DATA_FORMAT_32_32;100case 3:101return V_008F0C_BUF_DATA_FORMAT_32_32_32;102case 4:103return V_008F0C_BUF_DATA_FORMAT_32_32_32_32;104}105break;106case 64:107if (type != UTIL_FORMAT_TYPE_FLOAT && desc->nr_channels == 1)108return V_008F0C_BUF_DATA_FORMAT_32_32;109}110111return V_008F0C_BUF_DATA_FORMAT_INVALID;112}113114uint32_t115radv_translate_buffer_numformat(const struct util_format_description *desc, int first_non_void)116{117assert(util_format_get_num_planes(desc->format) == 1);118119if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT)120return V_008F0C_BUF_NUM_FORMAT_FLOAT;121122if (first_non_void < 0)123return ~0;124125switch (desc->channel[first_non_void].type) {126case UTIL_FORMAT_TYPE_SIGNED:127if (desc->channel[first_non_void].normalized)128return V_008F0C_BUF_NUM_FORMAT_SNORM;129else if (desc->channel[first_non_void].pure_integer)130return V_008F0C_BUF_NUM_FORMAT_SINT;131else132return V_008F0C_BUF_NUM_FORMAT_SSCALED;133break;134case UTIL_FORMAT_TYPE_UNSIGNED:135if (desc->channel[first_non_void].normalized)136return V_008F0C_BUF_NUM_FORMAT_UNORM;137else if (desc->channel[first_non_void].pure_integer)138return V_008F0C_BUF_NUM_FORMAT_UINT;139else140return V_008F0C_BUF_NUM_FORMAT_USCALED;141break;142case UTIL_FORMAT_TYPE_FLOAT:143default:144return V_008F0C_BUF_NUM_FORMAT_FLOAT;145}146}147148uint32_t149radv_translate_tex_dataformat(VkFormat format, const struct util_format_description *desc,150int first_non_void)151{152bool uniform = true;153int i;154155assert(vk_format_get_plane_count(format) == 1);156157if (!desc)158return ~0;159/* Colorspace (return non-RGB formats directly). */160switch (desc->colorspace) {161/* Depth stencil formats */162case UTIL_FORMAT_COLORSPACE_ZS:163switch (format) {164case VK_FORMAT_D16_UNORM:165return V_008F14_IMG_DATA_FORMAT_16;166case VK_FORMAT_D24_UNORM_S8_UINT:167case VK_FORMAT_X8_D24_UNORM_PACK32:168return V_008F14_IMG_DATA_FORMAT_8_24;169case VK_FORMAT_S8_UINT:170return V_008F14_IMG_DATA_FORMAT_8;171case VK_FORMAT_D32_SFLOAT:172return V_008F14_IMG_DATA_FORMAT_32;173case VK_FORMAT_D32_SFLOAT_S8_UINT:174return V_008F14_IMG_DATA_FORMAT_X24_8_32;175default:176goto out_unknown;177}178179case UTIL_FORMAT_COLORSPACE_YUV:180goto out_unknown; /* TODO */181182default:183break;184}185186if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {187switch (format) {188/* Don't ask me why this looks inverted. PAL does the same. */189case VK_FORMAT_G8B8G8R8_422_UNORM:190return V_008F14_IMG_DATA_FORMAT_BG_RG;191case VK_FORMAT_B8G8R8G8_422_UNORM:192return V_008F14_IMG_DATA_FORMAT_GB_GR;193default:194goto out_unknown;195}196}197198if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {199switch (format) {200case VK_FORMAT_BC4_UNORM_BLOCK:201case VK_FORMAT_BC4_SNORM_BLOCK:202return V_008F14_IMG_DATA_FORMAT_BC4;203case VK_FORMAT_BC5_UNORM_BLOCK:204case VK_FORMAT_BC5_SNORM_BLOCK:205return V_008F14_IMG_DATA_FORMAT_BC5;206default:207break;208}209}210211if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {212switch (format) {213case VK_FORMAT_BC1_RGB_UNORM_BLOCK:214case VK_FORMAT_BC1_RGB_SRGB_BLOCK:215case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:216case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:217return V_008F14_IMG_DATA_FORMAT_BC1;218case VK_FORMAT_BC2_UNORM_BLOCK:219case VK_FORMAT_BC2_SRGB_BLOCK:220return V_008F14_IMG_DATA_FORMAT_BC2;221case VK_FORMAT_BC3_UNORM_BLOCK:222case VK_FORMAT_BC3_SRGB_BLOCK:223return V_008F14_IMG_DATA_FORMAT_BC3;224default:225break;226}227}228229if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC) {230switch (format) {231case VK_FORMAT_BC6H_UFLOAT_BLOCK:232case VK_FORMAT_BC6H_SFLOAT_BLOCK:233return V_008F14_IMG_DATA_FORMAT_BC6;234case VK_FORMAT_BC7_UNORM_BLOCK:235case VK_FORMAT_BC7_SRGB_BLOCK:236return V_008F14_IMG_DATA_FORMAT_BC7;237default:238break;239}240}241242if (desc->layout == UTIL_FORMAT_LAYOUT_ETC) {243switch (format) {244case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:245case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:246return V_008F14_IMG_DATA_FORMAT_ETC2_RGB;247case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:248case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:249return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1;250case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:251case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:252return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA;253case VK_FORMAT_EAC_R11_UNORM_BLOCK:254case VK_FORMAT_EAC_R11_SNORM_BLOCK:255return V_008F14_IMG_DATA_FORMAT_ETC2_R;256case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:257case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:258return V_008F14_IMG_DATA_FORMAT_ETC2_RG;259default:260break;261}262}263264if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {265return V_008F14_IMG_DATA_FORMAT_5_9_9_9;266} else if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {267return V_008F14_IMG_DATA_FORMAT_10_11_11;268}269270/* R8G8Bx_SNORM - TODO CxV8U8 */271272/* hw cannot support mixed formats (except depth/stencil, since only273* depth is read).*/274if (desc->is_mixed && desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)275goto out_unknown;276277/* See whether the components are of the same size. */278for (i = 1; i < desc->nr_channels; i++) {279uniform = uniform && desc->channel[0].size == desc->channel[i].size;280}281282/* Non-uniform formats. */283if (!uniform) {284switch (desc->nr_channels) {285case 3:286if (desc->channel[0].size == 5 && desc->channel[1].size == 6 &&287desc->channel[2].size == 5) {288return V_008F14_IMG_DATA_FORMAT_5_6_5;289}290goto out_unknown;291case 4:292if (desc->channel[0].size == 5 && desc->channel[1].size == 5 &&293desc->channel[2].size == 5 && desc->channel[3].size == 1) {294return V_008F14_IMG_DATA_FORMAT_1_5_5_5;295}296if (desc->channel[0].size == 1 && desc->channel[1].size == 5 &&297desc->channel[2].size == 5 && desc->channel[3].size == 5) {298return V_008F14_IMG_DATA_FORMAT_5_5_5_1;299}300if (desc->channel[0].size == 10 && desc->channel[1].size == 10 &&301desc->channel[2].size == 10 && desc->channel[3].size == 2) {302/* Closed VK driver does this also no 2/10/10/10 snorm */303if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[0].normalized)304goto out_unknown;305return V_008F14_IMG_DATA_FORMAT_2_10_10_10;306}307goto out_unknown;308}309goto out_unknown;310}311312if (first_non_void < 0 || first_non_void > 3)313goto out_unknown;314315/* uniform formats */316switch (desc->channel[first_non_void].size) {317case 4:318switch (desc->nr_channels) {319#if 0 /* Not supported for render targets */320case 2:321return V_008F14_IMG_DATA_FORMAT_4_4;322#endif323case 4:324return V_008F14_IMG_DATA_FORMAT_4_4_4_4;325}326break;327case 8:328switch (desc->nr_channels) {329case 1:330return V_008F14_IMG_DATA_FORMAT_8;331case 2:332return V_008F14_IMG_DATA_FORMAT_8_8;333case 4:334return V_008F14_IMG_DATA_FORMAT_8_8_8_8;335}336break;337case 16:338switch (desc->nr_channels) {339case 1:340return V_008F14_IMG_DATA_FORMAT_16;341case 2:342return V_008F14_IMG_DATA_FORMAT_16_16;343case 4:344return V_008F14_IMG_DATA_FORMAT_16_16_16_16;345}346break;347case 32:348switch (desc->nr_channels) {349case 1:350return V_008F14_IMG_DATA_FORMAT_32;351case 2:352return V_008F14_IMG_DATA_FORMAT_32_32;353case 3:354return V_008F14_IMG_DATA_FORMAT_32_32_32;355case 4:356return V_008F14_IMG_DATA_FORMAT_32_32_32_32;357}358break;359case 64:360if (desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT && desc->nr_channels == 1)361return V_008F14_IMG_DATA_FORMAT_32_32;362break;363}364365out_unknown:366/* R600_ERR("Unable to handle texformat %d %s\n", format, vk_format_name(format)); */367return ~0;368}369370uint32_t371radv_translate_tex_numformat(VkFormat format, const struct util_format_description *desc,372int first_non_void)373{374assert(vk_format_get_plane_count(format) == 1);375376switch (format) {377case VK_FORMAT_D24_UNORM_S8_UINT:378return V_008F14_IMG_NUM_FORMAT_UNORM;379default:380if (first_non_void < 0) {381if (vk_format_is_compressed(format)) {382switch (format) {383case VK_FORMAT_BC1_RGB_SRGB_BLOCK:384case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:385case VK_FORMAT_BC2_SRGB_BLOCK:386case VK_FORMAT_BC3_SRGB_BLOCK:387case VK_FORMAT_BC7_SRGB_BLOCK:388case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:389case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:390case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:391return V_008F14_IMG_NUM_FORMAT_SRGB;392case VK_FORMAT_BC4_SNORM_BLOCK:393case VK_FORMAT_BC5_SNORM_BLOCK:394case VK_FORMAT_BC6H_SFLOAT_BLOCK:395case VK_FORMAT_EAC_R11_SNORM_BLOCK:396case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:397return V_008F14_IMG_NUM_FORMAT_SNORM;398default:399return V_008F14_IMG_NUM_FORMAT_UNORM;400}401} else if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {402return V_008F14_IMG_NUM_FORMAT_UNORM;403} else {404return V_008F14_IMG_NUM_FORMAT_FLOAT;405}406} else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {407return V_008F14_IMG_NUM_FORMAT_SRGB;408} else {409switch (desc->channel[first_non_void].type) {410case UTIL_FORMAT_TYPE_FLOAT:411return V_008F14_IMG_NUM_FORMAT_FLOAT;412case UTIL_FORMAT_TYPE_SIGNED:413if (desc->channel[first_non_void].normalized)414return V_008F14_IMG_NUM_FORMAT_SNORM;415else if (desc->channel[first_non_void].pure_integer)416return V_008F14_IMG_NUM_FORMAT_SINT;417else418return V_008F14_IMG_NUM_FORMAT_SSCALED;419case UTIL_FORMAT_TYPE_UNSIGNED:420if (desc->channel[first_non_void].normalized)421return V_008F14_IMG_NUM_FORMAT_UNORM;422else if (desc->channel[first_non_void].pure_integer)423return V_008F14_IMG_NUM_FORMAT_UINT;424else425return V_008F14_IMG_NUM_FORMAT_USCALED;426default:427return V_008F14_IMG_NUM_FORMAT_UNORM;428}429}430}431}432433uint32_t434radv_translate_color_numformat(VkFormat format, const struct util_format_description *desc,435int first_non_void)436{437unsigned ntype;438439assert(vk_format_get_plane_count(format) == 1);440441if (first_non_void == -1 || desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_FLOAT)442ntype = V_028C70_NUMBER_FLOAT;443else {444ntype = V_028C70_NUMBER_UNORM;445if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)446ntype = V_028C70_NUMBER_SRGB;447else if (desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_SIGNED) {448if (desc->channel[first_non_void].pure_integer) {449ntype = V_028C70_NUMBER_SINT;450} else if (desc->channel[first_non_void].normalized) {451ntype = V_028C70_NUMBER_SNORM;452} else453ntype = ~0u;454} else if (desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_UNSIGNED) {455if (desc->channel[first_non_void].pure_integer) {456ntype = V_028C70_NUMBER_UINT;457} else if (desc->channel[first_non_void].normalized) {458ntype = V_028C70_NUMBER_UNORM;459} else460ntype = ~0u;461}462}463return ntype;464}465466static bool467radv_is_sampler_format_supported(VkFormat format, bool *linear_sampling)468{469const struct util_format_description *desc = vk_format_description(format);470uint32_t num_format;471if (!desc || format == VK_FORMAT_UNDEFINED || format == VK_FORMAT_R64_UINT ||472format == VK_FORMAT_R64_SINT)473return false;474num_format =475radv_translate_tex_numformat(format, desc, vk_format_get_first_non_void_channel(format));476477if (num_format == V_008F14_IMG_NUM_FORMAT_USCALED ||478num_format == V_008F14_IMG_NUM_FORMAT_SSCALED)479return false;480481if (num_format == V_008F14_IMG_NUM_FORMAT_UNORM || num_format == V_008F14_IMG_NUM_FORMAT_SNORM ||482num_format == V_008F14_IMG_NUM_FORMAT_FLOAT || num_format == V_008F14_IMG_NUM_FORMAT_SRGB)483*linear_sampling = true;484else485*linear_sampling = false;486return radv_translate_tex_dataformat(format, vk_format_description(format),487vk_format_get_first_non_void_channel(format)) != ~0U;488}489490bool491radv_is_atomic_format_supported(VkFormat format)492{493return format == VK_FORMAT_R32_UINT || format == VK_FORMAT_R32_SINT ||494format == VK_FORMAT_R32_SFLOAT || format == VK_FORMAT_R64_UINT ||495format == VK_FORMAT_R64_SINT;496}497498bool499radv_is_storage_image_format_supported(struct radv_physical_device *physical_device,500VkFormat format)501{502const struct util_format_description *desc = vk_format_description(format);503unsigned data_format, num_format;504if (!desc || format == VK_FORMAT_UNDEFINED)505return false;506507data_format =508radv_translate_tex_dataformat(format, desc, vk_format_get_first_non_void_channel(format));509num_format =510radv_translate_tex_numformat(format, desc, vk_format_get_first_non_void_channel(format));511512if (data_format == ~0 || num_format == ~0)513return false;514515/* Extracted from the GCN3 ISA document. */516switch (num_format) {517case V_008F14_IMG_NUM_FORMAT_UNORM:518case V_008F14_IMG_NUM_FORMAT_SNORM:519case V_008F14_IMG_NUM_FORMAT_UINT:520case V_008F14_IMG_NUM_FORMAT_SINT:521case V_008F14_IMG_NUM_FORMAT_FLOAT:522break;523default:524return false;525}526527switch (data_format) {528case V_008F14_IMG_DATA_FORMAT_8:529case V_008F14_IMG_DATA_FORMAT_16:530case V_008F14_IMG_DATA_FORMAT_8_8:531case V_008F14_IMG_DATA_FORMAT_32:532case V_008F14_IMG_DATA_FORMAT_16_16:533case V_008F14_IMG_DATA_FORMAT_10_11_11:534case V_008F14_IMG_DATA_FORMAT_11_11_10:535case V_008F14_IMG_DATA_FORMAT_10_10_10_2:536case V_008F14_IMG_DATA_FORMAT_2_10_10_10:537case V_008F14_IMG_DATA_FORMAT_8_8_8_8:538case V_008F14_IMG_DATA_FORMAT_32_32:539case V_008F14_IMG_DATA_FORMAT_16_16_16_16:540case V_008F14_IMG_DATA_FORMAT_32_32_32_32:541case V_008F14_IMG_DATA_FORMAT_5_6_5:542case V_008F14_IMG_DATA_FORMAT_1_5_5_5:543case V_008F14_IMG_DATA_FORMAT_5_5_5_1:544case V_008F14_IMG_DATA_FORMAT_4_4_4_4:545/* TODO: FMASK formats. */546return true;547default:548return false;549}550}551552bool553radv_is_buffer_format_supported(VkFormat format, bool *scaled)554{555const struct util_format_description *desc = vk_format_description(format);556unsigned data_format, num_format;557if (!desc || format == VK_FORMAT_UNDEFINED)558return false;559560data_format =561radv_translate_buffer_dataformat(desc, vk_format_get_first_non_void_channel(format));562num_format = radv_translate_buffer_numformat(desc, vk_format_get_first_non_void_channel(format));563564if (scaled)565*scaled = (num_format == V_008F0C_BUF_NUM_FORMAT_SSCALED) ||566(num_format == V_008F0C_BUF_NUM_FORMAT_USCALED);567return data_format != V_008F0C_BUF_DATA_FORMAT_INVALID && num_format != ~0;568}569570bool571radv_is_colorbuffer_format_supported(const struct radv_physical_device *pdevice, VkFormat format,572bool *blendable)573{574const struct util_format_description *desc = vk_format_description(format);575uint32_t color_format = radv_translate_colorformat(format);576uint32_t color_swap = radv_translate_colorswap(format, false);577uint32_t color_num_format =578radv_translate_color_numformat(format, desc, vk_format_get_first_non_void_channel(format));579580if (color_num_format == V_028C70_NUMBER_UINT || color_num_format == V_028C70_NUMBER_SINT ||581color_format == V_028C70_COLOR_8_24 || color_format == V_028C70_COLOR_24_8 ||582color_format == V_028C70_COLOR_X24_8_32_FLOAT) {583*blendable = false;584} else585*blendable = true;586587if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 && pdevice->rad_info.chip_class < GFX10_3)588return false;589590return color_format != V_028C70_COLOR_INVALID && color_swap != ~0U && color_num_format != ~0;591}592593static bool594radv_is_zs_format_supported(VkFormat format)595{596return radv_translate_dbformat(format) != V_028040_Z_INVALID || format == VK_FORMAT_S8_UINT;597}598599static bool600radv_is_filter_minmax_format_supported(VkFormat format)601{602/* From the Vulkan spec 1.1.71:603*604* "The following formats must support the605* VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT feature with606* VK_IMAGE_TILING_OPTIMAL, if they support607* VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT."608*/609/* TODO: enable more formats. */610switch (format) {611case VK_FORMAT_R8_UNORM:612case VK_FORMAT_R8_SNORM:613case VK_FORMAT_R16_UNORM:614case VK_FORMAT_R16_SNORM:615case VK_FORMAT_R16_SFLOAT:616case VK_FORMAT_R32_SFLOAT:617case VK_FORMAT_D16_UNORM:618case VK_FORMAT_X8_D24_UNORM_PACK32:619case VK_FORMAT_D32_SFLOAT:620case VK_FORMAT_D16_UNORM_S8_UINT:621case VK_FORMAT_D24_UNORM_S8_UINT:622case VK_FORMAT_D32_SFLOAT_S8_UINT:623return true;624default:625return false;626}627}628629bool630radv_device_supports_etc(struct radv_physical_device *physical_device)631{632return physical_device->rad_info.family == CHIP_VEGA10 ||633physical_device->rad_info.family == CHIP_RAVEN ||634physical_device->rad_info.family == CHIP_RAVEN2 ||635physical_device->rad_info.family == CHIP_STONEY;636}637638static void639radv_physical_device_get_format_properties(struct radv_physical_device *physical_device,640VkFormat format, VkFormatProperties *out_properties)641{642VkFormatFeatureFlags linear = 0, tiled = 0, buffer = 0;643const struct util_format_description *desc = vk_format_description(format);644bool blendable;645bool scaled = false;646/* TODO: implement some software emulation of SUBSAMPLED formats. */647if (!desc || vk_format_to_pipe_format(format) == PIPE_FORMAT_NONE ||648desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {649out_properties->linearTilingFeatures = linear;650out_properties->optimalTilingFeatures = tiled;651out_properties->bufferFeatures = buffer;652return;653}654655if (desc->layout == UTIL_FORMAT_LAYOUT_ETC && !radv_device_supports_etc(physical_device)) {656out_properties->linearTilingFeatures = linear;657out_properties->optimalTilingFeatures = tiled;658out_properties->bufferFeatures = buffer;659return;660}661662if (vk_format_get_plane_count(format) > 1 || desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {663uint32_t tiling = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT |664VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |665VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |666VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;667668/* The subsampled formats have no support for linear filters. */669if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) {670tiling |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;671}672673/* Fails for unknown reasons with linear tiling & subsampled formats. */674out_properties->linearTilingFeatures =675desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED ? 0 : tiling;676out_properties->optimalTilingFeatures = tiling;677out_properties->bufferFeatures = 0;678return;679}680681if (radv_is_storage_image_format_supported(physical_device, format)) {682tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;683linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;684}685686if (radv_is_buffer_format_supported(format, &scaled)) {687if (format != VK_FORMAT_R64_UINT && format != VK_FORMAT_R64_SINT) {688buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;689if (!scaled)690buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;691}692buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;693}694695if (vk_format_is_depth_or_stencil(format)) {696if (radv_is_zs_format_supported(format)) {697tiled |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;698tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;699tiled |= VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;700tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;701702if (radv_is_filter_minmax_format_supported(format))703tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;704705if (vk_format_has_depth(format))706tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;707708/* Don't support blitting surfaces with depth/stencil. */709if (vk_format_has_depth(format) && vk_format_has_stencil(format))710tiled &= ~VK_FORMAT_FEATURE_BLIT_DST_BIT;711712/* Don't support linear depth surfaces */713linear = 0;714}715} else {716bool linear_sampling;717if (radv_is_sampler_format_supported(format, &linear_sampling)) {718linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;719tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;720721if (radv_is_filter_minmax_format_supported(format))722tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;723724if (linear_sampling) {725linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;726tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;727}728729/* Don't support blitting for R32G32B32 formats. */730if (format == VK_FORMAT_R32G32B32_SFLOAT || format == VK_FORMAT_R32G32B32_UINT ||731format == VK_FORMAT_R32G32B32_SINT) {732linear &= ~VK_FORMAT_FEATURE_BLIT_SRC_BIT;733}734}735if (radv_is_colorbuffer_format_supported(physical_device, format, &blendable)) {736linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;737tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;738if (blendable) {739linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;740tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;741}742}743if (tiled && !scaled) {744tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;745}746747/* Tiled formatting does not support NPOT pixel sizes */748if (!util_is_power_of_two_or_zero(vk_format_get_blocksize(format)))749tiled = 0;750}751752if (linear && !scaled) {753linear |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;754}755756if (radv_is_atomic_format_supported(format)) {757buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;758linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;759tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;760}761762switch (format) {763case VK_FORMAT_A2R10G10B10_SNORM_PACK32:764case VK_FORMAT_A2B10G10R10_SNORM_PACK32:765case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:766case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:767case VK_FORMAT_A2R10G10B10_SINT_PACK32:768case VK_FORMAT_A2B10G10R10_SINT_PACK32:769buffer &=770~(VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT);771linear = 0;772tiled = 0;773break;774default:775break;776}777778switch (format) {779case VK_FORMAT_R32G32B32_SFLOAT:780case VK_FORMAT_R32G32B32A32_SFLOAT:781case VK_FORMAT_R16G16B16_SFLOAT:782case VK_FORMAT_R16G16B16A16_SFLOAT:783buffer |= VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR;784break;785default:786break;787}788/* addrlib does not support linear compressed textures. */789if (vk_format_is_compressed(format))790linear = 0;791792/* From the Vulkan spec 1.2.163:793*794* "VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR must be supported for the795* following formats if the attachmentFragmentShadingRate feature is supported:"796*797* - VK_FORMAT_R8_UINT798*/799if (format == VK_FORMAT_R8_UINT) {800tiled |= VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;801}802803out_properties->linearTilingFeatures = linear;804out_properties->optimalTilingFeatures = tiled;805out_properties->bufferFeatures = buffer;806}807808uint32_t809radv_translate_colorformat(VkFormat format)810{811const struct util_format_description *desc = vk_format_description(format);812813#define HAS_SIZE(x, y, z, w) \814(desc->channel[0].size == (x) && desc->channel[1].size == (y) && \815desc->channel[2].size == (z) && desc->channel[3].size == (w))816817if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) /* isn't plain */818return V_028C70_COLOR_10_11_11;819820if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)821return V_028C70_COLOR_5_9_9_9;822823if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)824return V_028C70_COLOR_INVALID;825826/* hw cannot support mixed formats (except depth/stencil, since827* stencil is not written to). */828if (desc->is_mixed && desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)829return V_028C70_COLOR_INVALID;830831switch (desc->nr_channels) {832case 1:833switch (desc->channel[0].size) {834case 8:835return V_028C70_COLOR_8;836case 16:837return V_028C70_COLOR_16;838case 32:839return V_028C70_COLOR_32;840}841break;842case 2:843if (desc->channel[0].size == desc->channel[1].size) {844switch (desc->channel[0].size) {845case 8:846return V_028C70_COLOR_8_8;847case 16:848return V_028C70_COLOR_16_16;849case 32:850return V_028C70_COLOR_32_32;851}852} else if (HAS_SIZE(8, 24, 0, 0)) {853return V_028C70_COLOR_24_8;854} else if (HAS_SIZE(24, 8, 0, 0)) {855return V_028C70_COLOR_8_24;856}857break;858case 3:859if (HAS_SIZE(5, 6, 5, 0)) {860return V_028C70_COLOR_5_6_5;861} else if (HAS_SIZE(32, 8, 24, 0)) {862return V_028C70_COLOR_X24_8_32_FLOAT;863}864break;865case 4:866if (desc->channel[0].size == desc->channel[1].size &&867desc->channel[0].size == desc->channel[2].size &&868desc->channel[0].size == desc->channel[3].size) {869switch (desc->channel[0].size) {870case 4:871return V_028C70_COLOR_4_4_4_4;872case 8:873return V_028C70_COLOR_8_8_8_8;874case 16:875return V_028C70_COLOR_16_16_16_16;876case 32:877return V_028C70_COLOR_32_32_32_32;878}879} else if (HAS_SIZE(5, 5, 5, 1)) {880return V_028C70_COLOR_1_5_5_5;881} else if (HAS_SIZE(1, 5, 5, 5)) {882return V_028C70_COLOR_5_5_5_1;883} else if (HAS_SIZE(10, 10, 10, 2)) {884return V_028C70_COLOR_2_10_10_10;885}886break;887}888return V_028C70_COLOR_INVALID;889}890891uint32_t892radv_colorformat_endian_swap(uint32_t colorformat)893{894if (0 /*SI_BIG_ENDIAN*/) {895switch (colorformat) {896/* 8-bit buffers. */897case V_028C70_COLOR_8:898return V_028C70_ENDIAN_NONE;899900/* 16-bit buffers. */901case V_028C70_COLOR_5_6_5:902case V_028C70_COLOR_1_5_5_5:903case V_028C70_COLOR_4_4_4_4:904case V_028C70_COLOR_16:905case V_028C70_COLOR_8_8:906return V_028C70_ENDIAN_8IN16;907908/* 32-bit buffers. */909case V_028C70_COLOR_8_8_8_8:910case V_028C70_COLOR_2_10_10_10:911case V_028C70_COLOR_8_24:912case V_028C70_COLOR_24_8:913case V_028C70_COLOR_16_16:914return V_028C70_ENDIAN_8IN32;915916/* 64-bit buffers. */917case V_028C70_COLOR_16_16_16_16:918return V_028C70_ENDIAN_8IN16;919920case V_028C70_COLOR_32_32:921return V_028C70_ENDIAN_8IN32;922923/* 128-bit buffers. */924case V_028C70_COLOR_32_32_32_32:925return V_028C70_ENDIAN_8IN32;926default:927return V_028C70_ENDIAN_NONE; /* Unsupported. */928}929} else {930return V_028C70_ENDIAN_NONE;931}932}933934uint32_t935radv_translate_dbformat(VkFormat format)936{937switch (format) {938case VK_FORMAT_D16_UNORM:939case VK_FORMAT_D16_UNORM_S8_UINT:940return V_028040_Z_16;941case VK_FORMAT_D32_SFLOAT:942case VK_FORMAT_D32_SFLOAT_S8_UINT:943return V_028040_Z_32_FLOAT;944default:945return V_028040_Z_INVALID;946}947}948949unsigned950radv_translate_colorswap(VkFormat format, bool do_endian_swap)951{952const struct util_format_description *desc = vk_format_description(format);953954#define HAS_SWIZZLE(chan, swz) (desc->swizzle[chan] == PIPE_SWIZZLE_##swz)955956if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)957return V_028C70_SWAP_STD;958959if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)960return V_028C70_SWAP_STD;961962if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)963return ~0U;964965switch (desc->nr_channels) {966case 1:967if (HAS_SWIZZLE(0, X))968return V_028C70_SWAP_STD; /* X___ */969else if (HAS_SWIZZLE(3, X))970return V_028C70_SWAP_ALT_REV; /* ___X */971break;972case 2:973if ((HAS_SWIZZLE(0, X) && HAS_SWIZZLE(1, Y)) || (HAS_SWIZZLE(0, X) && HAS_SWIZZLE(1, NONE)) ||974(HAS_SWIZZLE(0, NONE) && HAS_SWIZZLE(1, Y)))975return V_028C70_SWAP_STD; /* XY__ */976else if ((HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(1, X)) ||977(HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(1, NONE)) ||978(HAS_SWIZZLE(0, NONE) && HAS_SWIZZLE(1, X)))979/* YX__ */980return (do_endian_swap ? V_028C70_SWAP_STD : V_028C70_SWAP_STD_REV);981else if (HAS_SWIZZLE(0, X) && HAS_SWIZZLE(3, Y))982return V_028C70_SWAP_ALT; /* X__Y */983else if (HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(3, X))984return V_028C70_SWAP_ALT_REV; /* Y__X */985break;986case 3:987if (HAS_SWIZZLE(0, X))988return (do_endian_swap ? V_028C70_SWAP_STD_REV : V_028C70_SWAP_STD);989else if (HAS_SWIZZLE(0, Z))990return V_028C70_SWAP_STD_REV; /* ZYX */991break;992case 4:993/* check the middle channels, the 1st and 4th channel can be NONE */994if (HAS_SWIZZLE(1, Y) && HAS_SWIZZLE(2, Z)) {995return V_028C70_SWAP_STD; /* XYZW */996} else if (HAS_SWIZZLE(1, Z) && HAS_SWIZZLE(2, Y)) {997return V_028C70_SWAP_STD_REV; /* WZYX */998} else if (HAS_SWIZZLE(1, Y) && HAS_SWIZZLE(2, X)) {999return V_028C70_SWAP_ALT; /* ZYXW */1000} else if (HAS_SWIZZLE(1, Z) && HAS_SWIZZLE(2, W)) {1001/* YZWX */1002if (desc->is_array)1003return V_028C70_SWAP_ALT_REV;1004else1005return (do_endian_swap ? V_028C70_SWAP_ALT : V_028C70_SWAP_ALT_REV);1006}1007break;1008}1009return ~0U;1010}10111012bool1013radv_format_pack_clear_color(VkFormat format, uint32_t clear_vals[2], VkClearColorValue *value)1014{1015const struct util_format_description *desc = vk_format_description(format);10161017if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {1018clear_vals[0] = float3_to_r11g11b10f(value->float32);1019clear_vals[1] = 0;1020return true;1021} else if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {1022clear_vals[0] = float3_to_rgb9e5(value->float32);1023clear_vals[1] = 0;1024return true;1025}10261027if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {1028fprintf(stderr, "failed to fast clear for non-plain format %d\n", format);1029return false;1030}10311032if (!util_is_power_of_two_or_zero(desc->block.bits)) {1033fprintf(stderr, "failed to fast clear for NPOT format %d\n", format);1034return false;1035}10361037if (desc->block.bits > 64) {1038/*1039* We have a 128 bits format, check if the first 3 components are the same.1040* Every elements has to be 32 bits since we don't support 64-bit formats,1041* and we can skip swizzling checks as alpha always comes last for these and1042* we do not care about the rest as they have to be the same.1043*/1044if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {1045if (value->float32[0] != value->float32[1] || value->float32[0] != value->float32[2])1046return false;1047} else {1048if (value->uint32[0] != value->uint32[1] || value->uint32[0] != value->uint32[2])1049return false;1050}1051clear_vals[0] = value->uint32[0];1052clear_vals[1] = value->uint32[3];1053return true;1054}1055uint64_t clear_val = 0;10561057for (unsigned c = 0; c < 4; ++c) {1058if (desc->swizzle[c] >= 4)1059continue;10601061const struct util_format_channel_description *channel = &desc->channel[desc->swizzle[c]];1062assert(channel->size);10631064uint64_t v = 0;1065if (channel->pure_integer) {1066v = value->uint32[c] & ((1ULL << channel->size) - 1);1067} else if (channel->normalized) {1068if (channel->type == UTIL_FORMAT_TYPE_UNSIGNED && desc->swizzle[c] < 3 &&1069desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {1070assert(channel->size == 8);10711072v = util_format_linear_float_to_srgb_8unorm(value->float32[c]);1073} else {1074float f = MIN2(value->float32[c], 1.0f);10751076if (channel->type == UTIL_FORMAT_TYPE_UNSIGNED) {1077f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1);1078} else {1079f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1);1080}10811082/* The hardware rounds before conversion. */1083if (f > 0)1084f += 0.5f;1085else1086f -= 0.5f;10871088v = (uint64_t)f;1089}1090} else if (channel->type == UTIL_FORMAT_TYPE_FLOAT) {1091if (channel->size == 32) {1092memcpy(&v, &value->float32[c], 4);1093} else if (channel->size == 16) {1094v = _mesa_float_to_float16_rtz(value->float32[c]);1095} else {1096fprintf(stderr, "failed to fast clear for unhandled float size in format %d\n", format);1097return false;1098}1099} else {1100fprintf(stderr, "failed to fast clear for unhandled component type in format %d\n",1101format);1102return false;1103}1104clear_val |= (v & ((1ULL << channel->size) - 1)) << channel->shift;1105}11061107clear_vals[0] = clear_val;1108clear_vals[1] = clear_val >> 32;11091110return true;1111}11121113void1114radv_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,1115VkFormatProperties *pFormatProperties)1116{1117RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);11181119radv_physical_device_get_format_properties(physical_device, format, pFormatProperties);1120}11211122static const struct ac_modifier_options radv_modifier_options = {1123.dcc = true,1124.dcc_retile = true,1125};11261127static VkFormatFeatureFlags1128radv_get_modifier_flags(struct radv_physical_device *dev, VkFormat format, uint64_t modifier,1129const VkFormatProperties *props)1130{1131VkFormatFeatureFlags features;11321133if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format))1134return 0;11351136if (modifier == DRM_FORMAT_MOD_LINEAR)1137features = props->linearTilingFeatures;1138else1139features = props->optimalTilingFeatures;11401141if (ac_modifier_has_dcc(modifier)) {1142features &= ~VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;11431144if (dev->instance->debug_flags & (RADV_DEBUG_NO_DCC | RADV_DEBUG_NO_DISPLAY_DCC))1145return 0;1146}11471148return features;1149}11501151static void1152radv_list_drm_format_modifiers(struct radv_physical_device *dev, VkFormat format,1153VkFormatProperties2 *pFormatProperties)1154{1155VkDrmFormatModifierPropertiesListEXT *mod_list =1156vk_find_struct(pFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);1157unsigned mod_count;11581159if (!mod_list)1160return;11611162if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format)) {1163mod_list->drmFormatModifierCount = 0;1164return;1165}11661167ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,1168vk_format_to_pipe_format(format), &mod_count, NULL);1169if (!mod_list->pDrmFormatModifierProperties) {1170mod_list->drmFormatModifierCount = mod_count;1171return;1172}11731174mod_count = MIN2(mod_count, mod_list->drmFormatModifierCount);11751176uint64_t *mods = malloc(mod_count * sizeof(uint64_t));1177if (!mods) {1178/* We can't return an error here ... */1179mod_list->drmFormatModifierCount = 0;1180return;1181}1182ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,1183vk_format_to_pipe_format(format), &mod_count, mods);11841185mod_list->drmFormatModifierCount = 0;1186for (unsigned i = 0; i < mod_count; ++i) {1187VkFormatFeatureFlags features =1188radv_get_modifier_flags(dev, format, mods[i], &pFormatProperties->formatProperties);1189unsigned planes = vk_format_get_plane_count(format);1190if (planes == 1) {1191if (ac_modifier_has_dcc_retile(mods[i]))1192planes = 3;1193else if (ac_modifier_has_dcc(mods[i]))1194planes = 2;1195}11961197if (!features)1198continue;11991200mod_list->pDrmFormatModifierProperties[mod_list->drmFormatModifierCount].drmFormatModifier =1201mods[i];1202mod_list->pDrmFormatModifierProperties[mod_list->drmFormatModifierCount]1203.drmFormatModifierPlaneCount = planes;1204mod_list->pDrmFormatModifierProperties[mod_list->drmFormatModifierCount]1205.drmFormatModifierTilingFeatures = features;12061207++mod_list->drmFormatModifierCount;1208}12091210free(mods);1211}12121213static VkResult1214radv_check_modifier_support(struct radv_physical_device *dev,1215const VkPhysicalDeviceImageFormatInfo2 *info,1216VkImageFormatProperties *props, VkFormat format, uint64_t modifier)1217{1218if (info->type != VK_IMAGE_TYPE_2D)1219return VK_ERROR_FORMAT_NOT_SUPPORTED;12201221/* We did not add modifiers for sparse textures. */1222if (info->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |1223VK_IMAGE_CREATE_SPARSE_ALIASED_BIT))1224return VK_ERROR_FORMAT_NOT_SUPPORTED;12251226/*1227* Need to check the modifier is supported in general:1228* "If the drmFormatModifier is incompatible with the parameters specified1229* in VkPhysicalDeviceImageFormatInfo2 and its pNext chain, then1230* vkGetPhysicalDeviceImageFormatProperties2 returns VK_ERROR_FORMAT_NOT_SUPPORTED.1231* The implementation must support the query of any drmFormatModifier,1232* including unknown and invalid modifier values."1233*/1234VkDrmFormatModifierPropertiesListEXT mod_list = {1235.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,1236};12371238VkFormatProperties2 format_props2 = {.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,1239.pNext = &mod_list};12401241radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(dev), format,1242&format_props2);12431244if (!mod_list.drmFormatModifierCount)1245return VK_ERROR_FORMAT_NOT_SUPPORTED;12461247mod_list.pDrmFormatModifierProperties =1248calloc(mod_list.drmFormatModifierCount, sizeof(*mod_list.pDrmFormatModifierProperties));1249if (!mod_list.pDrmFormatModifierProperties)1250return VK_ERROR_OUT_OF_HOST_MEMORY;12511252radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(dev), format,1253&format_props2);12541255bool found = false;1256for (uint32_t i = 0; i < mod_list.drmFormatModifierCount && !found; ++i)1257if (mod_list.pDrmFormatModifierProperties[i].drmFormatModifier == modifier)1258found = true;12591260free(mod_list.pDrmFormatModifierProperties);12611262if (!found)1263return VK_ERROR_FORMAT_NOT_SUPPORTED;12641265if (ac_modifier_has_dcc(modifier) &&1266!radv_are_formats_dcc_compatible(dev, info->pNext, format, info->flags))1267return VK_ERROR_FORMAT_NOT_SUPPORTED;12681269/* We can expand this as needed and implemented but there is not much demand1270* for more. */1271if (ac_modifier_has_dcc(modifier)) {1272props->maxMipLevels = 1;1273props->maxArrayLayers = 1;1274}1275/* We don't support MSAA for modifiers */1276props->sampleCounts &= VK_SAMPLE_COUNT_1_BIT;1277return VK_SUCCESS;1278}12791280void1281radv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format,1282VkFormatProperties2 *pFormatProperties)1283{1284RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);12851286radv_physical_device_get_format_properties(physical_device, format,1287&pFormatProperties->formatProperties);12881289radv_list_drm_format_modifiers(physical_device, format, pFormatProperties);1290}12911292static VkResult1293radv_get_image_format_properties(struct radv_physical_device *physical_device,1294const VkPhysicalDeviceImageFormatInfo2 *info, VkFormat format,1295VkImageFormatProperties *pImageFormatProperties)12961297{1298VkFormatProperties format_props;1299VkFormatFeatureFlags format_feature_flags;1300VkExtent3D maxExtent;1301uint32_t maxMipLevels;1302uint32_t maxArraySize;1303VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;1304const struct util_format_description *desc = vk_format_description(format);1305enum chip_class chip_class = physical_device->rad_info.chip_class;1306VkImageTiling tiling = info->tiling;1307const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *mod_info =1308vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);1309VkResult result = VK_ERROR_FORMAT_NOT_SUPPORTED;13101311radv_physical_device_get_format_properties(physical_device, format, &format_props);1312if (tiling == VK_IMAGE_TILING_LINEAR) {1313format_feature_flags = format_props.linearTilingFeatures;1314} else if (tiling == VK_IMAGE_TILING_OPTIMAL) {1315format_feature_flags = format_props.optimalTilingFeatures;1316} else if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {1317format_feature_flags = radv_get_modifier_flags(physical_device, format,1318mod_info->drmFormatModifier, &format_props);1319} else {1320unreachable("bad VkImageTiling");1321}13221323if (format_feature_flags == 0)1324goto unsupported;13251326if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(format))1327goto unsupported;13281329switch (info->type) {1330default:1331unreachable("bad vkimage type\n");1332case VK_IMAGE_TYPE_1D:1333maxExtent.width = 16384;1334maxExtent.height = 1;1335maxExtent.depth = 1;1336maxMipLevels = 15; /* log2(maxWidth) + 1 */1337maxArraySize = chip_class >= GFX10 ? 8192 : 2048;1338break;1339case VK_IMAGE_TYPE_2D:1340maxExtent.width = 16384;1341maxExtent.height = 16384;1342maxExtent.depth = 1;1343maxMipLevels = 15; /* log2(maxWidth) + 1 */1344maxArraySize = chip_class >= GFX10 ? 8192 : 2048;1345break;1346case VK_IMAGE_TYPE_3D:1347if (chip_class >= GFX10) {1348maxExtent.width = 8192;1349maxExtent.height = 8192;1350maxExtent.depth = 8192;1351} else {1352maxExtent.width = 2048;1353maxExtent.height = 2048;1354maxExtent.depth = 2048;1355}1356maxMipLevels = util_logbase2(maxExtent.width) + 1;1357maxArraySize = 1;1358break;1359}13601361if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {1362/* Might be able to support but the entire format support is1363* messy, so taking the lazy way out. */1364maxArraySize = 1;1365}13661367if (tiling == VK_IMAGE_TILING_OPTIMAL && info->type == VK_IMAGE_TYPE_2D &&1368(format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |1369VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&1370!(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&1371!(info->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)) {1372sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT;1373}13741375if (tiling == VK_IMAGE_TILING_LINEAR &&1376(format == VK_FORMAT_R32G32B32_SFLOAT || format == VK_FORMAT_R32G32B32_SINT ||1377format == VK_FORMAT_R32G32B32_UINT)) {1378/* R32G32B32 is a weird format and the driver currently only1379* supports the barely minimum.1380* TODO: Implement more if we really need to.1381*/1382if (info->type == VK_IMAGE_TYPE_3D)1383goto unsupported;1384maxArraySize = 1;1385maxMipLevels = 1;1386}13871388/* We can't create 3d compressed 128bpp images that can be rendered to on GFX9 */1389if (physical_device->rad_info.chip_class >= GFX9 && info->type == VK_IMAGE_TYPE_3D &&1390vk_format_get_blocksizebits(format) == 128 && vk_format_is_compressed(format) &&1391(info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) &&1392((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) ||1393(info->usage & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))) {1394goto unsupported;1395}13961397if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {1398if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {1399goto unsupported;1400}1401}14021403if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {1404if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {1405goto unsupported;1406}1407}14081409if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {1410if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {1411goto unsupported;1412}1413}14141415if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {1416if (!(format_feature_flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {1417goto unsupported;1418}1419}14201421if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {1422if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) {1423goto unsupported;1424}1425}14261427if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {1428if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {1429goto unsupported;1430}1431}14321433if (info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {1434if (!(format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |1435VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))) {1436goto unsupported;1437}1438}14391440/* Sparse resources with multi-planar formats are unsupported. */1441if (info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {1442if (vk_format_get_plane_count(format) > 1)1443goto unsupported;1444}14451446if (info->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {1447/* Sparse textures are only supported on GFX8+. */1448if (physical_device->rad_info.chip_class < GFX8)1449goto unsupported;14501451if (vk_format_get_plane_count(format) > 1 || info->type != VK_IMAGE_TYPE_2D ||1452info->tiling != VK_IMAGE_TILING_OPTIMAL || vk_format_is_depth_or_stencil(format))1453goto unsupported;1454}14551456*pImageFormatProperties = (VkImageFormatProperties){1457.maxExtent = maxExtent,1458.maxMipLevels = maxMipLevels,1459.maxArrayLayers = maxArraySize,1460.sampleCounts = sampleCounts,14611462/* FINISHME: Accurately calculate1463* VkImageFormatProperties::maxResourceSize.1464*/1465.maxResourceSize = UINT32_MAX,1466};14671468if (mod_info) {1469result = radv_check_modifier_support(physical_device, info, pImageFormatProperties, format,1470mod_info->drmFormatModifier);1471if (result != VK_SUCCESS)1472goto unsupported;1473}14741475return VK_SUCCESS;1476unsupported:1477*pImageFormatProperties = (VkImageFormatProperties){1478.maxExtent = {0, 0, 0},1479.maxMipLevels = 0,1480.maxArrayLayers = 0,1481.sampleCounts = 0,1482.maxResourceSize = 0,1483};14841485return result;1486}14871488VkResult1489radv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,1490VkImageType type, VkImageTiling tiling,1491VkImageUsageFlags usage, VkImageCreateFlags createFlags,1492VkImageFormatProperties *pImageFormatProperties)1493{1494RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);14951496const VkPhysicalDeviceImageFormatInfo2 info = {1497.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,1498.pNext = NULL,1499.format = format,1500.type = type,1501.tiling = tiling,1502.usage = usage,1503.flags = createFlags,1504};15051506return radv_get_image_format_properties(physical_device, &info, format, pImageFormatProperties);1507}15081509static void1510get_external_image_format_properties(struct radv_physical_device *physical_device,1511const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,1512VkExternalMemoryHandleTypeFlagBits handleType,1513VkExternalMemoryProperties *external_properties,1514VkImageFormatProperties *format_properties)1515{1516VkExternalMemoryFeatureFlagBits flags = 0;1517VkExternalMemoryHandleTypeFlags export_flags = 0;1518VkExternalMemoryHandleTypeFlags compat_flags = 0;15191520if (pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)1521return;15221523switch (handleType) {1524case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:1525if (pImageFormatInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)1526break;15271528switch (pImageFormatInfo->type) {1529case VK_IMAGE_TYPE_2D:1530flags =1531VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;15321533compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;1534break;1535default:1536break;1537}1538break;1539case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:1540switch (pImageFormatInfo->type) {1541case VK_IMAGE_TYPE_2D:1542flags =1543VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;1544if (pImageFormatInfo->tiling != VK_IMAGE_TILING_LINEAR)1545flags |= VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;15461547compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;1548break;1549default:1550break;1551}1552break;1553case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:1554if (!physical_device->vk.supported_extensions.ANDROID_external_memory_android_hardware_buffer)1555break;15561557if (!radv_android_gralloc_supports_format(pImageFormatInfo->format, pImageFormatInfo->usage))1558break;15591560if (pImageFormatInfo->type != VK_IMAGE_TYPE_2D)1561break;15621563format_properties->maxMipLevels = MIN2(1, format_properties->maxMipLevels);1564format_properties->maxArrayLayers = MIN2(1, format_properties->maxArrayLayers);1565format_properties->sampleCounts &= VK_SAMPLE_COUNT_1_BIT;15661567flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;1568if (pImageFormatInfo->tiling != VK_IMAGE_TILING_LINEAR)1569flags |= VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;15701571compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;1572break;1573case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:1574flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;1575compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;1576break;1577default:1578break;1579}15801581*external_properties = (VkExternalMemoryProperties){1582.externalMemoryFeatures = flags,1583.exportFromImportedHandleTypes = export_flags,1584.compatibleHandleTypes = compat_flags,1585};1586}15871588VkResult1589radv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,1590const VkPhysicalDeviceImageFormatInfo2 *base_info,1591VkImageFormatProperties2 *base_props)1592{1593RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);1594const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;1595VkExternalImageFormatProperties *external_props = NULL;1596struct VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;1597VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;1598VkTextureLODGatherFormatPropertiesAMD *texture_lod_props = NULL;1599VkResult result;1600VkFormat format = radv_select_android_external_format(base_info->pNext, base_info->format);16011602result = radv_get_image_format_properties(physical_device, base_info, format,1603&base_props->imageFormatProperties);1604if (result != VK_SUCCESS)1605return result;16061607/* Extract input structs */1608vk_foreach_struct_const(s, base_info->pNext)1609{1610switch (s->sType) {1611case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:1612external_info = (const void *)s;1613break;1614default:1615break;1616}1617}16181619/* Extract output structs */1620vk_foreach_struct(s, base_props->pNext)1621{1622switch (s->sType) {1623case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:1624external_props = (void *)s;1625break;1626case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:1627ycbcr_props = (void *)s;1628break;1629case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:1630android_usage = (void *)s;1631break;1632case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD:1633texture_lod_props = (void *)s;1634break;1635default:1636break;1637}1638}16391640bool ahb_supported =1641physical_device->vk.supported_extensions.ANDROID_external_memory_android_hardware_buffer;1642if (android_usage && ahb_supported) {1643#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER1644android_usage->androidHardwareBufferUsage =1645radv_ahb_usage_from_vk_usage(base_info->flags, base_info->usage);1646#endif1647}16481649/* From the Vulkan 1.0.97 spec:1650*1651* If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will1652* behave as if VkPhysicalDeviceExternalImageFormatInfo was not1653* present and VkExternalImageFormatProperties will be ignored.1654*/1655if (external_info && external_info->handleType != 0) {1656get_external_image_format_properties(physical_device, base_info, external_info->handleType,1657&external_props->externalMemoryProperties,1658&base_props->imageFormatProperties);1659if (!external_props->externalMemoryProperties.externalMemoryFeatures) {1660/* From the Vulkan 1.0.97 spec:1661*1662* If handleType is not compatible with the [parameters] specified1663* in VkPhysicalDeviceImageFormatInfo2, then1664* vkGetPhysicalDeviceImageFormatProperties2 returns1665* VK_ERROR_FORMAT_NOT_SUPPORTED.1666*/1667result = vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,1668"unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x",1669external_info->handleType);1670goto fail;1671}1672}16731674if (ycbcr_props) {1675ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(format);1676}16771678if (texture_lod_props) {1679if (physical_device->rad_info.chip_class >= GFX9) {1680texture_lod_props->supportsTextureGatherLODBiasAMD = true;1681} else {1682texture_lod_props->supportsTextureGatherLODBiasAMD = !vk_format_is_int(format);1683}1684}16851686return VK_SUCCESS;16871688fail:1689if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {1690/* From the Vulkan 1.0.97 spec:1691*1692* If the combination of parameters to1693* vkGetPhysicalDeviceImageFormatProperties2 is not supported by1694* the implementation for use in vkCreateImage, then all members of1695* imageFormatProperties will be filled with zero.1696*/1697base_props->imageFormatProperties = (VkImageFormatProperties){0};1698}16991700return result;1701}17021703static void1704fill_sparse_image_format_properties(struct radv_physical_device *pdev, VkFormat format,1705VkSparseImageFormatProperties *prop)1706{1707prop->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;1708prop->flags = 0;17091710/* On GFX8 we first subdivide by level and then layer, leading to a single1711* miptail. On GFX9+ we first subdivide by layer and then level which results1712* in a miptail per layer. */1713if (pdev->rad_info.chip_class < GFX9)1714prop->flags |= VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT;17151716/* This assumes the sparse image tile size is always 64 KiB (1 << 16) */1717unsigned l2_size = 16 - util_logbase2(vk_format_get_blocksize(format));1718unsigned w = (1u << ((l2_size + 1) / 2)) * vk_format_get_blockwidth(format);1719unsigned h = (1u << (l2_size / 2)) * vk_format_get_blockheight(format);17201721prop->imageGranularity = (VkExtent3D){w, h, 1};1722}17231724void1725radv_GetPhysicalDeviceSparseImageFormatProperties2(1726VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,1727uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties)1728{1729RADV_FROM_HANDLE(radv_physical_device, pdev, physicalDevice);1730VkResult result;17311732if (pFormatInfo->samples > VK_SAMPLE_COUNT_1_BIT) {1733*pPropertyCount = 0;1734return;1735}17361737const VkPhysicalDeviceImageFormatInfo2 fmt_info = {1738.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,1739.format = pFormatInfo->format,1740.type = pFormatInfo->type,1741.tiling = pFormatInfo->tiling,1742.usage = pFormatInfo->usage,1743.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT};17441745VkImageFormatProperties fmt_props;1746result = radv_get_image_format_properties(pdev, &fmt_info, pFormatInfo->format, &fmt_props);1747if (result != VK_SUCCESS) {1748*pPropertyCount = 0;1749return;1750}17511752VK_OUTARRAY_MAKE_TYPED(VkSparseImageFormatProperties2, out, pProperties, pPropertyCount);17531754vk_outarray_append_typed(VkSparseImageFormatProperties2, &out, prop)1755{1756fill_sparse_image_format_properties(pdev, pFormatInfo->format, &prop->properties);1757};1758}17591760void1761radv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,1762VkImageType type, uint32_t samples,1763VkImageUsageFlags usage, VkImageTiling tiling,1764uint32_t *pNumProperties,1765VkSparseImageFormatProperties *pProperties)1766{1767const VkPhysicalDeviceSparseImageFormatInfo2 info = {1768.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2,1769.format = format,1770.type = type,1771.samples = samples,1772.usage = usage,1773.tiling = tiling};17741775if (!pProperties) {1776radv_GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, &info, pNumProperties,1777NULL);1778return;1779}17801781VkSparseImageFormatProperties2 props[4];1782uint32_t prop_cnt = MIN2(ARRAY_SIZE(props), *pNumProperties);17831784memset(props, 0, sizeof(props));1785for (unsigned i = 0; i < ARRAY_SIZE(props); ++i)1786props[i].sType = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2;17871788radv_GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, &info, &prop_cnt, props);17891790for (unsigned i = 0; i < prop_cnt; ++i)1791pProperties[i] = props[i].properties;1792*pNumProperties = prop_cnt;1793}17941795void1796radv_GetImageSparseMemoryRequirements2(VkDevice _device,1797const VkImageSparseMemoryRequirementsInfo2 *pInfo,1798uint32_t *pSparseMemoryRequirementCount,1799VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)1800{1801RADV_FROM_HANDLE(radv_device, device, _device);1802RADV_FROM_HANDLE(radv_image, image, pInfo->image);18031804if (!(image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {1805*pSparseMemoryRequirementCount = 0;1806return;1807}18081809VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,1810pSparseMemoryRequirementCount);18111812vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, req)1813{1814fill_sparse_image_format_properties(device->physical_device, image->vk_format,1815&req->memoryRequirements.formatProperties);1816req->memoryRequirements.imageMipTailFirstLod = image->planes[0].surface.first_mip_tail_level;18171818if (req->memoryRequirements.imageMipTailFirstLod < image->info.levels) {1819if (device->physical_device->rad_info.chip_class >= GFX9) {1820/* The tail is always a single tile per layer. */1821req->memoryRequirements.imageMipTailSize = 65536;1822req->memoryRequirements.imageMipTailOffset =1823image->planes[0]1824.surface.u.gfx9.prt_level_offset[req->memoryRequirements.imageMipTailFirstLod] &1825~65535;1826req->memoryRequirements.imageMipTailStride =1827image->planes[0].surface.u.gfx9.surf_slice_size;1828} else {1829req->memoryRequirements.imageMipTailOffset =1830(uint64_t)image->planes[0]1831.surface.u.legacy.level[req->memoryRequirements.imageMipTailFirstLod]1832.offset_256B * 256;1833req->memoryRequirements.imageMipTailSize =1834image->size - req->memoryRequirements.imageMipTailOffset;1835req->memoryRequirements.imageMipTailStride = 0;1836}1837} else {1838req->memoryRequirements.imageMipTailSize = 0;1839req->memoryRequirements.imageMipTailOffset = 0;1840req->memoryRequirements.imageMipTailStride = 0;1841}1842};1843}18441845void1846radv_GetImageSparseMemoryRequirements(VkDevice device, VkImage image,1847uint32_t *pSparseMemoryRequirementCount,1848VkSparseImageMemoryRequirements *pSparseMemoryRequirements)1849{1850const VkImageSparseMemoryRequirementsInfo2 info = {1851.sType = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,1852.image = image};18531854if (!pSparseMemoryRequirements) {1855radv_GetImageSparseMemoryRequirements2(device, &info, pSparseMemoryRequirementCount, NULL);1856return;1857}18581859VkSparseImageMemoryRequirements2 reqs[4];1860uint32_t reqs_cnt = MIN2(ARRAY_SIZE(reqs), *pSparseMemoryRequirementCount);18611862memset(reqs, 0, sizeof(reqs));1863for (unsigned i = 0; i < ARRAY_SIZE(reqs); ++i)1864reqs[i].sType = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2;18651866radv_GetImageSparseMemoryRequirements2(device, &info, &reqs_cnt, reqs);18671868for (unsigned i = 0; i < reqs_cnt; ++i)1869pSparseMemoryRequirements[i] = reqs[i].memoryRequirements;1870*pSparseMemoryRequirementCount = reqs_cnt;1871}18721873void1874radv_GetPhysicalDeviceExternalBufferProperties(1875VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,1876VkExternalBufferProperties *pExternalBufferProperties)1877{1878VkExternalMemoryFeatureFlagBits flags = 0;1879VkExternalMemoryHandleTypeFlags export_flags = 0;1880VkExternalMemoryHandleTypeFlags compat_flags = 0;1881switch (pExternalBufferInfo->handleType) {1882case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:1883case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:1884flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;1885compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |1886VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;1887break;1888case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:1889flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;1890compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;1891break;1892default:1893break;1894}1895pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties){1896.externalMemoryFeatures = flags,1897.exportFromImportedHandleTypes = export_flags,1898.compatibleHandleTypes = compat_flags,1899};1900}19011902/* DCC channel type categories within which formats can be reinterpreted1903* while keeping the same DCC encoding. The swizzle must also match. */1904enum dcc_channel_type {1905dcc_channel_float32,1906dcc_channel_uint32,1907dcc_channel_sint32,1908dcc_channel_float16,1909dcc_channel_uint16,1910dcc_channel_sint16,1911dcc_channel_uint_10_10_10_2,1912dcc_channel_uint8,1913dcc_channel_sint8,1914dcc_channel_incompatible,1915};19161917/* Return the type of DCC encoding. */1918static enum dcc_channel_type1919radv_get_dcc_channel_type(const struct util_format_description *desc)1920{1921int i;19221923/* Find the first non-void channel. */1924for (i = 0; i < desc->nr_channels; i++)1925if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)1926break;1927if (i == desc->nr_channels)1928return dcc_channel_incompatible;19291930switch (desc->channel[i].size) {1931case 32:1932if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)1933return dcc_channel_float32;1934if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)1935return dcc_channel_uint32;1936return dcc_channel_sint32;1937case 16:1938if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)1939return dcc_channel_float16;1940if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)1941return dcc_channel_uint16;1942return dcc_channel_sint16;1943case 10:1944return dcc_channel_uint_10_10_10_2;1945case 8:1946if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)1947return dcc_channel_uint8;1948return dcc_channel_sint8;1949default:1950return dcc_channel_incompatible;1951}1952}19531954/* Return if it's allowed to reinterpret one format as another with DCC enabled. */1955bool1956radv_dcc_formats_compatible(VkFormat format1, VkFormat format2)1957{1958const struct util_format_description *desc1, *desc2;1959enum dcc_channel_type type1, type2;1960int i;19611962if (format1 == format2)1963return true;19641965desc1 = vk_format_description(format1);1966desc2 = vk_format_description(format2);19671968if (desc1->nr_channels != desc2->nr_channels)1969return false;19701971/* Swizzles must be the same. */1972for (i = 0; i < desc1->nr_channels; i++)1973if (desc1->swizzle[i] <= PIPE_SWIZZLE_W && desc2->swizzle[i] <= PIPE_SWIZZLE_W &&1974desc1->swizzle[i] != desc2->swizzle[i])1975return false;19761977type1 = radv_get_dcc_channel_type(desc1);1978type2 = radv_get_dcc_channel_type(desc2);19791980return type1 != dcc_channel_incompatible && type2 != dcc_channel_incompatible && type1 == type2;1981}198219831984