panfrost: Add optional opaque packs to GenXML
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 21 Aug 2020 22:11:57 +0000 (18:11 -0400)
committerTomeu Vizoso <tomeu.vizoso@collabora.com>
Tue, 25 Aug 2020 15:05:39 +0000 (17:05 +0200)
These special OPAQUE packs use packed structs in the struct template,
instead of struct templates. The use case is packing nested structs
out-of-band, to fit into the CSO model.

A more conventional GenXML solution would be an overlapping uint, but
this breaks our assumptions about struct packing which are otherwise
correct, so this seemed less intrusive than risk disrupting the main
pack routines.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6440>

src/panfrost/lib/gen_pack.py

index 8c1f2e755cdda1d232dfe76ea0ebce000ddc083b..e91769c193caaa56813d2c383dc47a0c04d0d0b7 100644 (file)
@@ -213,7 +213,7 @@ class Field(object):
 
         self.modifier  = parse_modifier(attrs.get("modifier"))
 
-    def emit_template_struct(self, dim):
+    def emit_template_struct(self, dim, opaque_structs):
         if self.type == 'address':
             type = 'uint64_t'
         elif self.type == 'bool':
@@ -228,6 +228,9 @@ class Field(object):
             type = 'uint32_t'
         elif self.type in self.parser.structs:
             type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper()))
+
+            if opaque_structs:
+                type = type.lower() + '_packed'
         elif self.type in self.parser.enums:
             type = 'enum ' + enum_name(self.type)
         else:
@@ -254,7 +257,7 @@ class Group(object):
         self.length = 0
         self.fields = []
 
-    def emit_template_struct(self, dim):
+    def emit_template_struct(self, dim, opaque_structs):
         if self.count == 0:
             print("   /* variable length fields follow */")
         else:
@@ -265,7 +268,7 @@ class Group(object):
                 if field.exact is not None:
                     continue
 
-                field.emit_template_struct(dim)
+                field.emit_template_struct(dim, opaque_structs)
 
     class Word:
         def __init__(self):
@@ -283,7 +286,7 @@ class Group(object):
 
                 words[b].fields.append(field)
 
-    def emit_pack_function(self):
+    def emit_pack_function(self, opaque_structs):
         # Determine number of bytes in this group.
         calculated = max(field.end // 8 for field in self.fields) + 1
 
@@ -330,9 +333,13 @@ class Group(object):
                 start = first.start
                 assert((first.start % 32) == 0)
                 assert(first.end == first.start + (self.parser.structs[first.type].length * 8) - 1)
-                print("   {}_pack(cl + {}, &values->{});".format(pack_name, first.start // 32, first.name))
                 emitted_structs.add(first.start)
 
+                if opaque_structs:
+                    print("   memcpy(cl + {}, &values->{}, {});".format(first.start // 32, first.name, (first.end - first.start + 1) // 8))
+                else:
+                    print("   {}_pack(cl + {}, &values->{});".format(pack_name, first.start // 32, first.name))
+
             for field in word.fields:
                 name = field.name
                 start = field.start
@@ -497,6 +504,7 @@ class Parser(object):
             print(pack_header)
         elif name == "struct":
             name = attrs["name"]
+            self.with_opaque = attrs.get("with_opaque", False)
 
             object_name = self.gen_prefix(safe_name(name.upper()))
             self.struct = object_name
@@ -548,18 +556,30 @@ class Parser(object):
         print(",  \\\n".join(default_fields))
         print('')
 
-    def emit_template_struct(self, name, group):
-        print("struct %s {" % name)
-        group.emit_template_struct("")
+    def emit_template_struct(self, name, group, opaque_structs):
+        print("struct %s {" % (name + ('_OPAQUE' if opaque_structs else '')))
+        group.emit_template_struct("", opaque_structs)
         print("};\n")
 
-    def emit_pack_function(self, name, group):
+        if opaque_structs:
+            # Just so it isn't left undefined
+            print('#define %-40s 0' % (name + '_OPAQUE_header'))
+
+    def emit_pack_function(self, name, group, with_opaque):
         print("static inline void\n%s_pack(uint32_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %
               (name, ' ' * (len(name) + 6), name))
 
-        group.emit_pack_function()
+        group.emit_pack_function(False)
 
-        print("}\n")
+        print("}\n\n")
+
+        if with_opaque:
+            print("static inline void\n%s_OPAQUE_pack(uint32_t * restrict cl,\n%sconst struct %s_OPAQUE * restrict values)\n{" %
+                  (name, ' ' * (len(name) + 6), name))
+
+            group.emit_pack_function(True)
+
+            print("}\n")
 
         # Should be a whole number of words
         assert((self.group.length % 4) == 0)
@@ -587,9 +607,11 @@ class Parser(object):
     def emit_struct(self):
         name = self.struct
 
-        self.emit_template_struct(self.struct, self.group)
+        self.emit_template_struct(self.struct, self.group, False)
+        if self.with_opaque:
+            self.emit_template_struct(self.struct, self.group, True)
         self.emit_header(name)
-        self.emit_pack_function(self.struct, self.group)
+        self.emit_pack_function(self.struct, self.group, self.with_opaque)
         self.emit_unpack_function(self.struct, self.group)
         self.emit_print_function(self.struct, self.group)