xref: /aosp_15_r20/external/mesa3d/src/intel/vulkan/grl/grl_cl_kernel_gen.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1COPYRIGHT = """\
2/*
3 * Copyright 2021 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25"""
26
27import argparse
28import os
29
30from grl_parser import parse_grl_file
31from mako.template import Template
32
33TEMPLATE_H = Template(COPYRIGHT + """
34/* This file generated from ${filename}, don't edit directly. */
35
36#ifndef GRL_CL_KERNEL_H
37#define GRL_CL_KERNEL_H
38
39#include "genxml/gen_macros.h"
40#include "compiler/brw_kernel.h"
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46enum grl_cl_kernel {
47% for k in kernels:
48    GRL_CL_KERNEL_${k.upper()},
49% endfor
50    GRL_CL_KERNEL_MAX,
51};
52
53const char *genX(grl_cl_kernel_name)(enum grl_cl_kernel kernel);
54
55const char *genX(grl_get_cl_kernel_sha1)(enum grl_cl_kernel id);
56
57void genX(grl_get_cl_kernel)(struct brw_kernel *kernel, enum grl_cl_kernel id);
58
59#ifdef __cplusplus
60} /* extern "C" */
61#endif
62
63#endif /* INTEL_GRL_H */
64""")
65
66TEMPLATE_C = Template(COPYRIGHT + """
67/* This file generated from ${filename}, don't edit directly. */
68
69#include "grl_cl_kernel.h"
70
71% for k in kernels:
72#include "${prefix}_${k}.h"
73% endfor
74
75const char *
76genX(grl_cl_kernel_name)(enum grl_cl_kernel kernel)
77{
78    switch (kernel) {
79% for k in kernels:
80    case GRL_CL_KERNEL_${k.upper()}: return "${k}";
81% endfor
82    default: return "unknown";
83    }
84}
85
86const char *
87genX(grl_get_cl_kernel_sha1)(enum grl_cl_kernel id)
88{
89    switch (id) {
90% for k in kernels:
91    case GRL_CL_KERNEL_${k.upper()}: return ${prefix}_${k}_sha1;
92% endfor
93    default:
94        unreachable("Invalid GRL kernel enum");
95    }
96};
97
98void
99${prefix}_grl_get_cl_kernel(struct brw_kernel *kernel, enum grl_cl_kernel id)
100{
101    switch (id) {
102% for k in kernels:
103    case GRL_CL_KERNEL_${k.upper()}:
104        *kernel = ${prefix}_${k};
105        break;
106% endfor
107    default:
108        unreachable("Invalid GRL kernel enum");
109    }
110}
111""")
112
113def get_libraries_files(kernel_module):
114    lib_files = []
115    for item in kernel_module[3]:
116        if item[0] != 'library':
117            continue
118        default_file = None
119        fallback_file = None
120        path_directory = None
121        for props in item[2]:
122            if props[0] == 'fallback':
123                fallback_file = props[1]
124            elif props[0] == 'default':
125                default_file = props[1]
126            elif props[0] == 'path':
127                path_directory = props[1]
128        assert path_directory
129        assert default_file or fallback_file
130        if fallback_file:
131            lib_files.append(os.path.join(path_directory, fallback_file))
132        else:
133            lib_files.append(os.path.join(path_directory, default_file))
134    return lib_files
135
136def add_kernels(kernels, cl_file, entrypoint, libs):
137    assert cl_file.endswith('.cl')
138    for lib_file in libs:
139        assert lib_file.endswith('.cl')
140    kernels.append((cl_file, entrypoint, ','.join(libs)))
141
142def get_kernels(grl_nodes):
143    kernels = []
144    for item in grl_nodes:
145        assert isinstance(item, tuple)
146        if item[0] == 'kernel':
147            ann = item[2]
148            add_kernels(kernels, ann['source'], ann['kernelFunction'], [])
149        elif item[0] == 'kernel-module':
150            cl_file = item[2]
151            libfiles = get_libraries_files(item)
152            for kernel_def in item[3]:
153                if kernel_def[0] == 'kernel':
154                    ann = kernel_def[2]
155                    add_kernels(kernels, cl_file, ann['kernelFunction'], libfiles)
156    return kernels
157
158def parse_libraries(filenames):
159    libraries = {}
160    for fname in filenames:
161        lib_package = parse_grl_file(fname, [])
162        for lib in lib_package:
163            assert lib[0] == 'library'
164            # Add the directory of the library so that CL files can be found.
165            lib[2].append(('path', os.path.dirname(fname)))
166            libraries[lib[1]] = lib
167    return libraries
168
169def main():
170    parser = argparse.ArgumentParser()
171    parser.add_argument('--out-c', help='Output C file')
172    parser.add_argument('--out-h', help='Output H file')
173    parser.add_argument('--ls-kernels', action='store_const', const=True,
174                        help='List all openCL kernels')
175    parser.add_argument('--prefix', help='Prefix')
176    parser.add_argument('--library', dest='libraries', action='append',
177                        default=[], help='Libraries to include')
178    parser.add_argument('files', type=str, nargs='*', help='GRL files')
179    args = parser.parse_args()
180
181    libraries = parse_libraries(args.libraries)
182
183    kernels = []
184    for fname in args.files:
185        kernels += get_kernels(parse_grl_file(fname, libraries))
186
187    # Make the list of kernels unique and sorted
188    kernels = sorted(list(set(kernels)))
189
190    if args.ls_kernels:
191        for cl_file, entrypoint, libs in kernels:
192            if not os.path.isabs(cl_file):
193                cl_file = os.path.join(os.path.dirname(fname), cl_file)
194            print('{}:{}:{}'.format(cl_file, entrypoint, libs))
195
196    kernel_c_names = []
197    for cl_file, entrypoint, libs in kernels:
198        cl_file = os.path.splitext(cl_file)[0]
199        cl_file_name = cl_file.replace('/', '_')
200        kernel_c_names.append('_'.join([cl_file_name, entrypoint]))
201
202    try:
203        if args.out_h:
204            with open(args.out_h, 'w', encoding='utf-8') as f:
205                f.write(TEMPLATE_H.render(kernels=kernel_c_names,
206                                          filename=os.path.basename(__file__)))
207
208        if args.out_c:
209            with open(args.out_c, 'w', encoding='utf-8') as f:
210                f.write(TEMPLATE_C.render(kernels=kernel_c_names,
211                                          prefix=args.prefix,
212                                          filename=os.path.basename(__file__)))
213    except Exception:
214        # In the event there's an error, this imports some helpers from mako
215        # to print a useful stack trace and prints it, then exits with
216        # status 1, if python is run with debug; otherwise it just raises
217        # the exception
218        if __debug__:
219            import sys
220            from mako import exceptions
221            sys.stderr.write(exceptions.text_error_template().render() + '\n')
222            sys.exit(1)
223        raise
224
225if __name__ == '__main__':
226    main()
227