xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/codec/kernel/merge.py (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1import os,shutil
2import sys
3import argparse
4
5import struct
6import os
7from sys import platform
8
9# Usage:
10#   merge.py -o out_file in_file [in_file...]
11#
12# Description:
13#   This script merges N kernels given in arguments (in_file...) to the common kernel (out_file) according
14# to the following output format:
15#
16# | DW0: kernel_count | DW1: offset_of_kernel_1 | DW1: offset_of_kernel_2 | ... | DW15: offset_of_kernel_15 |
17# |                                     kernel_1 (size aligned to 64 bytes)                                 |
18# |                                     kernel_2 (size aligned to 64 bytes)                                 |
19# |                                                 ...                                                     |
20# |                                     kernel_15 (size aligned to 64 bytes)                                |
21# |                                            padding 128 bytes                                            |
22#
23# Limitations:
24#   - No more than 15 kernels are being merged
25
26parser = argparse.ArgumentParser()
27parser.add_argument("-o", "--output", dest="out_file", required=True,
28    help="merged output kernel file name")
29parser.add_argument('dat_files', metavar='IN_FILE', type=str, nargs='+',
30    help='list of input kernels to merge into common kernel (.dat files, order is important)')
31args = parser.parse_args()
32
33removeList = []
34for filename in args.dat_files:
35    print("fileName: " + filename)
36    if(not os.path.exists(filename)):
37         print("File %s doesn't exist!" % filename)
38         removeList.append(filename)
39for filename in removeList:
40    args.dat_files.remove(filename)
41
42n_dats = len(args.dat_files)
43if n_dats > 15:
44    raise Exception("Can't merge more than 15 files")
45
46offset  = [0 for i in range(64)]
47padding = [0 for i in range(64)]
48
49# offset of the first kernel (first 64 bytes are header for combined kernel)
50offset[0] = 64
51# program offset for each kernel in the header of combined kernel
52for i in range(n_dats):
53    count = offset[i] + os.path.getsize(args.dat_files[i])
54    next_offset = ((count + 63) >> 6) << 6 # align next kernel at 64-bytes
55    padding[i] = next_offset - count
56    if (i != n_dats-1):
57        offset[i+1] = next_offset
58
59output = open(args.out_file, 'wb')
60
61# total number of kernels we are going to merge
62bytes = struct.pack('i', n_dats)
63output.write(bytes)
64
65# write offsets
66for i in range(n_dats):
67    bytes = struct.pack('i', offset[i])
68    output.write(bytes)
69
70# zero fill for the rest of the header, totally:
71#  64 bytes header - 4*number_of_kernels - 4 bytes for number of kernels
72zerofill = chr(0)*(64 - 4 - (n_dats << 2))
73output.write(zerofill.encode(encoding = "utf-8"))
74
75# write combined kernel, each child kernel is 64 bytes aligned
76for i in range(n_dats):
77    fileobj  = open(args.dat_files[i], 'rb')
78    while 1:
79        filebytes = fileobj.read()
80        if not filebytes:
81            zerofill = chr(0)*padding[i]
82            output.write(zerofill.encode(encoding = "utf-8"))
83            break
84        output.write(filebytes)
85    fileobj.close()
86
87# padding 128 bytes at the end of combined kernel which is required by HW
88zerofill = chr(0)*128
89output.write(zerofill.encode(encoding = "utf-8"))
90
91output.close()
92print ("Completed kernel merge")
93