From 100b15cdc827feb5b9339502af9a3b10cc31a059 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 21 Aug 2020 18:11:57 -0400 Subject: [PATCH] panfrost: Add optional opaque packs to GenXML 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 Reviewed-by: Tomeu Vizoso Part-of: --- src/panfrost/lib/gen_pack.py | 48 ++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/panfrost/lib/gen_pack.py b/src/panfrost/lib/gen_pack.py index 8c1f2e755cd..e91769c193c 100644 --- a/src/panfrost/lib/gen_pack.py +++ b/src/panfrost/lib/gen_pack.py @@ -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) -- 2.30.2