panfrost: gen_pack: Add the aggregate concept
Panfrost descriptors are big and are usually built from a combination of sub-descriptors. On top of that, layout of sub-descriptors might vary depending on the architecture version. Since unions are not really an option (too complex), here is a thin abstraction layer allowing us to manipulate aggregates in their packed format. Each aggregate is formed of one or more sections that are meant to be packed/unpacked/printed separately. Section overlapping is allowed to facilitate handling of descriptor variants. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6797>
This commit is contained in:

committed by
Alyssa Rosenzweig

parent
fa7d0974fb
commit
c7a10193d4
@@ -145,6 +145,23 @@ __gen_unpack_padded(const uint8_t *restrict cl, uint32_t start, uint32_t end)
|
||||
#define pan_print(fp, T, var, indent) \\
|
||||
MALI_ ## T ## _print(fp, &(var), indent)
|
||||
|
||||
#define pan_section_ptr(base, A, S) \\
|
||||
((void *)((uint8_t *)(base) + MALI_ ## A ## _SECTION_ ## S ## _OFFSET))
|
||||
|
||||
#define pan_section_pack(dst, A, S, name) \\
|
||||
for (MALI_ ## A ## _SECTION_ ## S ## _TYPE name = { MALI_ ## A ## _SECTION_ ## S ## _header }, \\
|
||||
*_loop_terminate = (void *) (dst); \\
|
||||
__builtin_expect(_loop_terminate != NULL, 1); \\
|
||||
({ MALI_ ## A ## _SECTION_ ## S ## _pack(pan_section_ptr(dst, A, S), &name); \\
|
||||
_loop_terminate = NULL; }))
|
||||
|
||||
#define pan_section_unpack(src, A, S, name) \\
|
||||
MALI_ ## A ## _SECTION_ ## S ## _TYPE name; \\
|
||||
MALI_ ## A ## _SECTION_ ## S ## _unpack(pan_section_ptr(src, A, S), &name)
|
||||
|
||||
#define pan_section_print(fp, A, S, var, indent) \\
|
||||
MALI_ ## A ## _SECTION_ ## S ## _print(fp, &(var), indent)
|
||||
|
||||
"""
|
||||
|
||||
def to_alphanum(name):
|
||||
@@ -209,6 +226,43 @@ def parse_modifier(modifier):
|
||||
print("Invalid modifier")
|
||||
assert(False)
|
||||
|
||||
class Aggregate(object):
|
||||
def __init__(self, parser, name, attrs):
|
||||
self.parser = parser
|
||||
self.sections = []
|
||||
self.name = name
|
||||
self.explicit_size = int(attrs["size"]) if "size" in attrs else 0
|
||||
self.size = 0
|
||||
|
||||
class Section:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def get_size(self):
|
||||
if self.size > 0:
|
||||
return self.size
|
||||
|
||||
size = 0
|
||||
for section in self.sections:
|
||||
size = max(size, section.offset + section.type.get_length())
|
||||
|
||||
if self.explicit_size > 0:
|
||||
assert(self.explicit_size >= size)
|
||||
self.size = self.explicit_size
|
||||
else:
|
||||
self.size = size
|
||||
return self.size
|
||||
|
||||
def add_section(self, type_name, attrs):
|
||||
assert("name" in attrs)
|
||||
section = self.Section(safe_name(attrs["name"]).lower())
|
||||
section.human_name = attrs["name"]
|
||||
section.offset = int(attrs["offset"])
|
||||
assert(section.offset % 4 == 0)
|
||||
section.type = self.parser.structs[attrs["type"]]
|
||||
section.type_name = type_name
|
||||
self.sections.append(section)
|
||||
|
||||
class Field(object):
|
||||
def __init__(self, parser, attrs):
|
||||
self.parser = parser
|
||||
@@ -279,7 +333,6 @@ class Field(object):
|
||||
def overlaps(self, field):
|
||||
return self != field and max(self.start, field.start) <= min(self.end, field.end)
|
||||
|
||||
|
||||
class Group(object):
|
||||
def __init__(self, parser, parent, start, count):
|
||||
self.parser = parser
|
||||
@@ -537,6 +590,8 @@ class Parser(object):
|
||||
self.structs = {}
|
||||
# Set of enum names we've seen.
|
||||
self.enums = set()
|
||||
self.aggregate = None
|
||||
self.aggregates = {}
|
||||
|
||||
def gen_prefix(self, name):
|
||||
return '{}_{}'.format(global_prefix.upper(), name)
|
||||
@@ -568,6 +623,13 @@ class Parser(object):
|
||||
self.prefix= None
|
||||
elif name == "value":
|
||||
self.values.append(Value(attrs))
|
||||
elif name == "aggregate":
|
||||
aggregate_name = self.gen_prefix(safe_name(attrs["name"].upper()))
|
||||
self.aggregate = Aggregate(self, aggregate_name, attrs)
|
||||
self.aggregates[attrs['name']] = self.aggregate
|
||||
elif name == "section":
|
||||
type_name = self.gen_prefix(safe_name(attrs["type"].upper()))
|
||||
self.aggregate.add_section(type_name, attrs)
|
||||
|
||||
def end_element(self, name):
|
||||
if name == "struct":
|
||||
@@ -579,6 +641,9 @@ class Parser(object):
|
||||
elif name == "enum":
|
||||
self.emit_enum()
|
||||
self.enum = None
|
||||
elif name == "aggregate":
|
||||
self.emit_aggregate()
|
||||
self.aggregate = None
|
||||
elif name == "panxml":
|
||||
# Include at the end so it can depend on us but not the converse
|
||||
print('#include "panfrost-job.h"')
|
||||
@@ -610,6 +675,21 @@ class Parser(object):
|
||||
# Just so it isn't left undefined
|
||||
print('#define %-40s 0' % (name + '_OPAQUE_header'))
|
||||
|
||||
def emit_aggregate(self):
|
||||
aggregate = self.aggregate
|
||||
print("struct %s_packed {" % aggregate.name.lower())
|
||||
print(" uint32_t opaque[{}];".format(aggregate.get_size() // 4))
|
||||
print("};\n")
|
||||
print('#define {}_LENGTH {}'.format(aggregate.name.upper(), aggregate.size))
|
||||
for section in aggregate.sections:
|
||||
print('#define {}_SECTION_{}_TYPE struct {}'.format(aggregate.name.upper(), section.name.upper(), section.type_name))
|
||||
print('#define {}_SECTION_{}_header {}_header'.format(aggregate.name.upper(), section.name.upper(), section.type_name))
|
||||
print('#define {}_SECTION_{}_pack {}_pack'.format(aggregate.name.upper(), section.name.upper(), section.type_name))
|
||||
print('#define {}_SECTION_{}_unpack {}_unpack'.format(aggregate.name.upper(), section.name.upper(), section.type_name))
|
||||
print('#define {}_SECTION_{}_print {}_print'.format(aggregate.name.upper(), section.name.upper(), section.type_name))
|
||||
print('#define {}_SECTION_{}_OFFSET {}'.format(aggregate.name.upper(), section.name.upper(), section.offset))
|
||||
print("")
|
||||
|
||||
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))
|
||||
|
Reference in New Issue
Block a user