X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fvulkan%2Fradv_formats.c;h=2e0a140d395e79f5d44721d10885711fe1ac7fb0;hb=203f60ebf2f64dab3dc77ce9c098a6ae3d2aca43;hp=e276432c2ee156657f7fc49d8aca6a7114ea424e;hpb=b5bb8b54cf285277215fece1bc31051434d58b91;p=mesa.git diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c index e276432c2ee..2e0a140d395 100644 --- a/src/amd/vulkan/radv_formats.c +++ b/src/amd/vulkan/radv_formats.c @@ -26,10 +26,12 @@ #include "vk_format.h" #include "sid.h" -#include "r600d_common.h" + +#include "vk_util.h" #include "util/u_half.h" #include "util/format_srgb.h" +#include "util/format_r11g11b10f.h" uint32_t radv_translate_buffer_dataformat(const struct vk_format_description *desc, int first_non_void) @@ -37,6 +39,8 @@ uint32_t radv_translate_buffer_dataformat(const struct vk_format_description *de unsigned type; int i; + assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE); + if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) return V_008F0C_BUF_DATA_FORMAT_10_11_11; @@ -108,6 +112,8 @@ uint32_t radv_translate_buffer_dataformat(const struct vk_format_description *de uint32_t radv_translate_buffer_numformat(const struct vk_format_description *desc, int first_non_void) { + assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE); + if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) return V_008F0C_BUF_NUM_FORMAT_FLOAT; @@ -144,6 +150,8 @@ uint32_t radv_translate_tex_dataformat(VkFormat format, bool uniform = true; int i; + assert(vk_format_get_plane_count(format) == 1); + if (!desc) return ~0; /* Colorspace (return non-RGB formats directly). */ @@ -178,6 +186,18 @@ uint32_t radv_translate_tex_dataformat(VkFormat format, break; } + if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) { + switch(format) { + /* Don't ask me why this looks inverted. PAL does the same. */ + case VK_FORMAT_G8B8G8R8_422_UNORM: + return V_008F14_IMG_DATA_FORMAT_BG_RG; + case VK_FORMAT_B8G8R8G8_422_UNORM: + return V_008F14_IMG_DATA_FORMAT_GB_GR; + default: + goto out_unknown; + } + } + if (desc->layout == VK_FORMAT_LAYOUT_RGTC) { switch(format) { case VK_FORMAT_BC4_UNORM_BLOCK: @@ -222,6 +242,28 @@ uint32_t radv_translate_tex_dataformat(VkFormat format, } } + if (desc->layout == VK_FORMAT_LAYOUT_ETC) { + switch (format) { + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + return V_008F14_IMG_DATA_FORMAT_ETC2_RGB; + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1; + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA; + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + return V_008F14_IMG_DATA_FORMAT_ETC2_R; + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: + return V_008F14_IMG_DATA_FORMAT_ETC2_RG; + default: + break; + } + } + if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) { return V_008F14_IMG_DATA_FORMAT_5_9_9_9; } else if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { @@ -319,10 +361,8 @@ uint32_t radv_translate_tex_dataformat(VkFormat format, return V_008F14_IMG_DATA_FORMAT_32; case 2: return V_008F14_IMG_DATA_FORMAT_32_32; -#if 0 /* Not supported for render targets */ case 3: return V_008F14_IMG_DATA_FORMAT_32_32_32; -#endif case 4: return V_008F14_IMG_DATA_FORMAT_32_32_32_32; } @@ -337,6 +377,8 @@ uint32_t radv_translate_tex_numformat(VkFormat format, const struct vk_format_description *desc, int first_non_void) { + assert(vk_format_get_plane_count(format) == 1); + switch (format) { case VK_FORMAT_D24_UNORM_S8_UINT: return V_008F14_IMG_NUM_FORMAT_UNORM; @@ -349,10 +391,15 @@ uint32_t radv_translate_tex_numformat(VkFormat format, case VK_FORMAT_BC2_SRGB_BLOCK: case VK_FORMAT_BC3_SRGB_BLOCK: case VK_FORMAT_BC7_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return V_008F14_IMG_NUM_FORMAT_SRGB; case VK_FORMAT_BC4_SNORM_BLOCK: case VK_FORMAT_BC5_SNORM_BLOCK: case VK_FORMAT_BC6H_SFLOAT_BLOCK: + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return V_008F14_IMG_NUM_FORMAT_SNORM; default: return V_008F14_IMG_NUM_FORMAT_UNORM; @@ -394,6 +441,9 @@ uint32_t radv_translate_color_numformat(VkFormat format, int first_non_void) { unsigned ntype; + + assert(vk_format_get_plane_count(format) == 1); + if (first_non_void == -1 || desc->channel[first_non_void].type == VK_FORMAT_TYPE_FLOAT) ntype = V_028C70_NUMBER_FLOAT; else { @@ -497,7 +547,7 @@ static bool radv_is_storage_image_format_supported(struct radv_physical_device * } } -static bool radv_is_buffer_format_supported(VkFormat format) +bool radv_is_buffer_format_supported(VkFormat format, bool *scaled) { const struct vk_format_description *desc = vk_format_description(format); unsigned data_format, num_format; @@ -509,6 +559,8 @@ static bool radv_is_buffer_format_supported(VkFormat format) num_format = radv_translate_buffer_numformat(desc, vk_format_get_first_non_void_channel(format)); + if (scaled) + *scaled = (num_format == V_008F0C_BUF_NUM_FORMAT_SSCALED) || (num_format == V_008F0C_BUF_NUM_FORMAT_USCALED); return data_format != V_008F0C_BUF_DATA_FORMAT_INVALID && num_format != ~0; } @@ -535,7 +587,44 @@ bool radv_is_colorbuffer_format_supported(VkFormat format, bool *blendable) static bool radv_is_zs_format_supported(VkFormat format) { - return radv_translate_dbformat(format) != V_028040_Z_INVALID; + return radv_translate_dbformat(format) != V_028040_Z_INVALID || format == VK_FORMAT_S8_UINT; +} + +static bool radv_is_filter_minmax_format_supported(VkFormat format) +{ + /* From the Vulkan spec 1.1.71: + * + * "The following formats must support the + * VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT feature with + * VK_IMAGE_TILING_OPTIMAL, if they support + * VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT." + */ + /* TODO: enable more formats. */ + switch (format) { + case VK_FORMAT_R8_UNORM: + case VK_FORMAT_R8_SNORM: + case VK_FORMAT_R16_UNORM: + case VK_FORMAT_R16_SNORM: + case VK_FORMAT_R16_SFLOAT: + case VK_FORMAT_R32_SFLOAT: + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return true; + default: + return false; + } +} + +bool +radv_device_supports_etc(struct radv_physical_device *physical_device) +{ + return physical_device->rad_info.family == CHIP_VEGA10 || + physical_device->rad_info.family == CHIP_RAVEN || + physical_device->rad_info.family == CHIP_STONEY; } static void @@ -546,30 +635,74 @@ radv_physical_device_get_format_properties(struct radv_physical_device *physical VkFormatFeatureFlags linear = 0, tiled = 0, buffer = 0; const struct vk_format_description *desc = vk_format_description(format); bool blendable; - if (!desc) { + bool scaled = false; + /* TODO: implement some software emulation of SUBSAMPLED formats. */ + if (!desc || desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) { + out_properties->linearTilingFeatures = linear; + out_properties->optimalTilingFeatures = tiled; + out_properties->bufferFeatures = buffer; + return; + } + + if (desc->layout == VK_FORMAT_LAYOUT_ETC && + !radv_device_supports_etc(physical_device)) { out_properties->linearTilingFeatures = linear; out_properties->optimalTilingFeatures = tiled; out_properties->bufferFeatures = buffer; return; } + if (desc->layout == VK_FORMAT_LAYOUT_MULTIPLANE || + desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) { + uint32_t tiling = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | + VK_FORMAT_FEATURE_TRANSFER_DST_BIT | + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT | + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT; + + /* The subsampled formats have no support for linear filters. */ + if (desc->layout != VK_FORMAT_LAYOUT_SUBSAMPLED) { + tiling |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT; + } + + /* Fails for unknown reasons with linear tiling & subsampled formats. */ + out_properties->linearTilingFeatures = desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED ? 0 : tiling; + out_properties->optimalTilingFeatures = tiling; + out_properties->bufferFeatures = 0; + return; + } + if (radv_is_storage_image_format_supported(physical_device, format)) { tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; } - if (radv_is_buffer_format_supported(format)) { - buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT | - VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | - VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT; + if (radv_is_buffer_format_supported(format, &scaled)) { + buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT; + if (!scaled) + buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT; } if (vk_format_is_depth_or_stencil(format)) { - if (radv_is_zs_format_supported(format)) + if (radv_is_zs_format_supported(format)) { tiled |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; - tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; - tiled |= VK_FORMAT_FEATURE_BLIT_SRC_BIT | - VK_FORMAT_FEATURE_BLIT_DST_BIT; + tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + tiled |= VK_FORMAT_FEATURE_BLIT_SRC_BIT | + VK_FORMAT_FEATURE_BLIT_DST_BIT; + tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | + VK_FORMAT_FEATURE_TRANSFER_DST_BIT; + + if (radv_is_filter_minmax_format_supported(format)) + tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT; + + /* Don't support blitting surfaces with depth/stencil. */ + if (vk_format_is_depth(format) && vk_format_is_stencil(format)) + tiled &= ~VK_FORMAT_FEATURE_BLIT_DST_BIT; + + /* Don't support linear depth surfaces */ + linear = 0; + } } else { bool linear_sampling; if (radv_is_sampler_format_supported(format, &linear_sampling)) { @@ -577,10 +710,21 @@ radv_physical_device_get_format_properties(struct radv_physical_device *physical VK_FORMAT_FEATURE_BLIT_SRC_BIT; tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT; + + if (radv_is_filter_minmax_format_supported(format)) + tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT; + if (linear_sampling) { linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; } + + /* Don't support blitting for R32G32B32 formats. */ + if (format == VK_FORMAT_R32G32B32_SFLOAT || + format == VK_FORMAT_R32G32B32_UINT || + format == VK_FORMAT_R32G32B32_SINT) { + linear &= ~VK_FORMAT_FEATURE_BLIT_SRC_BIT; + } } if (radv_is_colorbuffer_format_supported(format, &blendable)) { linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; @@ -590,6 +734,19 @@ radv_physical_device_get_format_properties(struct radv_physical_device *physical tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; } } + if (tiled && !scaled) { + tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | + VK_FORMAT_FEATURE_TRANSFER_DST_BIT; + } + + /* Tiled formatting does not support NPOT pixel sizes */ + if (!util_is_power_of_two_or_zero(vk_format_get_blocksize(format))) + tiled = 0; + } + + if (linear && !scaled) { + linear |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | + VK_FORMAT_FEATURE_TRANSFER_DST_BIT; } if (format == VK_FORMAT_R32_UINT || format == VK_FORMAT_R32_SINT) { @@ -598,6 +755,29 @@ radv_physical_device_get_format_properties(struct radv_physical_device *physical tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT; } + switch(format) { + case VK_FORMAT_A2R10G10B10_SNORM_PACK32: + case VK_FORMAT_A2B10G10R10_SNORM_PACK32: + case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: + case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: + case VK_FORMAT_A2R10G10B10_SINT_PACK32: + case VK_FORMAT_A2B10G10R10_SINT_PACK32: + if (physical_device->rad_info.chip_class <= GFX8 && + physical_device->rad_info.family != CHIP_STONEY) { + buffer &= ~(VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT); + linear = 0; + tiled = 0; + } + break; + default: + break; + } + + /* addrlib does not support linear compressed textures. */ + if (vk_format_is_compressed(format)) + linear = 0; + out_properties->linearTilingFeatures = linear; out_properties->optimalTilingFeatures = tiled; out_properties->bufferFeatures = buffer; @@ -730,9 +910,6 @@ uint32_t radv_translate_dbformat(VkFormat format) case VK_FORMAT_D16_UNORM: case VK_FORMAT_D16_UNORM_S8_UINT: return V_028040_Z_16; - case VK_FORMAT_X8_D24_UNORM_PACK32: - case VK_FORMAT_D24_UNORM_S8_UINT: - return V_028040_Z_24; /* deprecated on SI */ case VK_FORMAT_D32_SFLOAT: case VK_FORMAT_D32_SFLOAT_S8_UINT: return V_028040_Z_32_FLOAT; @@ -748,7 +925,7 @@ unsigned radv_translate_colorswap(VkFormat format, bool do_endian_swap) #define HAS_SWIZZLE(chan,swz) (desc->swizzle[chan] == VK_SWIZZLE_##swz) if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) - return V_0280A0_SWAP_STD; + return V_028C70_SWAP_STD; if (desc->layout != VK_FORMAT_LAYOUT_PLAIN) return ~0U; @@ -756,45 +933,45 @@ unsigned radv_translate_colorswap(VkFormat format, bool do_endian_swap) switch (desc->nr_channels) { case 1: if (HAS_SWIZZLE(0,X)) - return V_0280A0_SWAP_STD; /* X___ */ + return V_028C70_SWAP_STD; /* X___ */ else if (HAS_SWIZZLE(3,X)) - return V_0280A0_SWAP_ALT_REV; /* ___X */ + return V_028C70_SWAP_ALT_REV; /* ___X */ break; case 2: if ((HAS_SWIZZLE(0,X) && HAS_SWIZZLE(1,Y)) || (HAS_SWIZZLE(0,X) && HAS_SWIZZLE(1,NONE)) || (HAS_SWIZZLE(0,NONE) && HAS_SWIZZLE(1,Y))) - return V_0280A0_SWAP_STD; /* XY__ */ + return V_028C70_SWAP_STD; /* XY__ */ else if ((HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(1,X)) || (HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(1,NONE)) || (HAS_SWIZZLE(0,NONE) && HAS_SWIZZLE(1,X))) /* YX__ */ - return (do_endian_swap ? V_0280A0_SWAP_STD : V_0280A0_SWAP_STD_REV); + return (do_endian_swap ? V_028C70_SWAP_STD : V_028C70_SWAP_STD_REV); else if (HAS_SWIZZLE(0,X) && HAS_SWIZZLE(3,Y)) - return V_0280A0_SWAP_ALT; /* X__Y */ + return V_028C70_SWAP_ALT; /* X__Y */ else if (HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(3,X)) - return V_0280A0_SWAP_ALT_REV; /* Y__X */ + return V_028C70_SWAP_ALT_REV; /* Y__X */ break; case 3: if (HAS_SWIZZLE(0,X)) - return (do_endian_swap ? V_0280A0_SWAP_STD_REV : V_0280A0_SWAP_STD); + return (do_endian_swap ? V_028C70_SWAP_STD_REV : V_028C70_SWAP_STD); else if (HAS_SWIZZLE(0,Z)) - return V_0280A0_SWAP_STD_REV; /* ZYX */ + return V_028C70_SWAP_STD_REV; /* ZYX */ break; case 4: /* check the middle channels, the 1st and 4th channel can be NONE */ if (HAS_SWIZZLE(1,Y) && HAS_SWIZZLE(2,Z)) { - return V_0280A0_SWAP_STD; /* XYZW */ + return V_028C70_SWAP_STD; /* XYZW */ } else if (HAS_SWIZZLE(1,Z) && HAS_SWIZZLE(2,Y)) { - return V_0280A0_SWAP_STD_REV; /* WZYX */ + return V_028C70_SWAP_STD_REV; /* WZYX */ } else if (HAS_SWIZZLE(1,Y) && HAS_SWIZZLE(2,X)) { - return V_0280A0_SWAP_ALT; /* ZYXW */ + return V_028C70_SWAP_ALT; /* ZYXW */ } else if (HAS_SWIZZLE(1,Z) && HAS_SWIZZLE(2,W)) { /* YZWX */ if (desc->is_array) - return V_0280A0_SWAP_ALT_REV; + return V_028C70_SWAP_ALT_REV; else - return (do_endian_swap ? V_0280A0_SWAP_ALT : V_0280A0_SWAP_ALT_REV); + return (do_endian_swap ? V_028C70_SWAP_ALT : V_028C70_SWAP_ALT_REV); } break; } @@ -805,143 +982,99 @@ bool radv_format_pack_clear_color(VkFormat format, uint32_t clear_vals[2], VkClearColorValue *value) { - uint8_t r = 0, g = 0, b = 0, a = 0; const struct vk_format_description *desc = vk_format_description(format); - if (vk_format_get_component_bits(format, VK_FORMAT_COLORSPACE_RGB, 0) <= 8) { - if (desc->colorspace == VK_FORMAT_COLORSPACE_RGB) { - r = float_to_ubyte(value->float32[0]); - g = float_to_ubyte(value->float32[1]); - b = float_to_ubyte(value->float32[2]); - a = float_to_ubyte(value->float32[3]); - } else if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) { - r = util_format_linear_float_to_srgb_8unorm(value->float32[0]); - g = util_format_linear_float_to_srgb_8unorm(value->float32[1]); - b = util_format_linear_float_to_srgb_8unorm(value->float32[2]); - a = float_to_ubyte(value->float32[3]); - } - } - switch (format) { - case VK_FORMAT_R8_UNORM: - case VK_FORMAT_R8_SRGB: - clear_vals[0] = r; - clear_vals[1] = 0; - break; - case VK_FORMAT_R8G8_UNORM: - case VK_FORMAT_R8G8_SRGB: - clear_vals[0] = r | g << 8; - clear_vals[1] = 0; - break; - case VK_FORMAT_R8G8B8A8_SRGB: - case VK_FORMAT_R8G8B8A8_UNORM: - clear_vals[0] = r | g << 8 | b << 16 | a << 24; - clear_vals[1] = 0; - break; - case VK_FORMAT_B8G8R8A8_SRGB: - case VK_FORMAT_B8G8R8A8_UNORM: - clear_vals[0] = b | g << 8 | r << 16 | a << 24; - clear_vals[1] = 0; - break; - case VK_FORMAT_A8B8G8R8_UNORM_PACK32: - case VK_FORMAT_A8B8G8R8_SRGB_PACK32: - clear_vals[0] = r | g << 8 | b << 16 | a << 24; - clear_vals[1] = 0; - break; - case VK_FORMAT_R8_UINT: - clear_vals[0] = value->uint32[0] & 0xff; - clear_vals[1] = 0; - break; - case VK_FORMAT_R16_UINT: - clear_vals[0] = value->uint32[0] & 0xffff; - clear_vals[1] = 0; - break; - case VK_FORMAT_R8G8_UINT: - clear_vals[0] = value->uint32[0] & 0xff; - clear_vals[0] |= (value->uint32[1] & 0xff) << 8; - clear_vals[1] = 0; - break; - case VK_FORMAT_R8G8B8A8_UINT: - clear_vals[0] = value->uint32[0] & 0xff; - clear_vals[0] |= (value->uint32[1] & 0xff) << 8; - clear_vals[0] |= (value->uint32[2] & 0xff) << 16; - clear_vals[0] |= (value->uint32[3] & 0xff) << 24; - clear_vals[1] = 0; - break; - case VK_FORMAT_A8B8G8R8_UINT_PACK32: - clear_vals[0] = value->uint32[0] & 0xff; - clear_vals[0] |= (value->uint32[1] & 0xff) << 8; - clear_vals[0] |= (value->uint32[2] & 0xff) << 16; - clear_vals[0] |= (value->uint32[3] & 0xff) << 24; - clear_vals[1] = 0; - break; - case VK_FORMAT_R16G16_UINT: - clear_vals[0] = value->uint32[0] & 0xffff; - clear_vals[0] |= (value->uint32[1] & 0xffff) << 16; - clear_vals[1] = 0; - break; - case VK_FORMAT_R16G16B16A16_UINT: - clear_vals[0] = value->uint32[0] & 0xffff; - clear_vals[0] |= (value->uint32[1] & 0xffff) << 16; - clear_vals[1] = value->uint32[2] & 0xffff; - clear_vals[1] |= (value->uint32[3] & 0xffff) << 16; - break; - case VK_FORMAT_R32_UINT: - clear_vals[0] = value->uint32[0]; - clear_vals[1] = 0; - break; - case VK_FORMAT_R32G32_UINT: - clear_vals[0] = value->uint32[0]; - clear_vals[1] = value->uint32[1]; - break; - case VK_FORMAT_R32_SINT: - clear_vals[0] = value->int32[0]; - clear_vals[1] = 0; - break; - case VK_FORMAT_R16_SFLOAT: - clear_vals[0] = util_float_to_half(value->float32[0]); - clear_vals[1] = 0; - break; - case VK_FORMAT_R16G16_SFLOAT: - clear_vals[0] = util_float_to_half(value->float32[0]); - clear_vals[0] |= (uint32_t)util_float_to_half(value->float32[1]) << 16; - clear_vals[1] = 0; - break; - case VK_FORMAT_R16G16B16A16_SFLOAT: - clear_vals[0] = util_float_to_half(value->float32[0]); - clear_vals[0] |= (uint32_t)util_float_to_half(value->float32[1]) << 16; - clear_vals[1] = util_float_to_half(value->float32[2]); - clear_vals[1] |= (uint32_t)util_float_to_half(value->float32[3]) << 16; - break; - case VK_FORMAT_R16_UNORM: - clear_vals[0] = ((uint16_t)util_iround(CLAMP(value->float32[0], 0.0f, 1.0f) * 0xffff)) & 0xffff; - clear_vals[1] = 0; - break; - case VK_FORMAT_R16G16_UNORM: - clear_vals[0] = ((uint16_t)util_iround(CLAMP(value->float32[0], 0.0f, 1.0f) * 0xffff)) & 0xffff; - clear_vals[0] |= ((uint16_t)util_iround(CLAMP(value->float32[1], 0.0f, 1.0f) * 0xffff)) << 16; + if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { + clear_vals[0] = float3_to_r11g11b10f(value->float32); clear_vals[1] = 0; - break; - case VK_FORMAT_R16G16B16A16_UNORM: - clear_vals[0] = ((uint16_t)util_iround(CLAMP(value->float32[0], 0.0f, 1.0f) * 0xffff)) & 0xffff; - clear_vals[0] |= ((uint16_t)util_iround(CLAMP(value->float32[1], 0.0f, 1.0f) * 0xffff)) << 16; - clear_vals[1] = ((uint16_t)util_iround(CLAMP(value->float32[2], 0.0f, 1.0f) * 0xffff)) & 0xffff; - clear_vals[1] |= ((uint16_t)util_iround(CLAMP(value->float32[3], 0.0f, 1.0f) * 0xffff)) << 16; - break; - case VK_FORMAT_A2B10G10R10_UNORM_PACK32: - /* TODO */ + return true; + } + + if (desc->layout != VK_FORMAT_LAYOUT_PLAIN) { + fprintf(stderr, "failed to fast clear for non-plain format %d\n", format); return false; - case VK_FORMAT_R32G32_SFLOAT: - clear_vals[0] = fui(value->float32[0]); - clear_vals[1] = fui(value->float32[1]); - break; - case VK_FORMAT_R32_SFLOAT: - clear_vals[1] = 0; - clear_vals[0] = fui(value->float32[0]); - break; - default: - fprintf(stderr, "failed to fast clear %d\n", format); + } + + if (!util_is_power_of_two_or_zero(desc->block.bits)) { + fprintf(stderr, "failed to fast clear for NPOT format %d\n", format); return false; } + + if (desc->block.bits > 64) { + /* + * We have a 128 bits format, check if the first 3 components are the same. + * Every elements has to be 32 bits since we don't support 64-bit formats, + * and we can skip swizzling checks as alpha always comes last for these and + * we do not care about the rest as they have to be the same. + */ + if (desc->channel[0].type == VK_FORMAT_TYPE_FLOAT) { + if (value->float32[0] != value->float32[1] || + value->float32[0] != value->float32[2]) + return false; + } else { + if (value->uint32[0] != value->uint32[1] || + value->uint32[0] != value->uint32[2]) + return false; + } + clear_vals[0] = value->uint32[0]; + clear_vals[1] = value->uint32[3]; + return true; + } + uint64_t clear_val = 0; + + for (unsigned c = 0; c < 4; ++c) { + if (desc->swizzle[c] >= 4) + continue; + + const struct vk_format_channel_description *channel = &desc->channel[desc->swizzle[c]]; + assert(channel->size); + + uint64_t v = 0; + if (channel->pure_integer) { + v = value->uint32[c] & ((1ULL << channel->size) - 1); + } else if (channel->normalized) { + if (channel->type == VK_FORMAT_TYPE_UNSIGNED && + desc->swizzle[c] < 3 && + desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) { + assert(channel->size == 8); + + v = util_format_linear_float_to_srgb_8unorm(value->float32[c]); + } else { + float f = MIN2(value->float32[c], 1.0f); + + if (channel->type == VK_FORMAT_TYPE_UNSIGNED) { + f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1); + } else { + f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1); + } + + /* The hardware rounds before conversion. */ + if (f > 0) + f += 0.5f; + else + f -= 0.5f; + + v = (uint64_t)f; + } + } else if (channel->type == VK_FORMAT_TYPE_FLOAT) { + if (channel->size == 32) { + memcpy(&v, &value->float32[c], 4); + } else if(channel->size == 16) { + v = util_float_to_half(value->float32[c]); + } else { + fprintf(stderr, "failed to fast clear for unhandled float size in format %d\n", format); + return false; + } + } else { + fprintf(stderr, "failed to fast clear for unhandled component type in format %d\n", format); + return false; + } + clear_val |= (v & ((1ULL << channel->size) - 1)) << channel->shift; + } + + clear_vals[0] = clear_val; + clear_vals[1] = clear_val >> 32; + return true; } @@ -957,28 +1090,36 @@ void radv_GetPhysicalDeviceFormatProperties( pFormatProperties); } -VkResult radv_GetPhysicalDeviceImageFormatProperties( +void radv_GetPhysicalDeviceFormatProperties2( VkPhysicalDevice physicalDevice, VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags createFlags, - VkImageFormatProperties* pImageFormatProperties) + VkFormatProperties2* pFormatProperties) { RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice); + + radv_physical_device_get_format_properties(physical_device, + format, + &pFormatProperties->formatProperties); +} + +static VkResult radv_get_image_format_properties(struct radv_physical_device *physical_device, + const VkPhysicalDeviceImageFormatInfo2 *info, + VkImageFormatProperties *pImageFormatProperties) + +{ VkFormatProperties format_props; VkFormatFeatureFlags format_feature_flags; VkExtent3D maxExtent; uint32_t maxMipLevels; uint32_t maxArraySize; VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT; + const struct vk_format_description *desc = vk_format_description(info->format); - radv_physical_device_get_format_properties(physical_device, format, + radv_physical_device_get_format_properties(physical_device, info->format, &format_props); - if (tiling == VK_IMAGE_TILING_LINEAR) { + if (info->tiling == VK_IMAGE_TILING_LINEAR) { format_feature_flags = format_props.linearTilingFeatures; - } else if (tiling == VK_IMAGE_TILING_OPTIMAL) { + } else if (info->tiling == VK_IMAGE_TILING_OPTIMAL) { format_feature_flags = format_props.optimalTilingFeatures; } else { unreachable("bad VkImageTiling"); @@ -987,7 +1128,10 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties( if (format_feature_flags == 0) goto unsupported; - switch (type) { + if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(info->format)) + goto unsupported; + + switch (info->type) { default: unreachable("bad vkimage type\n"); case VK_IMAGE_TYPE_1D: @@ -1013,39 +1157,89 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties( break; } - if (tiling == VK_IMAGE_TILING_OPTIMAL && - type == VK_IMAGE_TYPE_2D && + if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) { + /* Might be able to support but the entire format support is + * messy, so taking the lazy way out. */ + maxArraySize = 1; + } + + if (info->tiling == VK_IMAGE_TILING_OPTIMAL && + info->type == VK_IMAGE_TYPE_2D && (format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) && - !(createFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && - !(usage & VK_IMAGE_USAGE_STORAGE_BIT)) { + !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)) { sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT; } - if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) { + if (info->tiling == VK_IMAGE_TILING_LINEAR && + (info->format == VK_FORMAT_R32G32B32_SFLOAT || + info->format == VK_FORMAT_R32G32B32_SINT || + info->format == VK_FORMAT_R32G32B32_UINT)) { + /* R32G32B32 is a weird format and the driver currently only + * supports the barely minimum. + * TODO: Implement more if we really need to. + */ + if (info->type == VK_IMAGE_TYPE_3D) + goto unsupported; + maxArraySize = 1; + maxMipLevels = 1; + } + + + /* We can't create 3d compressed 128bpp images that can be rendered to on GFX9 */ + if (physical_device->rad_info.chip_class >= GFX9 && + info->type == VK_IMAGE_TYPE_3D && + vk_format_get_blocksizebits(info->format) == 128 && + vk_format_is_compressed(info->format) && + (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) && + ((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) || + (info->usage & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))) { + goto unsupported; + } + + if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) { if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { goto unsupported; } } - if (usage & VK_IMAGE_USAGE_STORAGE_BIT) { + if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) { if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) { goto unsupported; } } - if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) { goto unsupported; } } - if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { if (!(format_feature_flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { goto unsupported; } } + if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { + if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) { + goto unsupported; + } + } + + if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { + if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { + goto unsupported; + } + } + + if (info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { + if (!(format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))) { + goto unsupported; + } + } + *pImageFormatProperties = (VkImageFormatProperties) { .maxExtent = maxExtent, .maxMipLevels = maxMipLevels, @@ -1071,6 +1265,158 @@ unsupported: return VK_ERROR_FORMAT_NOT_SUPPORTED; } +VkResult radv_GetPhysicalDeviceImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags createFlags, + VkImageFormatProperties* pImageFormatProperties) +{ + RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice); + + const VkPhysicalDeviceImageFormatInfo2 info = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + .pNext = NULL, + .format = format, + .type = type, + .tiling = tiling, + .usage = usage, + .flags = createFlags, + }; + + return radv_get_image_format_properties(physical_device, &info, + pImageFormatProperties); +} + +static void +get_external_image_format_properties(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, + VkExternalMemoryHandleTypeFlagBits handleType, + VkExternalMemoryProperties *external_properties) +{ + VkExternalMemoryFeatureFlagBits flags = 0; + VkExternalMemoryHandleTypeFlags export_flags = 0; + VkExternalMemoryHandleTypeFlags compat_flags = 0; + switch (handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + switch (pImageFormatInfo->type) { + case VK_IMAGE_TYPE_2D: + flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT|VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + break; + default: + break; + } + break; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + break; + default: + break; + } + + *external_properties = (VkExternalMemoryProperties) { + .externalMemoryFeatures = flags, + .exportFromImportedHandleTypes = export_flags, + .compatibleHandleTypes = compat_flags, + }; +} + +VkResult radv_GetPhysicalDeviceImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2 *base_info, + VkImageFormatProperties2 *base_props) +{ + RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice); + const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; + VkExternalImageFormatProperties *external_props = NULL; + VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL; + VkResult result; + + result = radv_get_image_format_properties(physical_device, base_info, + &base_props->imageFormatProperties); + if (result != VK_SUCCESS) + return result; + + /* Extract input structs */ + vk_foreach_struct_const(s, base_info->pNext) { + switch (s->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: + external_info = (const void *) s; + break; + default: + break; + } + } + + /* Extract output structs */ + vk_foreach_struct(s, base_props->pNext) { + switch (s->sType) { + case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: + external_props = (void *) s; + break; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: + ycbcr_props = (void *) s; + break; + default: + break; + } + } + + /* From the Vulkan 1.0.97 spec: + * + * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will + * behave as if VkPhysicalDeviceExternalImageFormatInfo was not + * present and VkExternalImageFormatProperties will be ignored. + */ + if (external_info && external_info->handleType != 0) { + switch (external_info->handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + get_external_image_format_properties(base_info, external_info->handleType, + &external_props->externalMemoryProperties); + break; + default: + /* From the Vulkan 1.0.97 spec: + * + * If handleType is not compatible with the [parameters] specified + * in VkPhysicalDeviceImageFormatInfo2, then + * vkGetPhysicalDeviceImageFormatProperties2 returns + * VK_ERROR_FORMAT_NOT_SUPPORTED. + */ + result = vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED, + "unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x", + external_info->handleType); + goto fail; + } + } + + if (ycbcr_props) { + ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(base_info->format); + } + + return VK_SUCCESS; + +fail: + if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) { + /* From the Vulkan 1.0.97 spec: + * + * If the combination of parameters to + * vkGetPhysicalDeviceImageFormatProperties2 is not supported by + * the implementation for use in vkCreateImage, then all members of + * imageFormatProperties will be filled with zero. + */ + base_props->imageFormatProperties = (VkImageFormatProperties) {0}; + } + + return result; +} + void radv_GetPhysicalDeviceSparseImageFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, @@ -1084,3 +1430,128 @@ void radv_GetPhysicalDeviceSparseImageFormatProperties( /* Sparse images are not yet supported. */ *pNumProperties = 0; } + +void radv_GetPhysicalDeviceSparseImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, + uint32_t *pPropertyCount, + VkSparseImageFormatProperties2 *pProperties) +{ + /* Sparse images are not yet supported. */ + *pPropertyCount = 0; +} + +void radv_GetPhysicalDeviceExternalBufferProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, + VkExternalBufferProperties *pExternalBufferProperties) +{ + VkExternalMemoryFeatureFlagBits flags = 0; + VkExternalMemoryHandleTypeFlags export_flags = 0; + VkExternalMemoryHandleTypeFlags compat_flags = 0; + switch(pExternalBufferInfo->handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + break; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + break; + default: + break; + } + pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties) { + .externalMemoryFeatures = flags, + .exportFromImportedHandleTypes = export_flags, + .compatibleHandleTypes = compat_flags, + }; +} + +/* DCC channel type categories within which formats can be reinterpreted + * while keeping the same DCC encoding. The swizzle must also match. */ +enum dcc_channel_type { + dcc_channel_float32, + dcc_channel_uint32, + dcc_channel_sint32, + dcc_channel_float16, + dcc_channel_uint16, + dcc_channel_sint16, + dcc_channel_uint_10_10_10_2, + dcc_channel_uint8, + dcc_channel_sint8, + dcc_channel_incompatible, +}; + +/* Return the type of DCC encoding. */ +static enum dcc_channel_type +radv_get_dcc_channel_type(const struct vk_format_description *desc) +{ + int i; + + /* Find the first non-void channel. */ + for (i = 0; i < desc->nr_channels; i++) + if (desc->channel[i].type != VK_FORMAT_TYPE_VOID) + break; + if (i == desc->nr_channels) + return dcc_channel_incompatible; + + switch (desc->channel[i].size) { + case 32: + if (desc->channel[i].type == VK_FORMAT_TYPE_FLOAT) + return dcc_channel_float32; + if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED) + return dcc_channel_uint32; + return dcc_channel_sint32; + case 16: + if (desc->channel[i].type == VK_FORMAT_TYPE_FLOAT) + return dcc_channel_float16; + if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED) + return dcc_channel_uint16; + return dcc_channel_sint16; + case 10: + return dcc_channel_uint_10_10_10_2; + case 8: + if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED) + return dcc_channel_uint8; + return dcc_channel_sint8; + default: + return dcc_channel_incompatible; + } +} + +/* Return if it's allowed to reinterpret one format as another with DCC enabled. */ +bool radv_dcc_formats_compatible(VkFormat format1, + VkFormat format2) +{ + const struct vk_format_description *desc1, *desc2; + enum dcc_channel_type type1, type2; + int i; + + if (format1 == format2) + return true; + + desc1 = vk_format_description(format1); + desc2 = vk_format_description(format2); + + if (desc1->nr_channels != desc2->nr_channels) + return false; + + /* Swizzles must be the same. */ + for (i = 0; i < desc1->nr_channels; i++) + if (desc1->swizzle[i] <= VK_SWIZZLE_W && + desc2->swizzle[i] <= VK_SWIZZLE_W && + desc1->swizzle[i] != desc2->swizzle[i]) + return false; + + type1 = radv_get_dcc_channel_type(desc1); + type2 = radv_get_dcc_channel_type(desc2); + + return type1 != dcc_channel_incompatible && + type2 != dcc_channel_incompatible && + type1 == type2; +} +