panfrost: Add padded type for instance fields
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 24 Aug 2020 17:36:22 +0000 (13:36 -0400)
committerMarge Bot <eric+marge@anholt.net>
Fri, 28 Aug 2020 14:53:53 +0000 (14:53 +0000)
Mali has a special 5:3 encoding representing a subset of the natural
numbers, of the form:

   a * (2^b)

for a odd and b natural/zero. It is used for padding out instance sizes,
as well as in attribute records so it's worth representing as a native
type as opposed to having manual packs/unpacks in various places.

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

src/panfrost/lib/gen_pack.py

index e91769c193caaa56813d2c383dc47a0c04d0d0b7..3fdef5c981ee001697048856b69e444d35bb1ff5 100644 (file)
@@ -81,6 +81,23 @@ __gen_sint(int32_t v, uint32_t start, uint32_t end)
    return ((uint32_t) v) << start;
 }
 
+static inline uint32_t
+__gen_padded(uint32_t v, uint32_t start, uint32_t end)
+{
+    unsigned shift = __builtin_ctz(v);
+    unsigned odd = v >> (shift + 1);
+
+#ifndef NDEBUG
+    assert((v >> shift) & 1);
+    assert(shift <= 31);
+    assert(odd <= 7);
+    assert((end - start + 1) == 8);
+#endif
+
+    return __gen_uint(shift | (odd << 5), start, end);
+}
+
+
 static inline uint64_t
 __gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
 {
@@ -105,6 +122,16 @@ __gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
    return (val << (64 - size)) >> (64 - size);
 }
 
+static inline uint64_t
+__gen_unpack_padded(const uint8_t *restrict cl, uint32_t start, uint32_t end)
+{
+   unsigned val = __gen_unpack_uint(cl, start, end);
+   unsigned shift = val & 0b11111;
+   unsigned odd = val >> 5;
+
+   return (2*odd + 1) << shift;
+}
+
 #define pan_pack(dst, T, name)                          \
    for (struct MALI_ ## T name = { MALI_ ## T ## _header }, \
         *_loop_terminate = (void *) (dst); \
@@ -224,7 +251,7 @@ class Field(object):
             type = 'uint64_t'
         elif self.type == 'int':
             type = 'int32_t'
-        elif self.type == 'uint':
+        elif self.type in ['uint', 'padded']:
             type = 'uint32_t'
         elif self.type in self.parser.structs:
             type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper()))
@@ -358,6 +385,9 @@ class Group(object):
                 if field.type == "uint" or field.type == "address":
                     s = "__gen_uint(%s, %d, %d)" % \
                         (value, start, end)
+                elif field.type == "padded":
+                    s = "__gen_padded(%s, %d, %d)" % \
+                        (value, start, end)
                 elif field.type in self.parser.enums:
                     s = "__gen_uint(%s, %d, %d)" % \
                         (value, start, end)
@@ -437,6 +467,8 @@ class Group(object):
                 convert = "__gen_unpack_uint"
             elif field.type == "int":
                 convert = "__gen_unpack_sint"
+            elif field.type == "padded":
+                convert = "__gen_unpack_padded"
             elif field.type == "bool":
                 convert = "__gen_unpack_uint"
             elif field.type == "float":