1bf215546Sopenharmony_ciCOPYRIGHT=u"""
2bf215546Sopenharmony_ci/* Copyright © 2015-2021 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci"""
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ciimport argparse
26bf215546Sopenharmony_ciimport os
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_cifrom mako.template import Template
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci# Mesa-local imports must be declared in meson variable
31bf215546Sopenharmony_ci# '{file_without_suffix}_depend_files'.
32bf215546Sopenharmony_cifrom vk_entrypoints import get_entrypoints_from_xml
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ciTEMPLATE_H = Template(COPYRIGHT + """\
35bf215546Sopenharmony_ci/* This file generated from ${filename}, don't edit directly. */
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "vk_dispatch_table.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#ifndef ${guard}
40bf215546Sopenharmony_ci#define ${guard}
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#ifdef __cplusplus
43bf215546Sopenharmony_ciextern "C" {
44bf215546Sopenharmony_ci#endif
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci% for p in instance_prefixes:
47bf215546Sopenharmony_ciextern const struct vk_instance_entrypoint_table ${p}_instance_entrypoints;
48bf215546Sopenharmony_ci% endfor
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci% for p in physical_device_prefixes:
51bf215546Sopenharmony_ciextern const struct vk_physical_device_entrypoint_table ${p}_physical_device_entrypoints;
52bf215546Sopenharmony_ci% endfor
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci% for p in device_prefixes:
55bf215546Sopenharmony_ciextern const struct vk_device_entrypoint_table ${p}_device_entrypoints;
56bf215546Sopenharmony_ci% endfor
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci% if gen_proto:
59bf215546Sopenharmony_ci% for e in instance_entrypoints:
60bf215546Sopenharmony_ci  % if e.guard is not None:
61bf215546Sopenharmony_ci#ifdef ${e.guard}
62bf215546Sopenharmony_ci  % endif
63bf215546Sopenharmony_ci  % for p in physical_device_prefixes:
64bf215546Sopenharmony_ci  VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
65bf215546Sopenharmony_ci  % endfor
66bf215546Sopenharmony_ci  % if e.guard is not None:
67bf215546Sopenharmony_ci#endif // ${e.guard}
68bf215546Sopenharmony_ci  % endif
69bf215546Sopenharmony_ci% endfor
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci% for e in physical_device_entrypoints:
72bf215546Sopenharmony_ci  % if e.guard is not None:
73bf215546Sopenharmony_ci#ifdef ${e.guard}
74bf215546Sopenharmony_ci  % endif
75bf215546Sopenharmony_ci  % for p in physical_device_prefixes:
76bf215546Sopenharmony_ci  VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
77bf215546Sopenharmony_ci  % endfor
78bf215546Sopenharmony_ci  % if e.guard is not None:
79bf215546Sopenharmony_ci#endif // ${e.guard}
80bf215546Sopenharmony_ci  % endif
81bf215546Sopenharmony_ci% endfor
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci% for e in device_entrypoints:
84bf215546Sopenharmony_ci  % if e.guard is not None:
85bf215546Sopenharmony_ci#ifdef ${e.guard}
86bf215546Sopenharmony_ci  % endif
87bf215546Sopenharmony_ci  % for p in device_prefixes:
88bf215546Sopenharmony_ci  VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
89bf215546Sopenharmony_ci  % endfor
90bf215546Sopenharmony_ci  % if e.guard is not None:
91bf215546Sopenharmony_ci#endif // ${e.guard}
92bf215546Sopenharmony_ci  % endif
93bf215546Sopenharmony_ci% endfor
94bf215546Sopenharmony_ci% endif
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci#ifdef __cplusplus
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci#endif
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci#endif /* ${guard} */
101bf215546Sopenharmony_ci""")
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ciTEMPLATE_C = Template(COPYRIGHT + """
104bf215546Sopenharmony_ci/* This file generated from ${filename}, don't edit directly. */
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci#include "${header}"
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci/* Weak aliases for all potential implementations. These will resolve to
109bf215546Sopenharmony_ci * NULL if they're not defined, which lets the resolve_entrypoint() function
110bf215546Sopenharmony_ci * either pick the correct entry point.
111bf215546Sopenharmony_ci *
112bf215546Sopenharmony_ci * MSVC uses different decorated names for 32-bit versus 64-bit. Declare
113bf215546Sopenharmony_ci * all argument sizes for 32-bit because computing the actual size would be
114bf215546Sopenharmony_ci * difficult.
115bf215546Sopenharmony_ci */
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci<%def name="entrypoint_table(type, entrypoints, prefixes)">
118bf215546Sopenharmony_ci% if gen_weak:
119bf215546Sopenharmony_ci  % for e in entrypoints:
120bf215546Sopenharmony_ci    % if e.guard is not None:
121bf215546Sopenharmony_ci#ifdef ${e.guard}
122bf215546Sopenharmony_ci    % endif
123bf215546Sopenharmony_ci    % for p in prefixes:
124bf215546Sopenharmony_ci#ifdef _MSC_VER
125bf215546Sopenharmony_ci#ifdef _M_IX86
126bf215546Sopenharmony_ci      % for args_size in [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 60, 104]:
127bf215546Sopenharmony_ci    #pragma comment(linker, "/alternatename:_${p}_${e.name}@${args_size}=_vk_entrypoint_stub@0")
128bf215546Sopenharmony_ci      % endfor
129bf215546Sopenharmony_ci#else
130bf215546Sopenharmony_ci    #pragma comment(linker, "/alternatename:${p}_${e.name}=vk_entrypoint_stub")
131bf215546Sopenharmony_ci#if defined(_M_ARM64EC)
132bf215546Sopenharmony_ci    #pragma comment(linker, "/alternatename:#${p}_${e.name}=#vk_entrypoint_stub")
133bf215546Sopenharmony_ci#endif
134bf215546Sopenharmony_ci#endif
135bf215546Sopenharmony_ci#else
136bf215546Sopenharmony_ci    VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) __attribute__ ((weak));
137bf215546Sopenharmony_ci#endif
138bf215546Sopenharmony_ci    % endfor
139bf215546Sopenharmony_ci    % if e.guard is not None:
140bf215546Sopenharmony_ci#endif // ${e.guard}
141bf215546Sopenharmony_ci    % endif
142bf215546Sopenharmony_ci  % endfor
143bf215546Sopenharmony_ci% endif
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci% for p in prefixes:
146bf215546Sopenharmony_ciconst struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = {
147bf215546Sopenharmony_ci  % for e in entrypoints:
148bf215546Sopenharmony_ci    % if e.guard is not None:
149bf215546Sopenharmony_ci#ifdef ${e.guard}
150bf215546Sopenharmony_ci    % endif
151bf215546Sopenharmony_ci    .${e.name} = ${p}_${e.name},
152bf215546Sopenharmony_ci    % if e.guard is not None:
153bf215546Sopenharmony_ci#elif defined(_MSC_VER)
154bf215546Sopenharmony_ci    .${e.name} = (PFN_vkVoidFunction)vk_entrypoint_stub,
155bf215546Sopenharmony_ci#endif // ${e.guard}
156bf215546Sopenharmony_ci    % endif
157bf215546Sopenharmony_ci  % endfor
158bf215546Sopenharmony_ci};
159bf215546Sopenharmony_ci% endfor
160bf215546Sopenharmony_ci</%def>
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci${entrypoint_table('instance', instance_entrypoints, instance_prefixes)}
163bf215546Sopenharmony_ci${entrypoint_table('physical_device', physical_device_entrypoints, physical_device_prefixes)}
164bf215546Sopenharmony_ci${entrypoint_table('device', device_entrypoints, device_prefixes)}
165bf215546Sopenharmony_ci""")
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_cidef get_entrypoints_defines(doc):
168bf215546Sopenharmony_ci    """Maps entry points to extension defines."""
169bf215546Sopenharmony_ci    entrypoints_to_defines = {}
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci    platform_define = {}
172bf215546Sopenharmony_ci    for platform in doc.findall('./platforms/platform'):
173bf215546Sopenharmony_ci        name = platform.attrib['name']
174bf215546Sopenharmony_ci        define = platform.attrib['protect']
175bf215546Sopenharmony_ci        platform_define[name] = define
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci    for extension in doc.findall('./extensions/extension[@platform]'):
178bf215546Sopenharmony_ci        platform = extension.attrib['platform']
179bf215546Sopenharmony_ci        define = platform_define[platform]
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci        for entrypoint in extension.findall('./require/command'):
182bf215546Sopenharmony_ci            fullname = entrypoint.attrib['name']
183bf215546Sopenharmony_ci            entrypoints_to_defines[fullname] = define
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci    return entrypoints_to_defines
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_cidef main():
189bf215546Sopenharmony_ci    parser = argparse.ArgumentParser()
190bf215546Sopenharmony_ci    parser.add_argument('--out-c', required=True, help='Output C file.')
191bf215546Sopenharmony_ci    parser.add_argument('--out-h', required=True, help='Output H file.')
192bf215546Sopenharmony_ci    parser.add_argument('--xml',
193bf215546Sopenharmony_ci                        help='Vulkan API XML file.',
194bf215546Sopenharmony_ci                        required=True, action='append', dest='xml_files')
195bf215546Sopenharmony_ci    parser.add_argument('--proto', help='Generate entrypoint prototypes',
196bf215546Sopenharmony_ci                        action='store_true', dest='gen_proto')
197bf215546Sopenharmony_ci    parser.add_argument('--weak', help='Generate weak entrypoint declarations',
198bf215546Sopenharmony_ci                        action='store_true', dest='gen_weak')
199bf215546Sopenharmony_ci    parser.add_argument('--prefix',
200bf215546Sopenharmony_ci                        help='Prefix to use for all dispatch tables.',
201bf215546Sopenharmony_ci                        action='append', default=[], dest='prefixes')
202bf215546Sopenharmony_ci    parser.add_argument('--device-prefix',
203bf215546Sopenharmony_ci                        help='Prefix to use for device dispatch tables.',
204bf215546Sopenharmony_ci                        action='append', default=[], dest='device_prefixes')
205bf215546Sopenharmony_ci    args = parser.parse_args()
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci    instance_prefixes = args.prefixes
208bf215546Sopenharmony_ci    physical_device_prefixes = args.prefixes
209bf215546Sopenharmony_ci    device_prefixes = args.prefixes + args.device_prefixes
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci    entrypoints = get_entrypoints_from_xml(args.xml_files)
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci    device_entrypoints = []
214bf215546Sopenharmony_ci    physical_device_entrypoints = []
215bf215546Sopenharmony_ci    instance_entrypoints = []
216bf215546Sopenharmony_ci    for e in entrypoints:
217bf215546Sopenharmony_ci        if e.is_device_entrypoint():
218bf215546Sopenharmony_ci            device_entrypoints.append(e)
219bf215546Sopenharmony_ci        elif e.is_physical_device_entrypoint():
220bf215546Sopenharmony_ci            physical_device_entrypoints.append(e)
221bf215546Sopenharmony_ci        else:
222bf215546Sopenharmony_ci            instance_entrypoints.append(e)
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci    assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h)
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci    environment = {
227bf215546Sopenharmony_ci        'gen_proto': args.gen_proto,
228bf215546Sopenharmony_ci        'gen_weak': args.gen_weak,
229bf215546Sopenharmony_ci        'header': os.path.basename(args.out_h),
230bf215546Sopenharmony_ci        'instance_entrypoints': instance_entrypoints,
231bf215546Sopenharmony_ci        'instance_prefixes': instance_prefixes,
232bf215546Sopenharmony_ci        'physical_device_entrypoints': physical_device_entrypoints,
233bf215546Sopenharmony_ci        'physical_device_prefixes': physical_device_prefixes,
234bf215546Sopenharmony_ci        'device_entrypoints': device_entrypoints,
235bf215546Sopenharmony_ci        'device_prefixes': device_prefixes,
236bf215546Sopenharmony_ci        'filename': os.path.basename(__file__),
237bf215546Sopenharmony_ci    }
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci    # For outputting entrypoints.h we generate a anv_EntryPoint() prototype
240bf215546Sopenharmony_ci    # per entry point.
241bf215546Sopenharmony_ci    try:
242bf215546Sopenharmony_ci        with open(args.out_h, 'w', encoding='utf-8') as f:
243bf215546Sopenharmony_ci            guard = os.path.basename(args.out_h).replace('.', '_').upper()
244bf215546Sopenharmony_ci            f.write(TEMPLATE_H.render(guard=guard, **environment))
245bf215546Sopenharmony_ci        with open(args.out_c, 'w', encoding='utf-8') as f:
246bf215546Sopenharmony_ci            f.write(TEMPLATE_C.render(**environment))
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci    except Exception:
249bf215546Sopenharmony_ci        # In the event there's an error, this imports some helpers from mako
250bf215546Sopenharmony_ci        # to print a useful stack trace and prints it, then exits with
251bf215546Sopenharmony_ci        # status 1, if python is run with debug; otherwise it just raises
252bf215546Sopenharmony_ci        # the exception
253bf215546Sopenharmony_ci        import sys
254bf215546Sopenharmony_ci        from mako import exceptions
255bf215546Sopenharmony_ci        print(exceptions.text_error_template().render(), file=sys.stderr)
256bf215546Sopenharmony_ci        sys.exit(1)
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ciif __name__ == '__main__':
259bf215546Sopenharmony_ci    main()
260