gallium: Make sure we return is_unorm/is_snorm for compressed formats.
authorEric Anholt <eric@anholt.net>
Wed, 23 Jan 2019 22:26:53 +0000 (14:26 -0800)
committerEric Anholt <eric@anholt.net>
Fri, 25 Jan 2019 21:06:50 +0000 (13:06 -0800)
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: <Roland Scheidegger sroland@vmware.com>
src/gallium/auxiliary/util/u_format.c
src/gallium/auxiliary/util/u_format.h
src/gallium/auxiliary/util/u_format_parse.py
src/gallium/auxiliary/util/u_format_table.py
src/gallium/tests/unit/u_format_test.c

index 862061a8ec278597da987d9f789e7a3f2b29b956..3a61d54f726bb185f226f6bded34f86f9b33a5e2 100644 (file)
@@ -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
index 0c0c505e3918cdbca419fdb10a12d7bece933e26..cb1138947aad659871bd548c48747142925b8212 100644 (file)
@@ -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.
     *
index 48cc012cd2a76e175ece815a37acde2e713c543b..e8a6c92d119b4339d46709f51d438acb6a16569d 100644 (file)
@@ -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())
 
index 1a966c52bc71c75774d2db8d3121e28ce242fbf4..97cd047438269aab00618609a063e41ecbb6629b 100644 (file)
@@ -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),))
index 437cc94b7575d9d37c3a7aa449986a89b777ea60..640214dfc50a673b8208bd844d68e60f75280c63 100644 (file)
@@ -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;