freedreno: Extract out common UBWC helper

And re-use in gallium driver.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30304>
This commit is contained in:
Rob Clark
2024-07-24 14:58:10 -07:00
committed by Marge Bot
parent 5c34a5e59a
commit beb5577e12
3 changed files with 130 additions and 134 deletions

View File

@@ -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

View File

@@ -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++) {

View File

@@ -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;