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