summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2018-04-11 21:21:28 -0400
committerMarek Olšák <[email protected]>2018-04-27 17:56:04 -0400
commit2d69b485f557d8d438edf7e99ad4b15bb2594061 (patch)
tree0c45aec886acdf8eb9f7f0f9b421abd0bda3ec5e /src
parentc732d069b3a4a5fefb353d01d17834ce2c548ae6 (diff)
radeonsi: rewrite DCC format compatibility checking code
It might be better to use a slow compressed clear when clearing to 1. Reviewed-by: Nicolai Hähnle <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/radeonsi/si_texture.c98
1 files changed, 42 insertions, 56 deletions
diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 9ff0ba3e9a8..ca8073ae84d 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -1894,77 +1894,63 @@ static const struct u_resource_vtbl si_texture_vtbl =
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,