pan/lower_fb: Support SNORM8 unpacking
authorBoris Brezillon <boris.brezillon@collabora.com>
Mon, 17 May 2021 12:53:05 +0000 (14:53 +0200)
committerMarge Bot <eric+marge@anholt.net>
Tue, 28 Sep 2021 18:59:46 +0000 (18:59 +0000)
Needed for panvk blend lowering.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12793>

src/panfrost/util/pan_lower_framebuffer.c

index 71795fd..a659ccd 100644 (file)
@@ -215,22 +215,34 @@ pan_unpack_pure_8(nir_builder *b, nir_ssa_def *pack, unsigned num_components)
         return nir_channels(b, unpacked, (1 << num_components) - 1);
 }
 
-/* For <= 8-bits per channel, UNORM formats are packed like UNORM 8, with
- * zeroes spacing out each component as needed */
+/* For <= 8-bits per channel, [U,S]NORM formats are packed like [U,S]NORM 8,
+ * with zeroes spacing out each component as needed */
 
 static nir_ssa_def *
-pan_pack_unorm(nir_builder *b, nir_ssa_def *v,
-               unsigned x, unsigned y, unsigned z, unsigned w)
+pan_pack_norm(nir_builder *b, nir_ssa_def *v,
+              unsigned x, unsigned y, unsigned z, unsigned w,
+              bool is_signed)
 {
-        /* If a channel has N bits, 1.0 is encoded as 2^N - 1 */
-        nir_ssa_def *scales = nir_imm_vec4_16(b,
-                        (1 << x) - 1, (1 << y) - 1, 
-                        (1 << z) - 1, (1 << w) - 1);
+        /* If a channel has N bits, 1.0 is encoded as 2^N - 1 for UNORMs and
+         * 2^(N-1) - 1 for SNORMs */
+        nir_ssa_def *scales =
+                is_signed ?
+                nir_imm_vec4_16(b,
+                                (1 << (x - 1)) - 1, (1 << (y - 1)) - 1,
+                                (1 << (z - 1)) - 1, (1 << (w - 1)) - 1) :
+                nir_imm_vec4_16(b,
+                                (1 << x) - 1, (1 << y) - 1,
+                                (1 << z) - 1, (1 << w) - 1);
 
         /* If a channel has N bits, we pad out to the byte by (8 - N) bits */
         nir_ssa_def *shifts = nir_imm_ivec4(b, 8 - x, 8 - y, 8 - z, 8 - w);
 
-        nir_ssa_def *f = nir_fmul(b, nir_fsat(b, nir_pad_vec4(b, v)), scales);
+        nir_ssa_def *clamped =
+                is_signed ?
+                nir_fsat_signed_mali(b, nir_pad_vec4(b, v)) :
+                nir_fsat(b, nir_pad_vec4(b, v));
+
+        nir_ssa_def *f = nir_fmul(b, clamped, scales);
         nir_ssa_def *u8 = nir_f2u8(b, nir_fround_even(b, f));
         nir_ssa_def *s = nir_ishl(b, u8, shifts);
         nir_ssa_def *repl = nir_pack_32_4x8(b, s);
@@ -238,6 +250,20 @@ pan_pack_unorm(nir_builder *b, nir_ssa_def *v,
         return pan_replicate_4(b, repl);
 }
 
+static nir_ssa_def *
+pan_pack_unorm(nir_builder *b, nir_ssa_def *v,
+               unsigned x, unsigned y, unsigned z, unsigned w)
+{
+        return pan_pack_norm(b, v, x, y, z, w, false);
+}
+
+static nir_ssa_def *
+pan_pack_snorm(nir_builder *b, nir_ssa_def *v,
+               unsigned x, unsigned y, unsigned z, unsigned w)
+{
+        return pan_pack_norm(b, v, x, y, z, w, true);
+}
+
 /* RGB10_A2 is packed in the tilebuffer as the bottom 3 bytes being the top
  * 8-bits of RGB and the top byte being RGBA as 2-bits packed. As imirkin
  * pointed out, this means free conversion to RGBX8 */
@@ -392,6 +418,9 @@ pan_pack(nir_builder *b,
         if (util_format_is_unorm8(desc))
                 return pan_pack_unorm(b, unpacked, 8, 8, 8, 8);
 
+        if (util_format_is_snorm8(desc->format))
+                return pan_pack_snorm(b, unpacked, 8, 8, 8, 8);
+
         if (desc->is_array) {
                 int c = util_format_get_first_non_void_channel(desc->format);
                 assert(c >= 0);