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