From beb5577e12593559f87ceae2dec090dff4d488a2 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 24 Jul 2024 14:58:10 -0700 Subject: [PATCH] freedreno: Extract out common UBWC helper And re-use in gallium driver. Signed-off-by: Rob Clark Part-of: --- src/freedreno/common/freedreno_ubwc.h | 115 ++++++++++++++++++ src/freedreno/vulkan/tu_formats.cc | 108 +--------------- .../drivers/freedreno/a6xx/fd6_resource.cc | 41 ++----- 3 files changed, 130 insertions(+), 134 deletions(-) create mode 100644 src/freedreno/common/freedreno_ubwc.h diff --git a/src/freedreno/common/freedreno_ubwc.h b/src/freedreno/common/freedreno_ubwc.h new file mode 100644 index 00000000000..afbcf473a2b --- /dev/null +++ b/src/freedreno/common/freedreno_ubwc.h @@ -0,0 +1,115 @@ +/* + * Copyright © Google, Inc. + * SPDX-License-Identifier: MIT + */ + +#ifndef __FREEDRENO_UBWC_H__ +#define __FREEDRENO_UBWC_H__ + +#include "util/format/u_format.h" + +#include "freedreno_dev_info.h" + +enum fd6_ubwc_compat_type { + FD6_UBWC_UNKNOWN_COMPAT, + FD6_UBWC_R8G8_UNORM, + FD6_UBWC_R8G8_INT, + FD6_UBWC_R8G8B8A8_UNORM, + FD6_UBWC_R8G8B8A8_INT, + FD6_UBWC_B8G8R8A8_UNORM, + FD6_UBWC_R16G16_UNORM, + FD6_UBWC_R16G16_INT, + FD6_UBWC_R16G16B16A16_UNORM, + FD6_UBWC_R16G16B16A16_INT, + FD6_UBWC_R32_INT, + FD6_UBWC_R32G32_INT, + FD6_UBWC_R32G32B32A32_INT, + FD6_UBWC_R32_FLOAT, +}; + +static inline enum fd6_ubwc_compat_type +fd6_ubwc_compat_mode(const struct fd_dev_info *info, enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8_SRGB: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R8G8_INT : FD6_UBWC_R8G8_UNORM; + + case PIPE_FORMAT_R8G8_SNORM: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R8G8_INT : FD6_UBWC_UNKNOWN_COMPAT; + + case PIPE_FORMAT_R8G8_UINT: + case PIPE_FORMAT_R8G8_SINT: + return FD6_UBWC_R8G8_INT; + + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_R8G8B8A8_SRGB: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R8G8B8A8_INT : FD6_UBWC_R8G8B8A8_UNORM; + + case PIPE_FORMAT_R8G8B8A8_SNORM: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R8G8B8A8_INT : FD6_UBWC_UNKNOWN_COMPAT; + + case PIPE_FORMAT_R8G8B8A8_UINT: + case PIPE_FORMAT_R8G8B8A8_SINT: + return FD6_UBWC_R8G8B8A8_INT; + + case PIPE_FORMAT_R16G16_UNORM: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R16G16_INT : FD6_UBWC_R16G16_UNORM; + + case PIPE_FORMAT_R16G16_SNORM: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R16G16_INT : FD6_UBWC_UNKNOWN_COMPAT; + + case PIPE_FORMAT_R16G16_UINT: + case PIPE_FORMAT_R16G16_SINT: + return FD6_UBWC_R16G16_INT; + + case PIPE_FORMAT_R16G16B16A16_UNORM: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R16G16B16A16_INT : FD6_UBWC_R16G16B16A16_UNORM; + + case PIPE_FORMAT_R16G16B16A16_SNORM: + return info->a7xx.ubwc_unorm_snorm_int_compatible ? + FD6_UBWC_R16G16B16A16_INT : FD6_UBWC_UNKNOWN_COMPAT; + + case PIPE_FORMAT_R16G16B16A16_UINT: + case PIPE_FORMAT_R16G16B16A16_SINT: + return FD6_UBWC_R16G16B16A16_INT; + + case PIPE_FORMAT_R32_UINT: + case PIPE_FORMAT_R32_SINT: + return FD6_UBWC_R32_INT; + + case PIPE_FORMAT_R32G32_UINT: + case PIPE_FORMAT_R32G32_SINT: + return FD6_UBWC_R32G32_INT; + + case PIPE_FORMAT_R32G32B32A32_UINT: + case PIPE_FORMAT_R32G32B32A32_SINT: + return FD6_UBWC_R32G32B32A32_INT; + + case PIPE_FORMAT_Z32_FLOAT: + case PIPE_FORMAT_R32_FLOAT: + /* TODO: a630 blob allows these, but not a660. When is it legal? */ + return FD6_UBWC_UNKNOWN_COMPAT; + + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_B8G8R8A8_SRGB: + /* The blob doesn't list these as compatible, but they surely are. + * freedreno's happy to cast between them, and zink would really like + * to. + */ + return FD6_UBWC_B8G8R8A8_UNORM; + + default: + return FD6_UBWC_UNKNOWN_COMPAT; + } +} + + +#endif diff --git a/src/freedreno/vulkan/tu_formats.cc b/src/freedreno/vulkan/tu_formats.cc index 1009936209d..914b43144c1 100644 --- a/src/freedreno/vulkan/tu_formats.cc +++ b/src/freedreno/vulkan/tu_formats.cc @@ -7,6 +7,7 @@ #include "tu_formats.h" #include "fdl/fd6_format_table.h" +#include "common/freedreno_ubwc.h" #include "vk_android.h" #include "vk_enum_defines.h" @@ -95,109 +96,10 @@ tu6_format_texture(enum pipe_format format, enum a6xx_tile_mode tile_mode) return fmt; } -enum tu6_ubwc_compat_type { - TU6_UBWC_UNKNOWN_COMPAT, - TU6_UBWC_R8G8_UNORM, - TU6_UBWC_R8G8_INT, - TU6_UBWC_R8G8B8A8_UNORM, - TU6_UBWC_R8G8B8A8_INT, - TU6_UBWC_B8G8R8A8_UNORM, - TU6_UBWC_R16G16_UNORM, - TU6_UBWC_R16G16_INT, - TU6_UBWC_R16G16B16A16_UNORM, - TU6_UBWC_R16G16B16A16_INT, - TU6_UBWC_R32_INT, - TU6_UBWC_R32G32_INT, - TU6_UBWC_R32G32B32A32_INT, - TU6_UBWC_R32_FLOAT, -}; - -static enum tu6_ubwc_compat_type +static enum fd6_ubwc_compat_type tu6_ubwc_compat_mode(const struct fd_dev_info *info, VkFormat format) { - switch (format) { - case VK_FORMAT_R8G8_UNORM: - case VK_FORMAT_R8G8_SRGB: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R8G8_INT : TU6_UBWC_R8G8_UNORM; - - case VK_FORMAT_R8G8_SNORM: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R8G8_INT : TU6_UBWC_UNKNOWN_COMPAT; - - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8_SINT: - return TU6_UBWC_R8G8_INT; - - case VK_FORMAT_R8G8B8A8_UNORM: - case VK_FORMAT_R8G8B8A8_SRGB: - case VK_FORMAT_A8B8G8R8_UNORM_PACK32: - case VK_FORMAT_A8B8G8R8_SRGB_PACK32: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R8G8B8A8_INT : TU6_UBWC_R8G8B8A8_UNORM; - - case VK_FORMAT_R8G8B8A8_SNORM: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R8G8B8A8_INT : TU6_UBWC_UNKNOWN_COMPAT; - - case VK_FORMAT_R8G8B8A8_UINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_A8B8G8R8_UINT_PACK32: - case VK_FORMAT_A8B8G8R8_SINT_PACK32: - return TU6_UBWC_R8G8B8A8_INT; - - case VK_FORMAT_R16G16_UNORM: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R16G16_INT : TU6_UBWC_R16G16_UNORM; - - case VK_FORMAT_R16G16_SNORM: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R16G16_INT : TU6_UBWC_UNKNOWN_COMPAT; - - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16_SINT: - return TU6_UBWC_R16G16_INT; - - case VK_FORMAT_R16G16B16A16_UNORM: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R16G16B16A16_INT : TU6_UBWC_R16G16B16A16_UNORM; - - case VK_FORMAT_R16G16B16A16_SNORM: - return info->a7xx.ubwc_unorm_snorm_int_compatible ? - TU6_UBWC_R16G16B16A16_INT : TU6_UBWC_UNKNOWN_COMPAT; - - case VK_FORMAT_R16G16B16A16_UINT: - case VK_FORMAT_R16G16B16A16_SINT: - return TU6_UBWC_R16G16B16A16_INT; - - case VK_FORMAT_R32_UINT: - case VK_FORMAT_R32_SINT: - return TU6_UBWC_R32_INT; - - case VK_FORMAT_R32G32_UINT: - case VK_FORMAT_R32G32_SINT: - return TU6_UBWC_R32G32_INT; - - case VK_FORMAT_R32G32B32A32_UINT: - case VK_FORMAT_R32G32B32A32_SINT: - return TU6_UBWC_R32G32B32A32_INT; - - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - /* TODO: a630 blob allows these, but not a660. When is it legal? */ - return TU6_UBWC_UNKNOWN_COMPAT; - - case VK_FORMAT_B8G8R8A8_UNORM: - case VK_FORMAT_B8G8R8A8_SRGB: - /* The blob doesn't list these as compatible, but they surely are. - * freedreno's happy to cast between them, and zink would really like - * to. - */ - return TU6_UBWC_B8G8R8A8_UNORM; - - default: - return TU6_UBWC_UNKNOWN_COMPAT; - } + return fd6_ubwc_compat_mode(info, vk_format_to_pipe_format(format)); } bool @@ -213,9 +115,9 @@ tu6_mutable_format_list_ubwc_compatible(const struct fd_dev_info *info, if (fmt_list->viewFormatCount == 1) return true; - enum tu6_ubwc_compat_type type = + enum fd6_ubwc_compat_type type = tu6_ubwc_compat_mode(info, fmt_list->pViewFormats[0]); - if (type == TU6_UBWC_UNKNOWN_COMPAT) + if (type == FD6_UBWC_UNKNOWN_COMPAT) return false; for (uint32_t i = 1; i < fmt_list->viewFormatCount; i++) { diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_resource.cc b/src/gallium/drivers/freedreno/a6xx/fd6_resource.cc index 711685c7598..9249061ccbc 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_resource.cc +++ b/src/gallium/drivers/freedreno/a6xx/fd6_resource.cc @@ -32,6 +32,7 @@ #include "a6xx/fd6_blitter.h" #include "fd6_resource.h" #include "fdl/fd6_format_table.h" +#include "common/freedreno_ubwc.h" #include "a6xx.xml.h" @@ -127,14 +128,6 @@ can_do_ubwc(struct pipe_resource *prsc) return true; } -static bool -is_norm(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - - return desc->is_snorm || desc->is_unorm; -} - static bool is_z24s8(enum pipe_format format) { @@ -150,8 +143,12 @@ is_z24s8(enum pipe_format format) } static bool -valid_format_cast(struct fd_resource *rsc, enum pipe_format format) +valid_ubwc_format_cast(struct fd_resource *rsc, enum pipe_format format) { + const struct fd_dev_info *info = fd_screen(rsc->b.b.screen)->info; + + assert(rsc->layout.ubwc); + /* Special case "casting" format in hw: */ if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8) return true; @@ -163,27 +160,8 @@ valid_format_cast(struct fd_resource *rsc, enum pipe_format format) is_z24s8(format) && is_z24s8(rsc->b.b.format)) return true; - /* For some color values (just "solid white") compression metadata maps to - * different pixel values for uint/sint vs unorm/snorm, so we can't reliably - * "cast" u/snorm to u/sint and visa versa: - */ - if (is_norm(format) != is_norm(rsc->b.b.format)) - return false; - - /* The UBWC formats can be re-interpreted so long as the components - * have the same # of bits - */ - for (unsigned i = 0; i < 4; i++) { - unsigned sb, db; - - sb = util_format_get_component_bits(rsc->b.b.format, UTIL_FORMAT_COLORSPACE_RGB, i); - db = util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, i); - - if (sb != db) - return false; - } - - return true; + return fd6_ubwc_compat_mode(info, format) == + fd6_ubwc_compat_mode(info, rsc->b.b.format); } /** @@ -217,7 +195,8 @@ fd6_check_valid_format(struct fd_resource *rsc, enum pipe_format format) if (!rsc->layout.ubwc) return FORMAT_OK; - if (ok_ubwc_format(rsc->b.b.screen, format) && valid_format_cast(rsc, format)) + if (ok_ubwc_format(rsc->b.b.screen, format) && + valid_ubwc_format_cast(rsc, format)) return FORMAT_OK; return DEMOTE_TO_TILED;