asahi: Make GenXML compatible with OpenCL

Adapt gen_pack.py to generate an OpenCL compatible header, capable of both
packing and unpacking but not printing (due to no known use case and no fprintf
in CL). This is useful as a building block for manipulating descriptors from
shader code, for example in texture lowering or device-generated commands.

To accomplish this, we need to inline in some CL-compatible variants of mesa
util functions (no doubles, etc), avoid FILE * use in the CL path, and use
__constant pointers where applicable for performance. Otherwise, there are
surprisingly few changes required, thanks mainly to CL 2.0 generic pointers.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25498>
This commit is contained in:
Alyssa Rosenzweig 2023-09-19 16:18:44 -04:00 committed by Marge Bot
parent 59499d8dbc
commit 0df82f76c4

View file

@ -24,19 +24,76 @@ pack_header = """
#ifndef AGX_PACK_H
#define AGX_PACK_H
#ifndef __OPENCL_VERSION__
#include <stdio.h>
#include <inttypes.h>
#include "util/bitpack_helpers.h"
#define FILE_TYPE FILE
#define CONSTANT const
#else
#include "libagx.h"
#define assert(x)
#define FILE_TYPE void
#define CONSTANT constant
static uint64_t
util_bitpack_uint(uint64_t v, uint32_t start, uint32_t end)
{
return v << start;
}
static uint64_t
util_bitpack_sint(int64_t v, uint32_t start, uint32_t end)
{
const int bits = end - start + 1;
const uint64_t mask = (bits == 64) ? ~((uint64_t)0) : (1ull << bits) - 1;
return (v & mask) << start;
}
static uint32_t
util_bitpack_float(float v)
{
union { float f; uint32_t dw; } x;
x.f = v;
return x.dw;
}
static inline float
uif(uint32_t ui)
{
union { float f; uint32_t dw; } fi;
fi.dw = ui;
return fi.f;
}
#define DIV_ROUND_UP( A, B ) ( ((A) + (B) - 1) / (B) )
#define CLAMP( X, MIN, MAX ) ( (X)>(MIN) ? ((X)>(MAX) ? (MAX) : (X)) : (MIN) )
#define ALIGN_POT(x, pot_align) (((x) + (pot_align) - 1) & ~((pot_align) - 1))
static inline unsigned
util_logbase2(unsigned n)
{
return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1));
}
static inline int64_t
util_sign_extend(uint64_t val, unsigned width)
{
unsigned shift = 64 - width;
return (int64_t)(val << shift) >> shift;
}
#endif
#define __gen_unpack_float(x, y, z) uif(__gen_unpack_uint(x, y, z))
static inline uint64_t
__gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
__gen_unpack_uint(CONSTANT uint8_t *restrict cl, uint32_t start, uint32_t end)
{
uint64_t val = 0;
const int width = end - start + 1;
const uint64_t mask = (width == 64 ? ~0 : (1ull << width) - 1 );
const uint64_t mask = (width == 64) ? ~((uint64_t)0) : ((uint64_t)1 << width) - 1;
for (unsigned byte = start / 8; byte <= end / 8; byte++) {
val |= ((uint64_t) cl[byte]) << ((byte - start / 8) * 8);
@ -57,13 +114,13 @@ __gen_pack_lod(float f, uint32_t start, uint32_t end)
}
static inline float
__gen_unpack_lod(const uint8_t *restrict cl, uint32_t start, uint32_t end)
__gen_unpack_lod(CONSTANT uint8_t *restrict cl, uint32_t start, uint32_t end)
{
return ((float) __gen_unpack_uint(cl, start, end)) / (1 << 6);
}
static inline uint64_t
__gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
__gen_unpack_sint(CONSTANT uint8_t *restrict cl, uint32_t start, uint32_t end)
{
int size = end - start + 1;
int64_t val = __gen_unpack_uint(cl, start, end);
@ -106,7 +163,7 @@ __gen_from_groups(uint32_t value, uint32_t group_size, uint32_t length)
#define agx_unpack(fp, src, T, name) \\
struct AGX_ ## T name; \\
AGX_ ## T ## _unpack(fp, (uint8_t *)(src), &name)
AGX_ ## T ## _unpack(fp, (CONSTANT uint8_t *)(src), &name)
#define agx_print(fp, T, var, indent) \\
AGX_ ## T ## _print(fp, &(var), indent)
@ -438,6 +495,7 @@ class Group(object):
words = {}
self.collect_words(self.fields, 0, '', words)
print('#ifndef __OPENCL_VERSION__')
for index in range(self.length // 4):
base = index * 32
word = words.get(index, self.Word())
@ -449,6 +507,7 @@ class Group(object):
if mask != ALL_ONES:
TMPL = ' if (((const uint32_t *) cl)[{}] & {}) fprintf(fp, "XXX: Unknown field of {} unpacked at word {}: got %X, bad mask %X\\n", ((const uint32_t *) cl)[{}], ((const uint32_t *) cl)[{}] & {});'
print(TMPL.format(index, hex(mask ^ ALL_ONES), self.label, index, index, index, hex(mask ^ ALL_ONES)))
print('#endif')
fieldrefs = []
self.collect_fields(self.fields, 0, '', fieldrefs)
@ -624,7 +683,7 @@ class Parser(object):
def emit_unpack_function(self, name, group):
print("static inline void")
print("%s_unpack(FILE *fp, const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
print("%s_unpack(FILE_TYPE *fp, CONSTANT uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
(name.upper(), ' ' * (len(name) + 8), name))
group.emit_unpack_function()
@ -632,12 +691,14 @@ class Parser(object):
print("}\n")
def emit_print_function(self, name, group):
print("#ifndef __OPENCL_VERSION__")
print("static inline void")
print("{}_print(FILE *fp, const struct {} * values, unsigned indent)\n{{".format(name.upper(), name))
group.emit_print_function()
print("}\n")
print("#endif")
def emit_struct(self):
name = self.struct
@ -662,6 +723,7 @@ class Parser(object):
print(' % -36s = %6d,' % (name, value.value))
print('};\n')
print("#ifndef __OPENCL_VERSION__")
print("static inline const char *")
print("{}_as_str(enum {} imm)\n{{".format(e_name.lower(), e_name))
print(" switch (imm) {")
@ -673,6 +735,7 @@ class Parser(object):
print(" }")
print(" return NULL;")
print("}\n")
print("#endif")
def parse(self, filename):
file = open(filename, "rb")