blob: c24ea89300164e2df7fb04ae1d9570225224fe13 [file] [log] [blame]
/*
* 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;
}