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:
Rhys Perry
2021-03-02 16:34:59 +00:00
parent 688d11e4e8
commit c14a85e756
5 changed files with 62 additions and 45 deletions
+36 -33
View File
@@ -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;
}
+14 -9
View File
@@ -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))
+4
View File
@@ -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) {
+4 -1
View File
@@ -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;
+4 -2
View File
@@ -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);