[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