radv: enable DCC with signedness reinterpretation
It seems we can enable DCC if the possible formats differ in signedness and are otherwise compatible. We just need a fast-clear eliminate for certain clear colors. Improves Trine 4 performance. Signed-off-by: Rhys Perry <pendingchaos02@gmail.com> Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9387>
This commit is contained in:
@@ -1263,8 +1263,11 @@ radv_check_modifier_support(struct radv_physical_device *dev,
|
||||
if (!found)
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
|
||||
bool need_dcc_sign_reinterpret = false;
|
||||
if (ac_modifier_has_dcc(modifier) &&
|
||||
!radv_are_formats_dcc_compatible(dev, info->pNext, format, info->flags))
|
||||
!radv_are_formats_dcc_compatible(dev, info->pNext, format, info->flags,
|
||||
&need_dcc_sign_reinterpret) &&
|
||||
!need_dcc_sign_reinterpret)
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
|
||||
/* We can expand this as needed and implemented but there is not much demand
|
||||
@@ -1903,21 +1906,16 @@ radv_GetPhysicalDeviceExternalBufferProperties(
|
||||
/* DCC channel type categories within which formats can be reinterpreted
|
||||
* while keeping the same DCC encoding. The swizzle must also match. */
|
||||
enum dcc_channel_type {
|
||||
dcc_channel_float32,
|
||||
dcc_channel_uint32,
|
||||
dcc_channel_sint32,
|
||||
dcc_channel_float16,
|
||||
dcc_channel_uint16,
|
||||
dcc_channel_sint16,
|
||||
dcc_channel_uint_10_10_10_2,
|
||||
dcc_channel_uint8,
|
||||
dcc_channel_sint8,
|
||||
dcc_channel_float,
|
||||
dcc_channel_uint,
|
||||
dcc_channel_sint,
|
||||
dcc_channel_incompatible,
|
||||
};
|
||||
|
||||
/* Return the type of DCC encoding. */
|
||||
static enum dcc_channel_type
|
||||
radv_get_dcc_channel_type(const struct util_format_description *desc)
|
||||
static void
|
||||
radv_get_dcc_channel_type(const struct util_format_description *desc, enum dcc_channel_type *type,
|
||||
unsigned *size)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1925,39 +1923,37 @@ radv_get_dcc_channel_type(const struct util_format_description *desc)
|
||||
for (i = 0; i < desc->nr_channels; i++)
|
||||
if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
|
||||
break;
|
||||
if (i == desc->nr_channels)
|
||||
return dcc_channel_incompatible;
|
||||
if (i == desc->nr_channels) {
|
||||
*type = dcc_channel_incompatible;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (desc->channel[i].size) {
|
||||
case 32:
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
|
||||
return dcc_channel_float32;
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)
|
||||
return dcc_channel_uint32;
|
||||
return dcc_channel_sint32;
|
||||
case 16:
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
|
||||
return dcc_channel_float16;
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)
|
||||
return dcc_channel_uint16;
|
||||
return dcc_channel_sint16;
|
||||
case 10:
|
||||
return dcc_channel_uint_10_10_10_2;
|
||||
case 8:
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)
|
||||
return dcc_channel_uint8;
|
||||
return dcc_channel_sint8;
|
||||
*size = desc->channel[i].size;
|
||||
if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
|
||||
*type = dcc_channel_float;
|
||||
else if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)
|
||||
*type = dcc_channel_uint;
|
||||
else
|
||||
*type = dcc_channel_sint;
|
||||
break;
|
||||
default:
|
||||
return dcc_channel_incompatible;
|
||||
*type = dcc_channel_incompatible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return if it's allowed to reinterpret one format as another with DCC enabled. */
|
||||
bool
|
||||
radv_dcc_formats_compatible(VkFormat format1, VkFormat format2)
|
||||
radv_dcc_formats_compatible(VkFormat format1, VkFormat format2, bool *sign_reinterpret)
|
||||
{
|
||||
const struct util_format_description *desc1, *desc2;
|
||||
enum dcc_channel_type type1, type2;
|
||||
unsigned size1, size2;
|
||||
int i;
|
||||
|
||||
if (format1 == format2)
|
||||
@@ -1975,8 +1971,15 @@ radv_dcc_formats_compatible(VkFormat format1, VkFormat format2)
|
||||
desc1->swizzle[i] != desc2->swizzle[i])
|
||||
return false;
|
||||
|
||||
type1 = radv_get_dcc_channel_type(desc1);
|
||||
type2 = radv_get_dcc_channel_type(desc2);
|
||||
radv_get_dcc_channel_type(desc1, &type1, &size1);
|
||||
radv_get_dcc_channel_type(desc2, &type2, &size2);
|
||||
|
||||
return type1 != dcc_channel_incompatible && type2 != dcc_channel_incompatible && type1 == type2;
|
||||
if (type1 == dcc_channel_incompatible || type2 == dcc_channel_incompatible ||
|
||||
(type1 == dcc_channel_float) != (type2 == dcc_channel_float) || size1 != size2)
|
||||
return false;
|
||||
|
||||
if (type1 != type2)
|
||||
*sign_reinterpret = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -150,13 +150,16 @@ radv_image_use_fast_clear_for_image(const struct radv_device *device,
|
||||
|
||||
bool
|
||||
radv_are_formats_dcc_compatible(const struct radv_physical_device *pdev, const void *pNext,
|
||||
VkFormat format, VkImageCreateFlags flags)
|
||||
VkFormat format, VkImageCreateFlags flags, bool *sign_reinterpret)
|
||||
{
|
||||
bool blendable;
|
||||
|
||||
if (!radv_is_colorbuffer_format_supported(pdev, format, &blendable))
|
||||
return false;
|
||||
|
||||
if (sign_reinterpret != NULL)
|
||||
*sign_reinterpret = false;
|
||||
|
||||
if (flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
|
||||
const struct VkImageFormatListCreateInfo *format_list =
|
||||
(const struct VkImageFormatListCreateInfo *)vk_find_struct_const(
|
||||
@@ -170,7 +173,8 @@ radv_are_formats_dcc_compatible(const struct radv_physical_device *pdev, const v
|
||||
if (format_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)
|
||||
continue;
|
||||
|
||||
if (!radv_dcc_formats_compatible(format, format_list->pViewFormats[i]))
|
||||
if (!radv_dcc_formats_compatible(format, format_list->pViewFormats[i],
|
||||
sign_reinterpret))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -205,8 +209,9 @@ radv_formats_is_atomic_allowed(const void *pNext, VkFormat format, VkImageCreate
|
||||
}
|
||||
|
||||
static bool
|
||||
radv_use_dcc_for_image(struct radv_device *device, const struct radv_image *image,
|
||||
const VkImageCreateInfo *pCreateInfo, VkFormat format)
|
||||
radv_use_dcc_for_image(struct radv_device *device, struct radv_image *image,
|
||||
const VkImageCreateInfo *pCreateInfo, VkFormat format,
|
||||
bool *sign_reinterpret)
|
||||
{
|
||||
/* DCC (Delta Color Compression) is only available for GFX8+. */
|
||||
if (device->physical_device->rad_info.chip_class < GFX8)
|
||||
@@ -260,7 +265,7 @@ radv_use_dcc_for_image(struct radv_device *device, const struct radv_image *imag
|
||||
}
|
||||
|
||||
return radv_are_formats_dcc_compatible(device->physical_device, pCreateInfo->pNext, format,
|
||||
pCreateInfo->flags);
|
||||
pCreateInfo->flags, sign_reinterpret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -480,9 +485,8 @@ radv_patch_image_from_extra_info(struct radv_device *device, struct radv_image *
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
radv_get_surface_flags(struct radv_device *device, const struct radv_image *image,
|
||||
unsigned plane_id, const VkImageCreateInfo *pCreateInfo,
|
||||
VkFormat image_format)
|
||||
radv_get_surface_flags(struct radv_device *device, struct radv_image *image, unsigned plane_id,
|
||||
const VkImageCreateInfo *pCreateInfo, VkFormat image_format)
|
||||
{
|
||||
uint64_t flags;
|
||||
unsigned array_mode = radv_choose_tiling(device, pCreateInfo, image_format);
|
||||
@@ -538,7 +542,8 @@ radv_get_surface_flags(struct radv_device *device, const struct radv_image *imag
|
||||
vk_format_get_blocksizebits(image_format) == 128 && vk_format_is_compressed(image_format))
|
||||
flags |= RADEON_SURF_NO_RENDER_TARGET;
|
||||
|
||||
if (!radv_use_dcc_for_image(device, image, pCreateInfo, image_format))
|
||||
if (!radv_use_dcc_for_image(device, image, pCreateInfo, image_format,
|
||||
&image->dcc_sign_reinterpret))
|
||||
flags |= RADEON_SURF_DISABLE_DCC;
|
||||
|
||||
if (!radv_use_fmask_for_image(device, image))
|
||||
|
||||
@@ -1760,6 +1760,10 @@ vi_get_fast_clear_parameters(struct radv_device *device, const struct radv_image
|
||||
desc->swizzle[i] >= PIPE_SWIZZLE_X && desc->swizzle[i] <= PIPE_SWIZZLE_W)
|
||||
return;
|
||||
|
||||
/* Only DCC clear code 0000 is allowed for signed<->unsigned formats. */
|
||||
if ((main_value || extra_value) && iview->image->dcc_sign_reinterpret)
|
||||
return;
|
||||
|
||||
*can_avoid_fast_clear_elim = true;
|
||||
|
||||
if (main_value) {
|
||||
|
||||
@@ -434,8 +434,11 @@ copy_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
|
||||
bool src_compressed = radv_layout_dcc_compressed(cmd_buffer->device, src_image,
|
||||
region->srcSubresource.mipLevel,
|
||||
src_image_layout, false, src_queue_mask);
|
||||
bool need_dcc_sign_reinterpret = false;
|
||||
|
||||
if (!src_compressed || radv_dcc_formats_compatible(b_src.format, b_dst.format)) {
|
||||
if (!src_compressed ||
|
||||
(radv_dcc_formats_compatible(b_src.format, b_dst.format, &need_dcc_sign_reinterpret) &&
|
||||
!need_dcc_sign_reinterpret)) {
|
||||
b_src.format = b_dst.format;
|
||||
} else if (!dst_compressed) {
|
||||
b_dst.format = b_src.format;
|
||||
|
||||
@@ -1873,7 +1873,7 @@ bool radv_is_storage_image_format_supported(struct radv_physical_device *physica
|
||||
VkFormat format);
|
||||
bool radv_is_colorbuffer_format_supported(const struct radv_physical_device *pdevice,
|
||||
VkFormat format, bool *blendable);
|
||||
bool radv_dcc_formats_compatible(VkFormat format1, VkFormat format2);
|
||||
bool radv_dcc_formats_compatible(VkFormat format1, VkFormat format2, bool *sign_reinterpret);
|
||||
bool radv_is_atomic_format_supported(VkFormat format);
|
||||
bool radv_device_supports_etc(struct radv_physical_device *physical_device);
|
||||
|
||||
@@ -1901,6 +1901,7 @@ struct radv_image {
|
||||
bool exclusive;
|
||||
bool shareable;
|
||||
bool l2_coherent;
|
||||
bool dcc_sign_reinterpret;
|
||||
|
||||
/* Set when bound */
|
||||
struct radeon_winsys_bo *bo;
|
||||
@@ -2243,7 +2244,8 @@ VkResult radv_image_create(VkDevice _device, const struct radv_image_create_info
|
||||
const VkAllocationCallbacks *alloc, VkImage *pImage);
|
||||
|
||||
bool radv_are_formats_dcc_compatible(const struct radv_physical_device *pdev, const void *pNext,
|
||||
VkFormat format, VkImageCreateFlags flags);
|
||||
VkFormat format, VkImageCreateFlags flags,
|
||||
bool *sign_reinterpret);
|
||||
|
||||
bool vi_alpha_is_on_msb(struct radv_device *device, VkFormat format);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user