From 08f4a904b386f3535719dff4c224ea5cfccc92cd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 23 Jan 2019 14:26:53 -0800 Subject: [PATCH] gallium: Make sure we return is_unorm/is_snorm for compressed formats. The util helpers were looking for a non-void channels in a non-mixed format and returning its snorm/unorm state. However, compressed formats don't have non-void channels, so they always returned false. V3D wants to use util_format_is_[su]norm for its border color clamping workarounds, so fix the functions to return the right answer for these. This now means that we ignore .is_mixed. I could retain the is_mixed check, but it doesn't seem like a useful feature -- the only code I could find that might care is freedreno's blit, which has some notes about how things are wonky in this area anyway. Reviewed-by: --- src/gallium/auxiliary/util/u_format.c | 28 ++------- src/gallium/auxiliary/util/u_format.h | 10 +++ src/gallium/auxiliary/util/u_format_parse.py | 20 ++++++ src/gallium/auxiliary/util/u_format_table.py | 2 + src/gallium/tests/unit/u_format_test.c | 65 ++++++++++++++++++++ 5 files changed, 101 insertions(+), 24 deletions(-) diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c index 862061a8ec2..3a61d54f726 100644 --- a/src/gallium/auxiliary/util/u_format.c +++ b/src/gallium/auxiliary/util/u_format.c @@ -149,45 +149,25 @@ util_format_is_pure_uint(enum pipe_format format) } /** - * Returns true if all non-void channels are normalized signed. + * Returns true if the format contains normalized signed channels. */ boolean util_format_is_snorm(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); - int i; - - if (desc->is_mixed) - return FALSE; - - i = util_format_get_first_non_void_channel(format); - if (i == -1) - return FALSE; - return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && - !desc->channel[i].pure_integer && - desc->channel[i].normalized; + return desc->is_snorm; } /** - * Returns true if all non-void channels are normalized unsigned. + * Returns true if the format contains normalized unsigned channels. */ boolean util_format_is_unorm(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); - int i; - if (desc->is_mixed) - return FALSE; - - i = util_format_get_first_non_void_channel(format); - if (i == -1) - return FALSE; - - return desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && - !desc->channel[i].pure_integer && - desc->channel[i].normalized; + return desc->is_unorm; } boolean diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h index 0c0c505e391..cb1138947aa 100644 --- a/src/gallium/auxiliary/util/u_format.h +++ b/src/gallium/auxiliary/util/u_format.h @@ -177,6 +177,16 @@ struct util_format_description */ unsigned is_mixed:1; + /** + * Whether the format contains UNORM channels + */ + unsigned is_unorm:1; + + /** + * Whether the format contains SNORM channels + */ + unsigned is_snorm:1; + /** * Input channel description, in the order XYZW. * diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py index 48cc012cd2a..e8a6c92d119 100644 --- a/src/gallium/auxiliary/util/u_format_parse.py +++ b/src/gallium/auxiliary/util/u_format_parse.py @@ -187,6 +187,26 @@ class Format: return True return False + def is_compressed(self): + for channel in self.le_channels: + if channel.type != VOID: + return False + return True + + def is_unorm(self): + # Non-compressed formats all have unorm or srgb in their name. + for keyword in ['_UNORM', '_SRGB']: + if keyword in self.name: + return True + + # All the compressed formats in GLES3.2 and GL4.6 ("Table 8.14: Generic + # and specific compressed internal formats.") that aren't snorm for + # border colors are unorm, other than BPTC_*_FLOAT. + return self.is_compressed() and not ('FLOAT' in self.name or self.is_snorm()) + + def is_snorm(self): + return '_SNORM' in self.name + def is_pot(self): return is_pot(self.block_size()) diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py index 1a966c52bc7..97cd0474382 100644 --- a/src/gallium/auxiliary/util/u_format_table.py +++ b/src/gallium/auxiliary/util/u_format_table.py @@ -136,6 +136,8 @@ def write_format_table(formats): print(" %s,\t/* is_array */" % (bool_map(format.is_array()),)) print(" %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),)) print(" %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)) + print(" %s,\t/* is_unorm */" % (bool_map(format.is_unorm()),)) + print(" %s,\t/* is_snorm */" % (bool_map(format.is_snorm()),)) u_format_pack.print_channels(format, do_channel_array) u_format_pack.print_channels(format, do_swizzle_array) print(" %s," % (colorspace_map(format.colorspace),)) diff --git a/src/gallium/tests/unit/u_format_test.c b/src/gallium/tests/unit/u_format_test.c index 437cc94b757..640214dfc50 100644 --- a/src/gallium/tests/unit/u_format_test.c +++ b/src/gallium/tests/unit/u_format_test.c @@ -668,6 +668,47 @@ test_format_pack_s_8uint(const struct util_format_description *format_desc, } +/* Touch-test that the unorm/snorm flags are set up right by codegen. */ +static boolean +test_format_norm_flags(const struct util_format_description *format_desc) +{ + boolean success = TRUE; + +#define FORMAT_CASE(format, unorm, snorm) \ + case format: \ + success = (format_desc->is_unorm == unorm && \ + format_desc->is_snorm == snorm); \ + break + + switch (format_desc->format) { + FORMAT_CASE(PIPE_FORMAT_R8G8B8A8_UNORM, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_R8G8B8A8_SRGB, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_R8G8B8A8_SNORM, FALSE, TRUE); + FORMAT_CASE(PIPE_FORMAT_R32_FLOAT, FALSE, FALSE); + FORMAT_CASE(PIPE_FORMAT_X8Z24_UNORM, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_S8X24_UINT, FALSE, FALSE); + FORMAT_CASE(PIPE_FORMAT_DXT1_RGB, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_ETC2_RGB8, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_ETC2_R11_SNORM, FALSE, TRUE); + FORMAT_CASE(PIPE_FORMAT_ASTC_4x4, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_BPTC_RGBA_UNORM, TRUE, FALSE); + FORMAT_CASE(PIPE_FORMAT_BPTC_RGB_FLOAT, FALSE, FALSE); + default: + success = !(format_desc->is_unorm && format_desc->is_snorm); + break; + } +#undef FORMAT_CASE + + if (!success) { + printf("FAILED: %s (unorm %s, snorm %s)\n", + format_desc->short_name, + format_desc->is_unorm ? "yes" : "no", + format_desc->is_snorm ? "yes" : "no"); + } + + return success; +} + typedef boolean (*test_func_t)(const struct util_format_description *format_desc, const struct util_format_test_case *test); @@ -698,6 +739,22 @@ test_one_func(const struct util_format_description *format_desc, return success; } +static boolean +test_format_metadata(const struct util_format_description *format_desc, + boolean (*func)(const struct util_format_description *format_desc), + const char *suffix) +{ + boolean success = TRUE; + + printf("Testing util_format_%s_%s ...\n", format_desc->short_name, suffix); + fflush(stdout); + + if (!func(format_desc)) { + success = FALSE; + } + + return success; +} static boolean test_all(void) @@ -724,6 +781,11 @@ test_all(void) } \ } +# define TEST_FORMAT_METADATA(name) \ + if (!test_format_metadata(format_desc, &test_format_##name, #name)) { \ + success = FALSE; \ + } \ + TEST_ONE_FUNC(fetch_rgba_float); TEST_ONE_FUNC(pack_rgba_float); TEST_ONE_FUNC(unpack_rgba_float); @@ -737,7 +799,10 @@ test_all(void) TEST_ONE_FUNC(unpack_s_8uint); TEST_ONE_FUNC(pack_s_8uint); + TEST_FORMAT_METADATA(norm_flags); + # undef TEST_ONE_FUNC +# undef TEST_ONE_FORMAT } return success; -- 2.30.2