#!/usr/bin/env python3 """Turns a linked AMDGPU code object into a C header for the PS5 compute path. The PS5 path programs the compute registers itself, so it only supports kernels whose launch needs nothing but the kernel argument pointer (after an unused private segment buffer, if the compiler reserves one), wave64, no scratch and no LDS. Anything else fails the build instead of failing on the console. """ import struct import sys PT_LOAD = 1 PT_DYNAMIC = 2 SHT_SYMTAB = 2 DT_RELA, DT_RELASZ, DT_REL, DT_RELSZ = 7, 8, 17, 18 PROP_PRIVATE_BUFFER = 1 << 0 PROP_KERNARG_PTR = 1 << 3 PROP_WAVE32 = 1 << 10 def fail(message): sys.exit(f"embed-kernel: {message}") def main(): if len(sys.argv) != 4: sys.exit("usage: embed-kernel.py
") path, kernel, header = sys.argv[1:] data = open(path, "rb").read() if data[:4] != b"\x7fELF" or data[4] != 2: fail("not an ELF64 file") phoff, shoff = struct.unpack_from("> 1) & 0x1f if user_sgprs != kernarg_sgpr + 2: fail(f"unexpected user SGPR count {user_sgprs}") with open(header, "w") as out: out.write(f"#define KERNEL_ENTRY {entry:#x}\n") out.write(f"#define KERNEL_KERNARG_SIZE {kernarg_size}\n") out.write(f"#define KERNEL_KERNARG_SGPR {kernarg_sgpr}\n") out.write(f"#define KERNEL_USER_SGPRS {user_sgprs}\n") out.write(f"#define KERNEL_RSRC1 {rsrc1:#010x}u\n") out.write(f"#define KERNEL_RSRC2 {rsrc2:#010x}u\n") out.write(f"#define KERNEL_RSRC3 {rsrc3:#010x}u\n") out.write("static const unsigned char kernel_image[] = {\n") for i in range(0, len(image), 16): out.write(" " + ", ".join(f"0x{b:02x}" for b in image[i:i + 16]) + ",\n") out.write("};\n") main()