Mesa (main): panfrost: Add basic fixed-function blending tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Aug 11 18:32:48 UTC 2021


Module: Mesa
Branch: main
Commit: 95e306dc84c4964bb5ef84ff4099ae20a7ac53f1
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=95e306dc84c4964bb5ef84ff4099ae20a7ac53f1

Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date:   Fri Jul 30 18:43:48 2021 -0400

panfrost: Add basic fixed-function blending tests

Add unit tests for the fixed-function blending helpers in pan_blend.c.
Each test consists of a Porter-Duff blend mode and the associated
hardware state. In this commit, we add tests for the most common modes.

For motivation, this code has NOT been properly tested in CI. True,
functional correctness of the blend module as a whole is tested by
dEQP-GLES3.functional.fragment_ops.blend.* among other integration
tests. However, this testing is insufficient to check for regressions.
Crucially, the following broken patch would clear CI:

   bool pan_can_fixed_function(...) {
      return false;
   }

In that case, blend shaders are used 100% of the time, which will
regress performance horribly but still pass dEQP. The only clue
something went wrong would be some traces changing checksum due to the
fixed-function blender producing slightly different output than
equivalent blend shaders. By unit testing the fixed blend path, we
ensure we always use the fixed-function path when we expect it to.

Similarly, using incorrect values for the blend metadata may not affect
functional correctness but will increase power consumption. Let's check
all the data we export to drivers.

Note: due to additive commutativity, there are many pairs of equivalent
Mali blend modes. Unfortunately, the vendor is... inconsistent about how
to resolve ambiguous modes. Our algorithm for computing modes is
correct; the "preferred" values are left in comments since otherwise our
tests fail despite correct code. I want to blame Bifrost for this, but
Midgard was patient zero.

Signed-off-by: Alyssa Rosenzweig <alyssa at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12152>

---

 src/panfrost/lib/meson.build        |  15 +++
 src/panfrost/lib/tests/test-blend.c | 216 ++++++++++++++++++++++++++++++++++++
 2 files changed, 231 insertions(+)

diff --git a/src/panfrost/lib/meson.build b/src/panfrost/lib/meson.build
index 934440d3276..f01cb6c19b2 100644
--- a/src/panfrost/lib/meson.build
+++ b/src/panfrost/lib/meson.build
@@ -100,3 +100,18 @@ libpanfrost_dep = declare_dependency(
   include_directories: [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_panfrost_hw, inc_panfrost],
   dependencies: [dep_libdrm, idep_nir, idep_midgard_pack],
 )
+
+if with_tests
+  test(
+    'panfrost_blend',
+    executable(
+      'panfrost_blend_test',
+      files('tests/test-blend.c'),
+      c_args : [c_msvc_compat_args, no_override_init_args],
+      gnu_symbol_visibility : 'hidden',
+      include_directories : [inc_include, inc_src, inc_mesa],
+      dependencies: [libpanfrost_dep],
+    ),
+    suite : ['panfrost'],
+  )
+endif
diff --git a/src/panfrost/lib/tests/test-blend.c b/src/panfrost/lib/tests/test-blend.c
new file mode 100644
index 00000000000..b088415f364
--- /dev/null
+++ b/src/panfrost/lib/tests/test-blend.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2021 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pan_blend.h"
+
+/* A test consists of a given blend mode and its translated form */
+struct test {
+   const char *label;
+   struct pan_blend_equation eq;
+   unsigned constant_mask;
+   bool reads_dest;
+   bool opaque;
+   bool fixed_function;
+   uint32_t hardware;
+};
+
+#define RGBA(key, value) \
+   .rgb_ ## key = value, \
+   .alpha_ ## key = value
+
+static const struct test blend_tests[] = {
+   {
+      "Replace",
+      {
+         .blend_enable = false,
+         .color_mask = 0xF,
+      },
+      .constant_mask = 0x0,
+      .reads_dest = false,
+      .opaque = true,
+      .fixed_function = true,
+      .hardware = 0xF0122122
+   },
+   {
+      "Alpha",
+      {
+         .blend_enable = true,
+         .color_mask = 0xF,
+
+         RGBA(func, BLEND_FUNC_ADD),
+         RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA),
+         RGBA(dst_factor, BLEND_FACTOR_SRC_ALPHA),
+         RGBA(invert_dst_factor, true),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xF0503503
+   },
+   {
+      "Additive",
+      {
+         .blend_enable = true,
+         .color_mask = 0xF,
+
+         RGBA(func, BLEND_FUNC_ADD),
+         RGBA(src_factor, BLEND_FACTOR_ZERO),
+         RGBA(dst_factor, BLEND_FACTOR_ZERO),
+         RGBA(invert_src_factor, true),
+         RGBA(invert_dst_factor, true),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xF0932932 /* equivalently 0xF0923923 */
+   },
+   {
+      "Additive-Alpha",
+      {
+         .blend_enable = true,
+         .color_mask = 0xF,
+
+         RGBA(func, BLEND_FUNC_ADD),
+         RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA),
+         RGBA(dst_factor, BLEND_FACTOR_ZERO),
+         RGBA(invert_dst_factor, true),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xF0523523
+   },
+   {
+      "Subtractive",
+      {
+         .blend_enable = true,
+         .color_mask = 0xF,
+
+         RGBA(func, BLEND_FUNC_SUBTRACT),
+         RGBA(src_factor, BLEND_FACTOR_ZERO),
+         RGBA(dst_factor, BLEND_FACTOR_ZERO),
+         RGBA(invert_src_factor, true),
+         RGBA(invert_dst_factor, true),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xF09B29B2 /* equivalently 0xF09A39A3 */
+   },
+   {
+      "Subtractive-Alpha",
+      {
+         .blend_enable = true,
+         .color_mask = 0xF,
+
+         RGBA(func, BLEND_FUNC_SUBTRACT),
+         RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA),
+         RGBA(dst_factor, BLEND_FACTOR_ZERO),
+         RGBA(invert_dst_factor, true),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xF052B52b /* equivalently 0xF05A35A3 */
+   },
+   {
+      "Modulate",
+      {
+         .blend_enable = true,
+         .color_mask = 0xF,
+
+         RGBA(func, BLEND_FUNC_ADD),
+         RGBA(src_factor, BLEND_FACTOR_ZERO),
+         RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xF0231231 /* equivalently 0xF0321321 */
+   },
+   {
+      "Replace masked",
+      {
+         .blend_enable = false,
+         .color_mask = 0x3,
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0x30122122
+   },
+   {
+      "Modulate masked",
+      {
+         .blend_enable = true,
+         .color_mask = 0xA,
+
+         RGBA(func, BLEND_FUNC_ADD),
+         RGBA(src_factor, BLEND_FACTOR_ZERO),
+         RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR),
+      },
+      .constant_mask = 0x0,
+      .reads_dest = true,
+      .opaque = false,
+      .fixed_function = true,
+      .hardware = 0xA0231231 /* equivalently 0xA0321321 */
+   },
+
+};
+
+#define ASSERT_EQ(x, y) do { \
+   if (x == y) { \
+      nr_pass++; \
+   } else { \
+      nr_fail++; \
+      fprintf(stderr, "%s: Assertion failed %s (%x) != %s (%x)\n", \
+            T.label, #x, x, #y, y); \
+   } \
+} while(0)
+
+int main(int argc, const char **argv)
+{
+   unsigned nr_pass = 0, nr_fail = 0;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(blend_tests); ++i) {
+      struct test T = blend_tests[i];
+      ASSERT_EQ(T.constant_mask, pan_blend_constant_mask(T.eq));
+      ASSERT_EQ(T.reads_dest, pan_blend_reads_dest(T.eq));
+      ASSERT_EQ(T.opaque, pan_blend_is_opaque(T.eq));
+      ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq));
+
+      if (pan_blend_can_fixed_function(T.eq)) {
+         ASSERT_EQ(T.hardware, pan_pack_blend(T.eq));
+      }
+   }
+
+   printf("Passed %u/%u\n", nr_pass, nr_pass + nr_fail);
+   return nr_fail ? 1 : 0;
+}



More information about the mesa-commit mailing list