[Mesa-dev] [PATCH 6/7] radeonsi: rewrite DCC format compatibility checking code

Marek Olšák maraeo at gmail.com
Tue Apr 17 00:41:33 UTC 2018


From: Marek Olšák <marek.olsak at amd.com>

It might be better to use a slow compressed clear when clearing to 1.
---
 src/gallium/drivers/radeonsi/si_texture.c | 98 ++++++++++-------------
 1 file changed, 42 insertions(+), 56 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 675e78766ad..e220d438de4 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -1888,91 +1888,77 @@ static void si_texture_transfer_unmap(struct pipe_context *ctx,
 
 static const struct u_resource_vtbl si_texture_vtbl =
 {
 	NULL,				/* get_handle */
 	si_texture_destroy,		/* resource_destroy */
 	si_texture_transfer_map,	/* transfer_map */
 	u_default_transfer_flush_region, /* transfer_flush_region */
 	si_texture_transfer_unmap,	/* transfer_unmap */
 };
 
-/* 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_float,
-	/* uint and sint can be merged if we never use TC-compatible DCC clear
-	 * encoding with the clear value of 1. */
-	dcc_channel_uint,
-	dcc_channel_sint,
-	dcc_channel_uint_10_10_10_2,
-	dcc_channel_incompatible,
-};
-
-/* Return the type of DCC encoding. */
-static enum dcc_channel_type
-vi_get_dcc_channel_type(const struct util_format_description *desc)
-{
-	int i;
-
-	/* Find the first non-void channel. */
-	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;
-
-	switch (desc->channel[i].size) {
-	case 32:
-	case 16:
-	case 8:
-		if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
-			return dcc_channel_float;
-		if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)
-			return dcc_channel_uint;
-		return dcc_channel_sint;
-	case 10:
-		return dcc_channel_uint_10_10_10_2;
-	default:
-		return dcc_channel_incompatible;
-	}
-}
-
-/* Return if it's allowed to reinterpret one format as another with DCC enabled. */
+/* Return if it's allowed to reinterpret one format as another with DCC enabled.
+ */
 bool vi_dcc_formats_compatible(enum pipe_format format1,
 			       enum pipe_format format2)
 {
 	const struct util_format_description *desc1, *desc2;
-	enum dcc_channel_type type1, type2;
-	int i;
 
+	/* No format change - exit early. */
+	if (format1 == format2)
+		return true;
+
+	format1 = si_simplify_cb_format(format1);
+	format2 = si_simplify_cb_format(format2);
+
+	/* Check again after format adjustments. */
 	if (format1 == format2)
 		return true;
 
 	desc1 = util_format_description(format1);
 	desc2 = util_format_description(format2);
 
-	if (desc1->nr_channels != desc2->nr_channels)
+	if (desc1->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
+	    desc2->layout != UTIL_FORMAT_LAYOUT_PLAIN)
 		return false;
 
-	/* Swizzles must be the same. */
-	for (i = 0; i < desc1->nr_channels; i++)
-		if (desc1->swizzle[i] <= PIPE_SWIZZLE_W &&
-		    desc2->swizzle[i] <= PIPE_SWIZZLE_W &&
-		    desc1->swizzle[i] != desc2->swizzle[i])
-			return false;
+	/* Float and non-float are totally incompatible. */
+	if ((desc1->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) !=
+	    (desc2->channel[0].type == UTIL_FORMAT_TYPE_FLOAT))
+		return false;
 
-	type1 = vi_get_dcc_channel_type(desc1);
-	type2 = vi_get_dcc_channel_type(desc2);
+	/* Channel sizes must match across DCC formats.
+	 * Comparing just the first 2 channels should be enough.
+	 */
+	if (desc1->channel[0].size != desc2->channel[0].size ||
+	    (desc1->nr_channels >= 2 &&
+	     desc1->channel[1].size != desc2->channel[1].size))
+		return false;
 
-	return type1 != dcc_channel_incompatible &&
-	       type2 != dcc_channel_incompatible &&
-	       type1 == type2;
+	/* Everything below is not needed if the driver never uses the DCC
+	 * clear code with the value of 1.
+	 */
+
+	/* If the clear values are all 1 or all 0, this constraint can be
+	 * ignored. */
+	if (vi_alpha_is_on_msb(format1) != vi_alpha_is_on_msb(format2))
+		return false;
+
+	/* Channel types must match if the clear value of 1 is used.
+	 * The type categories are only float, signed, unsigned.
+	 * NORM and INT are always compatible.
+	 */
+	if (desc1->channel[0].type != desc2->channel[0].type ||
+	    (desc1->nr_channels >= 2 &&
+	     desc1->channel[1].type != desc2->channel[1].type))
+		return false;
+
+	return true;
 }
 
 bool vi_dcc_formats_are_incompatible(struct pipe_resource *tex,
 				     unsigned level,
 				     enum pipe_format view_format)
 {
 	struct r600_texture *rtex = (struct r600_texture *)tex;
 
 	return vi_dcc_enabled(rtex, level) &&
 	       !vi_dcc_formats_compatible(tex->format, view_format);
-- 
2.17.0



More information about the mesa-dev mailing list