radv: Add code to check if two formats can share DCC metadata.
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Fri, 15 Sep 2017 21:39:45 +0000 (23:39 +0200)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Sat, 16 Sep 2017 09:55:42 +0000 (11:55 +0200)
Ported from radeonsi.

Reviewed-by: Dave Airlie <airlied@redhat.com>
src/amd/vulkan/radv_formats.c
src/amd/vulkan/radv_private.h

index c19a9a37a49cd35ac14632fbcdacf729fbc3a6d0..244454128133c4d3ad68193409d9247350c310a2 100644 (file)
@@ -1317,3 +1317,88 @@ void radv_GetPhysicalDeviceExternalBufferPropertiesKHR(
                .compatibleHandleTypes = compat_flags,
        };
 }
+
+/* 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_incompatible,
+};
+
+/* Return the type of DCC encoding. */
+static enum dcc_channel_type
+radv_get_dcc_channel_type(const struct vk_format_description *desc)
+{
+        int i;
+
+        /* Find the first non-void channel. */
+        for (i = 0; i < desc->nr_channels; i++)
+                if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
+                        break;
+        if (i == desc->nr_channels)
+                return dcc_channel_incompatible;
+
+        switch (desc->channel[i].size) {
+        case 32:
+                if (desc->channel[i].type == VK_FORMAT_TYPE_FLOAT)
+                        return dcc_channel_float32;
+                if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED)
+                        return dcc_channel_uint32;
+                return dcc_channel_sint32;
+        case 16:
+                if (desc->channel[i].type == VK_FORMAT_TYPE_FLOAT)
+                        return dcc_channel_float16;
+                if (desc->channel[i].type == VK_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 == VK_FORMAT_TYPE_UNSIGNED)
+                        return dcc_channel_uint8;
+                return dcc_channel_sint8;
+        default:
+                return dcc_channel_incompatible;
+        }
+}
+
+/* Return if it's allowed to reinterpret one format as another with DCC enabled. */
+bool radv_dcc_formats_compatible(VkFormat format1,
+                                 VkFormat format2)
+{
+        const struct vk_format_description *desc1, *desc2;
+        enum dcc_channel_type type1, type2;
+        int i;
+
+        if (format1 == format2)
+                return true;
+
+        desc1 = vk_format_description(format1);
+        desc2 = vk_format_description(format2);
+
+        if (desc1->nr_channels != desc2->nr_channels)
+                return false;
+
+        /* Swizzles must be the same. */
+        for (i = 0; i < desc1->nr_channels; i++)
+                if (desc1->swizzle[i] <= VK_SWIZZLE_W &&
+                    desc2->swizzle[i] <= VK_SWIZZLE_W &&
+                    desc1->swizzle[i] != desc2->swizzle[i])
+                        return false;
+
+        type1 = radv_get_dcc_channel_type(desc1);
+        type2 = radv_get_dcc_channel_type(desc2);
+
+        return type1 != dcc_channel_incompatible &&
+               type2 != dcc_channel_incompatible &&
+               type1 == type2;
+}
+
index e5092a8923b01381efb97c09ad1da686078a6ce6..f9853df5a3fef8d5662de7cad2fd6193738cbc4c 100644 (file)
@@ -1170,6 +1170,8 @@ bool radv_format_pack_clear_color(VkFormat format,
                                  uint32_t clear_vals[2],
                                  VkClearColorValue *value);
 bool radv_is_colorbuffer_format_supported(VkFormat format, bool *blendable);
+bool radv_dcc_formats_compatible(VkFormat format1,
+                                 VkFormat format2);
 
 struct radv_fmask_info {
        uint64_t offset;