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 <alyssa.rosenzweig@collabora.com>
Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6440>
This commit is contained in:
Alyssa Rosenzweig 2020-08-21 18:11:57 -04:00 committed by Tomeu Vizoso
parent a7b2317d0a
commit 100b15cdc8
1 changed files with 35 additions and 13 deletions

View 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)