/* * Copyright 2015 Advanced Micro Devices, Inc. * Copyright 2024 Valve Corporation * * SPDX-License-Identifier: MIT */ #include "ac_gpu_info.h" #include "ac_formats.h" #include "ac_gpu_info.h" #include "sid.h" uint32_t ac_translate_buffer_numformat(const struct util_format_description *desc, int first_non_void) { if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT) return V_008F0C_BUF_NUM_FORMAT_FLOAT; assert(first_non_void >= 0); switch (desc->channel[first_non_void].type) { case UTIL_FORMAT_TYPE_SIGNED: case UTIL_FORMAT_TYPE_FIXED: if (desc->channel[first_non_void].size >= 32 || desc->channel[first_non_void].pure_integer) return V_008F0C_BUF_NUM_FORMAT_SINT; else if (desc->channel[first_non_void].normalized) return V_008F0C_BUF_NUM_FORMAT_SNORM; else return V_008F0C_BUF_NUM_FORMAT_SSCALED; break; case UTIL_FORMAT_TYPE_UNSIGNED: if (desc->channel[first_non_void].size >= 32 || desc->channel[first_non_void].pure_integer) return V_008F0C_BUF_NUM_FORMAT_UINT; else if (desc->channel[first_non_void].normalized) return V_008F0C_BUF_NUM_FORMAT_UNORM; else return V_008F0C_BUF_NUM_FORMAT_USCALED; break; case UTIL_FORMAT_TYPE_FLOAT: default: return V_008F0C_BUF_NUM_FORMAT_FLOAT; } } uint32_t ac_translate_buffer_dataformat(const struct util_format_description *desc, int first_non_void) { int i; if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT) return V_008F0C_BUF_DATA_FORMAT_10_11_11; assert(first_non_void >= 0); if (desc->nr_channels == 4 && desc->channel[0].size == 10 && desc->channel[1].size == 10 && desc->channel[2].size == 10 && desc->channel[3].size == 2) return V_008F0C_BUF_DATA_FORMAT_2_10_10_10; /* See whether the components are of the same size. */ for (i = 0; i < desc->nr_channels; i++) { if (desc->channel[first_non_void].size != desc->channel[i].size) return V_008F0C_BUF_DATA_FORMAT_INVALID; } switch (desc->channel[first_non_void].size) { case 8: switch (desc->nr_channels) { case 1: case 3: /* 3 loads */ return V_008F0C_BUF_DATA_FORMAT_8; case 2: return V_008F0C_BUF_DATA_FORMAT_8_8; case 4: return V_008F0C_BUF_DATA_FORMAT_8_8_8_8; } break; case 16: switch (desc->nr_channels) { case 1: case 3: /* 3 loads */ return V_008F0C_BUF_DATA_FORMAT_16; case 2: return V_008F0C_BUF_DATA_FORMAT_16_16; case 4: return V_008F0C_BUF_DATA_FORMAT_16_16_16_16; } break; case 32: switch (desc->nr_channels) { case 1: return V_008F0C_BUF_DATA_FORMAT_32; case 2: return V_008F0C_BUF_DATA_FORMAT_32_32; case 3: return V_008F0C_BUF_DATA_FORMAT_32_32_32; case 4: return V_008F0C_BUF_DATA_FORMAT_32_32_32_32; } break; case 64: /* Legacy double formats. */ switch (desc->nr_channels) { case 1: /* 1 load */ return V_008F0C_BUF_DATA_FORMAT_32_32; case 2: /* 1 load */ return V_008F0C_BUF_DATA_FORMAT_32_32_32_32; case 3: /* 3 loads */ return V_008F0C_BUF_DATA_FORMAT_32_32; case 4: /* 2 loads */ return V_008F0C_BUF_DATA_FORMAT_32_32_32_32; } break; } return V_008F0C_BUF_DATA_FORMAT_INVALID; } uint32_t ac_translate_tex_numformat(const struct util_format_description *desc, int first_non_void) { uint32_t num_format; switch (desc->format) { case PIPE_FORMAT_S8_UINT_Z24_UNORM: num_format = V_008F14_IMG_NUM_FORMAT_UNORM; break; default: if (first_non_void < 0) { if (util_format_is_compressed(desc->format)) { switch (desc->format) { case PIPE_FORMAT_DXT1_SRGB: case PIPE_FORMAT_DXT1_SRGBA: case PIPE_FORMAT_DXT3_SRGBA: case PIPE_FORMAT_DXT5_SRGBA: case PIPE_FORMAT_BPTC_SRGBA: case PIPE_FORMAT_ETC2_SRGB8: case PIPE_FORMAT_ETC2_SRGB8A1: case PIPE_FORMAT_ETC2_SRGBA8: num_format = V_008F14_IMG_NUM_FORMAT_SRGB; break; case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_SNORM: case PIPE_FORMAT_RGTC2_SNORM: case PIPE_FORMAT_LATC2_SNORM: case PIPE_FORMAT_ETC2_R11_SNORM: case PIPE_FORMAT_ETC2_RG11_SNORM: /* implies float, so use SNORM/UNORM to determine whether data is signed or not */ case PIPE_FORMAT_BPTC_RGB_FLOAT: num_format = V_008F14_IMG_NUM_FORMAT_SNORM; break; default: num_format = V_008F14_IMG_NUM_FORMAT_UNORM; break; } } else if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) { num_format = V_008F14_IMG_NUM_FORMAT_UNORM; } else { num_format = V_008F14_IMG_NUM_FORMAT_FLOAT; } } else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { num_format = V_008F14_IMG_NUM_FORMAT_SRGB; } else { switch (desc->channel[first_non_void].type) { case UTIL_FORMAT_TYPE_FLOAT: num_format = V_008F14_IMG_NUM_FORMAT_FLOAT; break; case UTIL_FORMAT_TYPE_SIGNED: if (desc->channel[first_non_void].normalized) num_format = V_008F14_IMG_NUM_FORMAT_SNORM; else if (desc->channel[first_non_void].pure_integer) num_format = V_008F14_IMG_NUM_FORMAT_SINT; else num_format = V_008F14_IMG_NUM_FORMAT_SSCALED; break; case UTIL_FORMAT_TYPE_UNSIGNED: if (desc->channel[first_non_void].normalized) num_format = V_008F14_IMG_NUM_FORMAT_UNORM; else if (desc->channel[first_non_void].pure_integer) num_format = V_008F14_IMG_NUM_FORMAT_UINT; else num_format = V_008F14_IMG_NUM_FORMAT_USCALED; break; default: num_format = V_008F14_IMG_NUM_FORMAT_UNORM; break; } } } return num_format; } uint32_t ac_translate_tex_dataformat(const struct radeon_info *info, const struct util_format_description *desc, int first_non_void) { bool uniform = true; int i; /* Colorspace (return non-RGB formats directly). */ switch (desc->colorspace) { /* Depth stencil formats */ case UTIL_FORMAT_COLORSPACE_ZS: switch (desc->format) { case PIPE_FORMAT_Z16_UNORM: return V_008F14_IMG_DATA_FORMAT_16; case PIPE_FORMAT_X24S8_UINT: case PIPE_FORMAT_S8X24_UINT: /* * Implemented as an 8_8_8_8 data format to fix texture * gathers in stencil sampling. This affects at least * GL45-CTS.texture_cube_map_array.sampling on GFX8. */ if (info->gfx_level <= GFX8) return V_008F14_IMG_DATA_FORMAT_8_8_8_8; if (desc->format == PIPE_FORMAT_X24S8_UINT) return V_008F14_IMG_DATA_FORMAT_8_24; else return V_008F14_IMG_DATA_FORMAT_24_8; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_UINT: return V_008F14_IMG_DATA_FORMAT_8_24; case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8_UINT_Z24_UNORM: return V_008F14_IMG_DATA_FORMAT_24_8; case PIPE_FORMAT_S8_UINT: return V_008F14_IMG_DATA_FORMAT_8; case PIPE_FORMAT_Z32_FLOAT: return V_008F14_IMG_DATA_FORMAT_32; case PIPE_FORMAT_X32_S8X24_UINT: case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: return V_008F14_IMG_DATA_FORMAT_X24_8_32; default: return ~0; } case UTIL_FORMAT_COLORSPACE_YUV: return ~0; /* TODO */ default: break; } if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (desc->format) { case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_SNORM: case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_LATC1_UNORM: return V_008F14_IMG_DATA_FORMAT_BC4; case PIPE_FORMAT_RGTC2_SNORM: case PIPE_FORMAT_LATC2_SNORM: case PIPE_FORMAT_RGTC2_UNORM: case PIPE_FORMAT_LATC2_UNORM: return V_008F14_IMG_DATA_FORMAT_BC5; default: return ~0; } } if (desc->layout == UTIL_FORMAT_LAYOUT_ETC) { switch (desc->format) { case PIPE_FORMAT_ETC1_RGB8: case PIPE_FORMAT_ETC2_RGB8: case PIPE_FORMAT_ETC2_SRGB8: return V_008F14_IMG_DATA_FORMAT_ETC2_RGB; case PIPE_FORMAT_ETC2_RGB8A1: case PIPE_FORMAT_ETC2_SRGB8A1: return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1; case PIPE_FORMAT_ETC2_RGBA8: case PIPE_FORMAT_ETC2_SRGBA8: return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA; case PIPE_FORMAT_ETC2_R11_UNORM: case PIPE_FORMAT_ETC2_R11_SNORM: return V_008F14_IMG_DATA_FORMAT_ETC2_R; case PIPE_FORMAT_ETC2_RG11_UNORM: case PIPE_FORMAT_ETC2_RG11_SNORM: return V_008F14_IMG_DATA_FORMAT_ETC2_RG; default: break; } } if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC) { switch (desc->format) { case PIPE_FORMAT_BPTC_RGBA_UNORM: case PIPE_FORMAT_BPTC_SRGBA: return V_008F14_IMG_DATA_FORMAT_BC7; case PIPE_FORMAT_BPTC_RGB_FLOAT: case PIPE_FORMAT_BPTC_RGB_UFLOAT: return V_008F14_IMG_DATA_FORMAT_BC6; default: return ~0; } } if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) { switch (desc->format) { case PIPE_FORMAT_R8G8_B8G8_UNORM: case PIPE_FORMAT_G8R8_B8R8_UNORM: case PIPE_FORMAT_B8G8_R8G8_UNORM: return V_008F14_IMG_DATA_FORMAT_GB_GR; case PIPE_FORMAT_G8R8_G8B8_UNORM: case PIPE_FORMAT_R8G8_R8B8_UNORM: case PIPE_FORMAT_G8B8_G8R8_UNORM: return V_008F14_IMG_DATA_FORMAT_BG_RG; default: return ~0; } } if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { switch (desc->format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: case PIPE_FORMAT_DXT1_SRGB: case PIPE_FORMAT_DXT1_SRGBA: return V_008F14_IMG_DATA_FORMAT_BC1; case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT3_SRGBA: return V_008F14_IMG_DATA_FORMAT_BC2; case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_DXT5_SRGBA: return V_008F14_IMG_DATA_FORMAT_BC3; default: return ~0; } } if (desc->format == PIPE_FORMAT_R9G9B9E5_FLOAT) { return V_008F14_IMG_DATA_FORMAT_5_9_9_9; } else if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT) { return V_008F14_IMG_DATA_FORMAT_10_11_11; } /* hw cannot support mixed formats (except depth/stencil, since only * depth is read).*/ if (desc->is_mixed && desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) return ~0; if (first_non_void < 0 || first_non_void > 3) return ~0; /* See whether the components are of the same size. */ for (i = 1; i < desc->nr_channels; i++) { uniform = uniform && desc->channel[0].size == desc->channel[i].size; } /* Non-uniform formats. */ if (!uniform) { switch (desc->nr_channels) { case 3: if (desc->channel[0].size == 5 && desc->channel[1].size == 6 && desc->channel[2].size == 5) { return V_008F14_IMG_DATA_FORMAT_5_6_5; } return ~0; case 4: /* 5551 and 1555 UINT formats fail on Gfx8/Carrizo´. */ if (info->family == CHIP_CARRIZO && desc->channel[1].size == 5 && desc->channel[2].size == 5 && desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[first_non_void].pure_integer) return ~0; if (desc->channel[0].size == 5 && desc->channel[1].size == 5 && desc->channel[2].size == 5 && desc->channel[3].size == 1) { return V_008F14_IMG_DATA_FORMAT_1_5_5_5; } if (desc->channel[0].size == 1 && desc->channel[1].size == 5 && desc->channel[2].size == 5 && desc->channel[3].size == 5) { return V_008F14_IMG_DATA_FORMAT_5_5_5_1; } if (desc->channel[0].size == 10 && desc->channel[1].size == 10 && desc->channel[2].size == 10 && desc->channel[3].size == 2) { return V_008F14_IMG_DATA_FORMAT_2_10_10_10; } return ~0; } return ~0; } /* uniform formats */ switch (desc->channel[first_non_void].size) { case 4: switch (desc->nr_channels) { case 4: /* 4444 UINT formats fail on Gfx8/Carrizo´. */ if (info->family == CHIP_CARRIZO && desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[first_non_void].pure_integer) return ~0; return V_008F14_IMG_DATA_FORMAT_4_4_4_4; } break; case 8: switch (desc->nr_channels) { case 1: return V_008F14_IMG_DATA_FORMAT_8; case 2: return V_008F14_IMG_DATA_FORMAT_8_8; case 4: return V_008F14_IMG_DATA_FORMAT_8_8_8_8; } break; case 16: switch (desc->nr_channels) { case 1: return V_008F14_IMG_DATA_FORMAT_16; case 2: return V_008F14_IMG_DATA_FORMAT_16_16; case 4: return V_008F14_IMG_DATA_FORMAT_16_16_16_16; } break; case 32: switch (desc->nr_channels) { case 1: return V_008F14_IMG_DATA_FORMAT_32; case 2: return V_008F14_IMG_DATA_FORMAT_32_32; /* Not supported for render targets */ case 3: return V_008F14_IMG_DATA_FORMAT_32_32_32; case 4: return V_008F14_IMG_DATA_FORMAT_32_32_32_32; } break; case 64: if (desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT && desc->nr_channels == 1) return V_008F14_IMG_DATA_FORMAT_32_32; break; } return ~0; } unsigned ac_get_cb_format(enum amd_gfx_level gfx_level, enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); #define HAS_SIZE(x, y, z, w) \ (desc->channel[0].size == (x) && desc->channel[1].size == (y) && \ desc->channel[2].size == (z) && desc->channel[3].size == (w)) if (format == PIPE_FORMAT_R11G11B10_FLOAT) /* isn't plain */ return V_028C70_COLOR_10_11_11; if (gfx_level >= GFX10_3 && format == PIPE_FORMAT_R9G9B9E5_FLOAT) /* isn't plain */ return V_028C70_COLOR_5_9_9_9; if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) return V_028C70_COLOR_INVALID; /* hw cannot support mixed formats (except depth/stencil, since * stencil is not written to). */ if (desc->is_mixed && desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) return V_028C70_COLOR_INVALID; int first_non_void = util_format_get_first_non_void_channel(format); /* Reject SCALED formats because we don't implement them for CB. */ if (first_non_void >= 0 && first_non_void <= 3 && (desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_UNSIGNED || desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_SIGNED) && !desc->channel[first_non_void].normalized && !desc->channel[first_non_void].pure_integer) return V_028C70_COLOR_INVALID; switch (desc->nr_channels) { case 1: switch (desc->channel[0].size) { case 8: return V_028C70_COLOR_8; case 16: return V_028C70_COLOR_16; case 32: return V_028C70_COLOR_32; case 64: return V_028C70_COLOR_32_32; } break; case 2: if (desc->channel[0].size == desc->channel[1].size) { switch (desc->channel[0].size) { case 8: return V_028C70_COLOR_8_8; case 16: return V_028C70_COLOR_16_16; case 32: return V_028C70_COLOR_32_32; } } else if (HAS_SIZE(8, 24, 0, 0)) { return V_028C70_COLOR_24_8; } else if (HAS_SIZE(24, 8, 0, 0)) { return V_028C70_COLOR_8_24; } break; case 3: if (HAS_SIZE(5, 6, 5, 0)) { return V_028C70_COLOR_5_6_5; } else if (HAS_SIZE(32, 8, 24, 0)) { return V_028C70_COLOR_X24_8_32_FLOAT; } break; case 4: if (desc->channel[0].size == desc->channel[1].size && desc->channel[0].size == desc->channel[2].size && desc->channel[0].size == desc->channel[3].size) { switch (desc->channel[0].size) { case 4: return V_028C70_COLOR_4_4_4_4; case 8: return V_028C70_COLOR_8_8_8_8; case 16: return V_028C70_COLOR_16_16_16_16; case 32: return V_028C70_COLOR_32_32_32_32; } } else if (HAS_SIZE(5, 5, 5, 1)) { return V_028C70_COLOR_1_5_5_5; } else if (HAS_SIZE(1, 5, 5, 5)) { return V_028C70_COLOR_5_5_5_1; } else if (HAS_SIZE(10, 10, 10, 2)) { return V_028C70_COLOR_2_10_10_10; } else if (HAS_SIZE(2, 10, 10, 10)) { return V_028C70_COLOR_10_10_10_2; } break; } return V_028C70_COLOR_INVALID; } unsigned ac_get_cb_number_type(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); int chan = util_format_get_first_non_void_channel(format); if (chan == -1 || desc->channel[chan].type == UTIL_FORMAT_TYPE_FLOAT) { return V_028C70_NUMBER_FLOAT; } else { if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { return V_028C70_NUMBER_SRGB; } else if (desc->channel[chan].type == UTIL_FORMAT_TYPE_SIGNED) { return desc->channel[chan].pure_integer ? V_028C70_NUMBER_SINT : V_028C70_NUMBER_SNORM; } else if (desc->channel[chan].type == UTIL_FORMAT_TYPE_UNSIGNED) { return desc->channel[chan].pure_integer ? V_028C70_NUMBER_UINT : V_028C70_NUMBER_UNORM; } else { return V_028C70_NUMBER_UNORM; } } } unsigned ac_translate_colorswap(enum amd_gfx_level gfx_level, enum pipe_format format, bool do_endian_swap) { const struct util_format_description *desc = util_format_description(format); #define HAS_SWIZZLE(chan, swz) (desc->swizzle[chan] == PIPE_SWIZZLE_##swz) if (format == PIPE_FORMAT_R11G11B10_FLOAT) /* isn't plain */ return V_028C70_SWAP_STD; if (gfx_level >= GFX10_3 && format == PIPE_FORMAT_R9G9B9E5_FLOAT) /* isn't plain */ return V_028C70_SWAP_STD; if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) return ~0U; switch (desc->nr_channels) { case 1: if (HAS_SWIZZLE(0, X)) return V_028C70_SWAP_STD; /* X___ */ else if (HAS_SWIZZLE(3, 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_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_028C70_SWAP_STD : V_028C70_SWAP_STD_REV); else if (HAS_SWIZZLE(0, X) && HAS_SWIZZLE(3, Y)) return V_028C70_SWAP_ALT; /* X__Y */ else if (HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(3, X)) return V_028C70_SWAP_ALT_REV; /* Y__X */ break; case 3: if (HAS_SWIZZLE(0, X)) return (do_endian_swap ? V_028C70_SWAP_STD_REV : V_028C70_SWAP_STD); else if (HAS_SWIZZLE(0, Z)) 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_028C70_SWAP_STD; /* XYZW */ } else if (HAS_SWIZZLE(1, Z) && HAS_SWIZZLE(2, Y)) { return V_028C70_SWAP_STD_REV; /* WZYX */ } else if (HAS_SWIZZLE(1, Y) && HAS_SWIZZLE(2, X)) { return V_028C70_SWAP_ALT; /* ZYXW */ } else if (HAS_SWIZZLE(1, Z) && HAS_SWIZZLE(2, W)) { /* YZWX */ if (desc->is_array) return V_028C70_SWAP_ALT_REV; else return (do_endian_swap ? V_028C70_SWAP_ALT : V_028C70_SWAP_ALT_REV); } break; } return ~0U; } bool ac_is_colorbuffer_format_supported(enum amd_gfx_level gfx_level, enum pipe_format format) { return ac_get_cb_format(gfx_level, format) != V_028C70_COLOR_INVALID && ac_translate_colorswap(gfx_level, format, false) != ~0U; } uint32_t ac_colorformat_endian_swap(uint32_t colorformat) { if (UTIL_ARCH_BIG_ENDIAN) { switch (colorformat) { /* 8-bit buffers. */ case V_028C70_COLOR_8: return V_028C70_ENDIAN_NONE; /* 16-bit buffers. */ case V_028C70_COLOR_5_6_5: case V_028C70_COLOR_1_5_5_5: case V_028C70_COLOR_4_4_4_4: case V_028C70_COLOR_16: case V_028C70_COLOR_8_8: return V_028C70_ENDIAN_8IN16; /* 32-bit buffers. */ case V_028C70_COLOR_8_8_8_8: case V_028C70_COLOR_2_10_10_10: case V_028C70_COLOR_10_10_10_2: case V_028C70_COLOR_8_24: case V_028C70_COLOR_24_8: case V_028C70_COLOR_16_16: return V_028C70_ENDIAN_8IN32; /* 64-bit buffers. */ case V_028C70_COLOR_16_16_16_16: return V_028C70_ENDIAN_8IN16; case V_028C70_COLOR_32_32: return V_028C70_ENDIAN_8IN32; /* 128-bit buffers. */ case V_028C70_COLOR_32_32_32_32: return V_028C70_ENDIAN_8IN32; default: return V_028C70_ENDIAN_NONE; /* Unsupported. */ } } else { return V_028C70_ENDIAN_NONE; } } uint32_t ac_translate_dbformat(enum pipe_format format) { switch (format) { case PIPE_FORMAT_Z16_UNORM: case PIPE_FORMAT_Z16_UNORM_S8_UINT: return V_028040_Z_16; case PIPE_FORMAT_S8_UINT_Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_UINT: return V_028040_Z_24; /* not present on GFX12 */ case PIPE_FORMAT_Z32_FLOAT: case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: return V_028040_Z_32_FLOAT; default: return V_028040_Z_INVALID; } } bool ac_is_zs_format_supported(enum pipe_format format) { return ac_translate_dbformat(format) != V_028040_Z_INVALID; } uint32_t ac_border_color_swizzle(const struct util_format_description *desc) { unsigned bc_swizzle = V_008F20_BC_SWIZZLE_XYZW; if (desc->format == PIPE_FORMAT_S8_UINT) { /* Swizzle of 8-bit stencil format is defined as _x__ but the hw expects XYZW. */ assert(desc->swizzle[1] == PIPE_SWIZZLE_X); return bc_swizzle; } if (desc->swizzle[3] == PIPE_SWIZZLE_X) { /* For the pre-defined border color values (white, opaque * black, transparent black), the only thing that matters is * that the alpha channel winds up in the correct place * (because the RGB channels are all the same) so either of * these enumerations will work. */ if (desc->swizzle[2] == PIPE_SWIZZLE_Y) bc_swizzle = V_008F20_BC_SWIZZLE_WZYX; else bc_swizzle = V_008F20_BC_SWIZZLE_WXYZ; } else if (desc->swizzle[0] == PIPE_SWIZZLE_X) { if (desc->swizzle[1] == PIPE_SWIZZLE_Y) bc_swizzle = V_008F20_BC_SWIZZLE_XYZW; else bc_swizzle = V_008F20_BC_SWIZZLE_XWYZ; } else if (desc->swizzle[1] == PIPE_SWIZZLE_X) { bc_swizzle = V_008F20_BC_SWIZZLE_YXWZ; } else if (desc->swizzle[2] == PIPE_SWIZZLE_X) { bc_swizzle = V_008F20_BC_SWIZZLE_ZYXW; } return bc_swizzle; } /** Linearize and convert luminance/intensity to red. */ enum pipe_format ac_simplify_cb_format(enum pipe_format format) { format = util_format_linear(format); format = util_format_luminance_to_red(format); return util_format_intensity_to_red(format); } bool ac_alpha_is_on_msb(const struct radeon_info *info, enum pipe_format format) { if (info->gfx_level >= GFX11) return false; format = ac_simplify_cb_format(format); const struct util_format_description *desc = util_format_description(format); unsigned comp_swap = ac_translate_colorswap(info->gfx_level, format, false); /* The following code matches the hw behavior. */ if (desc->nr_channels == 1) { return (comp_swap == V_028C70_SWAP_ALT_REV) != (info->family == CHIP_RAVEN2 || info->family == CHIP_RENOIR); } return comp_swap != V_028C70_SWAP_STD_REV && comp_swap != V_028C70_SWAP_ALT_REV; } /* GFX6-8: * - no integer format support * - no depth format support (depth formats without shadow samplers are supported, * but that's not enough) * - only single-channel formats are supported * - limitations of early chips (GFX6 only): no R9G9B9E5 support * * GFX9+: * - all formats are supported */ bool ac_is_reduction_mode_supported(const struct radeon_info *info, enum pipe_format format, bool shadow_samplers) { const struct util_format_description *desc = util_format_description(format); if (info->gfx_level <= GFX8) { /* old HW limitations */ if (info->gfx_level == GFX6 && format == PIPE_FORMAT_R9G9B9E5_FLOAT) return false; /* reject if more than one channel */ if (desc->nr_channels > 1) return false; /* no integer or depth format support */ if (util_format_is_pure_integer(format) || (shadow_samplers && util_format_has_depth(desc))) return false; } return true; }