diff --git a/src/amd/common/ac_formats.c b/src/amd/common/ac_formats.c index ece88f387b1..47420cba847 100644 --- a/src/amd/common/ac_formats.c +++ b/src/amd/common/ac_formats.c @@ -41,3 +41,77 @@ ac_translate_buffer_numformat(const struct util_format_description *desc, 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; +} diff --git a/src/amd/common/ac_formats.h b/src/amd/common/ac_formats.h index a2a54c3aaa0..58827cb4c2e 100644 --- a/src/amd/common/ac_formats.h +++ b/src/amd/common/ac_formats.h @@ -18,6 +18,10 @@ uint32_t ac_translate_buffer_numformat(const struct util_format_description *desc, int first_non_void); +uint32_t +ac_translate_buffer_dataformat(const struct util_format_description *desc, + int first_non_void); + #ifdef __cplusplus } #endif diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c index b61f365306c..c91e85a3ccf 100644 --- a/src/amd/vulkan/radv_formats.c +++ b/src/amd/vulkan/radv_formats.c @@ -29,76 +29,9 @@ uint32_t radv_translate_buffer_dataformat(const struct util_format_description *desc, int first_non_void) { - unsigned type; - int i; - assert(util_format_get_num_planes(desc->format) == 1); - if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT) - return V_008F0C_BUF_DATA_FORMAT_10_11_11; - - assert(first_non_void >= 0); - - type = desc->channel[first_non_void].type; - - if (type == UTIL_FORMAT_TYPE_FIXED) - return V_008F0C_BUF_DATA_FORMAT_INVALID; - 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: - 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: - 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: - /* From the Southern Islands ISA documentation about MTBUF: - * 'Memory reads of data in memory that is 32 or 64 bits do not - * undergo any format conversion.' - */ - if (type != UTIL_FORMAT_TYPE_FLOAT && !desc->channel[first_non_void].pure_integer) - return V_008F0C_BUF_DATA_FORMAT_INVALID; - - 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: - if (type != UTIL_FORMAT_TYPE_FLOAT && desc->nr_channels == 1) - return V_008F0C_BUF_DATA_FORMAT_32_32; - } - - return V_008F0C_BUF_DATA_FORMAT_INVALID; + return ac_translate_buffer_dataformat(desc, first_non_void); } uint32_t @@ -505,11 +438,46 @@ radv_is_storage_image_format_supported(const struct radv_physical_device *pdev, } } +static bool +radv_is_buffer_dataformat_supported(const struct util_format_description *desc, int first_non_void) +{ + uint32_t data_format, type; + + data_format = ac_translate_buffer_dataformat(desc, first_non_void); + if (data_format == V_008F0C_BUF_DATA_FORMAT_INVALID) + return false; + + assert(first_non_void >= 0); + + type = desc->channel[first_non_void].type; + + if (type == UTIL_FORMAT_TYPE_FIXED) + return V_008F0C_BUF_DATA_FORMAT_INVALID; + + if (desc->channel[first_non_void].size <= 16 && desc->nr_channels == 3 && + desc->format != PIPE_FORMAT_R11G11B10_FLOAT) + return false; + + /* From the Southern Islands ISA documentation about MTBUF: + * 'Memory reads of data in memory that is 32 or 64 bits do not + * undergo any format conversion.' + */ + if (desc->channel[first_non_void].size == 32 && type != UTIL_FORMAT_TYPE_FLOAT && + !desc->channel[first_non_void].pure_integer) + return false; + + if (desc->channel[first_non_void].size == 64 && (type == UTIL_FORMAT_TYPE_FLOAT || desc->nr_channels != 1)) + return false; + + return true; +} + bool radv_is_buffer_format_supported(VkFormat format, bool *scaled) { const struct util_format_description *desc = vk_format_description(format); - unsigned data_format, num_format; + unsigned num_format; + if (format == VK_FORMAT_UNDEFINED) return false; @@ -517,8 +485,7 @@ radv_is_buffer_format_supported(VkFormat format, bool *scaled) if (first_non_void < 0) return false; - data_format = radv_translate_buffer_dataformat(desc, first_non_void); - if (data_format == V_008F0C_BUF_DATA_FORMAT_INVALID) + if (!radv_is_buffer_dataformat_supported(desc, first_non_void)) return false; num_format = radv_translate_buffer_numformat(desc, first_non_void); diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index c66411fe487..6c3072942b4 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2460,76 +2460,9 @@ static uint32_t si_translate_buffer_dataformat(struct pipe_screen *screen, const struct util_format_description *desc, int first_non_void) { - int i; - assert(((struct si_screen *)screen)->info.gfx_level <= GFX9); - 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; + return ac_translate_buffer_dataformat(desc, first_non_void); } static uint32_t si_translate_buffer_numformat(struct pipe_screen *screen,