Mesa (main): radv: enable DCC with signedness reinterpretation
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Aug 12 18:05:36 UTC 2021
Module: Mesa
Branch: main
Commit: c14a85e75688763b56dfaceda899090200398f9e
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=c14a85e75688763b56dfaceda899090200398f9e
Author: Rhys Perry <pendingchaos02 at gmail.com>
Date: Tue Mar 2 16:34:59 2021 +0000
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 at gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9387>
---
src/amd/vulkan/radv_formats.c | 69 +++++++++++++++++++++-------------------
src/amd/vulkan/radv_image.c | 23 ++++++++------
src/amd/vulkan/radv_meta_clear.c | 4 +++
src/amd/vulkan/radv_meta_copy.c | 5 ++-
src/amd/vulkan/radv_private.h | 6 ++--
5 files changed, 62 insertions(+), 45 deletions(-)
diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c
index ce2d81df10f..1ad9ca19876 100644
--- a/src/amd/vulkan/radv_formats.c
+++ b/src/amd/vulkan/radv_formats.c
@@ -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);
+
+ 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 type1 != dcc_channel_incompatible && type2 != dcc_channel_incompatible && type1 == type2;
+ return true;
}
diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c
index 32cef33f2d9..45b5f53725a 100644
--- a/src/amd/vulkan/radv_image.c
+++ b/src/amd/vulkan/radv_image.c
@@ -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))
diff --git a/src/amd/vulkan/radv_meta_clear.c b/src/amd/vulkan/radv_meta_clear.c
index b7fd48d2b5c..82bb12b5365 100644
--- a/src/amd/vulkan/radv_meta_clear.c
+++ b/src/amd/vulkan/radv_meta_clear.c
@@ -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) {
diff --git a/src/amd/vulkan/radv_meta_copy.c b/src/amd/vulkan/radv_meta_copy.c
index 168ccfc074c..a50818d1ddb 100644
--- a/src/amd/vulkan/radv_meta_copy.c
+++ b/src/amd/vulkan/radv_meta_copy.c
@@ -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;
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 06d76567892..3d20e23d388 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -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);
More information about the mesa-commit
mailing list