anv: More carefully dirty state in BindPipeline
[mesa.git] / src / intel / vulkan / anv_entrypoints_gen.py
1 # coding=utf-8
2 #
3 # Copyright © 2015, 2017 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 import argparse
26 import math
27 import os
28 import xml.etree.cElementTree as et
29
30 from collections import OrderedDict, namedtuple
31 from mako.template import Template
32
33 from anv_extensions import VkVersion, MAX_API_VERSION, EXTENSIONS
34
35 # We generate a static hash table for entry point lookup
36 # (vkGetProcAddress). We use a linear congruential generator for our hash
37 # function and a power-of-two size table. The prime numbers are determined
38 # experimentally.
39
40 LAYERS = [
41 'anv',
42 'gen7',
43 'gen75',
44 'gen8',
45 'gen9',
46 'gen10',
47 'gen11',
48 'gen12',
49 ]
50
51 TEMPLATE_H = Template("""\
52 /* This file generated from ${filename}, don't edit directly. */
53
54 struct anv_instance_dispatch_table {
55 union {
56 void *entrypoints[${len(instance_entrypoints)}];
57 struct {
58 % for e in instance_entrypoints:
59 % if e.guard is not None:
60 #ifdef ${e.guard}
61 PFN_${e.name} ${e.name};
62 #else
63 void *${e.name};
64 # endif
65 % else:
66 PFN_${e.name} ${e.name};
67 % endif
68 % endfor
69 };
70 };
71 };
72
73 struct anv_physical_device_dispatch_table {
74 union {
75 void *entrypoints[${len(physical_device_entrypoints)}];
76 struct {
77 % for e in physical_device_entrypoints:
78 % if e.guard is not None:
79 #ifdef ${e.guard}
80 PFN_${e.name} ${e.name};
81 #else
82 void *${e.name};
83 # endif
84 % else:
85 PFN_${e.name} ${e.name};
86 % endif
87 % endfor
88 };
89 };
90 };
91
92 struct anv_device_dispatch_table {
93 union {
94 void *entrypoints[${len(device_entrypoints)}];
95 struct {
96 % for e in device_entrypoints:
97 % if e.guard is not None:
98 #ifdef ${e.guard}
99 PFN_${e.name} ${e.name};
100 #else
101 void *${e.name};
102 # endif
103 % else:
104 PFN_${e.name} ${e.name};
105 % endif
106 % endfor
107 };
108 };
109 };
110
111 extern const struct anv_instance_dispatch_table anv_instance_dispatch_table;
112 %for layer in LAYERS:
113 extern const struct anv_physical_device_dispatch_table ${layer}_physical_device_dispatch_table;
114 %endfor
115 %for layer in LAYERS:
116 extern const struct anv_device_dispatch_table ${layer}_device_dispatch_table;
117 %endfor
118
119 % for e in instance_entrypoints:
120 % if e.alias:
121 <% continue %>
122 % endif
123 % if e.guard is not None:
124 #ifdef ${e.guard}
125 % endif
126 ${e.return_type} ${e.prefixed_name('anv')}(${e.decl_params()});
127 % if e.guard is not None:
128 #endif // ${e.guard}
129 % endif
130 % endfor
131
132 % for e in physical_device_entrypoints:
133 % if e.alias:
134 <% continue %>
135 % endif
136 % if e.guard is not None:
137 #ifdef ${e.guard}
138 % endif
139 % for layer in LAYERS:
140 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()});
141 % endfor
142 % if e.guard is not None:
143 #endif // ${e.guard}
144 % endif
145 % endfor
146
147 % for e in device_entrypoints:
148 % if e.alias:
149 <% continue %>
150 % endif
151 % if e.guard is not None:
152 #ifdef ${e.guard}
153 % endif
154 % for layer in LAYERS:
155 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()});
156 % endfor
157 % if e.guard is not None:
158 #endif // ${e.guard}
159 % endif
160 % endfor
161 """, output_encoding='utf-8')
162
163 TEMPLATE_C = Template(u"""\
164 /*
165 * Copyright © 2015 Intel Corporation
166 *
167 * Permission is hereby granted, free of charge, to any person obtaining a
168 * copy of this software and associated documentation files (the "Software"),
169 * to deal in the Software without restriction, including without limitation
170 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
171 * and/or sell copies of the Software, and to permit persons to whom the
172 * Software is furnished to do so, subject to the following conditions:
173 *
174 * The above copyright notice and this permission notice (including the next
175 * paragraph) shall be included in all copies or substantial portions of the
176 * Software.
177 *
178 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
179 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
180 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
181 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
182 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
183 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
184 * IN THE SOFTWARE.
185 */
186
187 /* This file generated from ${filename}, don't edit directly. */
188
189 #include "anv_private.h"
190
191 #include "util/macros.h"
192
193 struct string_map_entry {
194 uint32_t name;
195 uint32_t hash;
196 uint32_t num;
197 };
198
199 /* We use a big string constant to avoid lots of reloctions from the entry
200 * point table to lots of little strings. The entries in the entry point table
201 * store the index into this big string.
202 */
203
204 <%def name="strmap(strmap, prefix)">
205 static const char ${prefix}_strings[] =
206 % for s in strmap.sorted_strings:
207 "${s.string}\\0"
208 % endfor
209 ;
210
211 static const struct string_map_entry ${prefix}_string_map_entries[] = {
212 % for s in strmap.sorted_strings:
213 { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */
214 % endfor
215 };
216
217 /* Hash table stats:
218 * size ${len(strmap.sorted_strings)} entries
219 * collisions entries:
220 % for i in range(10):
221 * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]}
222 % endfor
223 */
224
225 #define none 0xffff
226 static const uint16_t ${prefix}_string_map[${strmap.hash_size}] = {
227 % for e in strmap.mapping:
228 ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' },
229 % endfor
230 };
231
232 static int
233 ${prefix}_string_map_lookup(const char *str)
234 {
235 static const uint32_t prime_factor = ${strmap.prime_factor};
236 static const uint32_t prime_step = ${strmap.prime_step};
237 const struct string_map_entry *e;
238 uint32_t hash, h;
239 uint16_t i;
240 const char *p;
241
242 hash = 0;
243 for (p = str; *p; p++)
244 hash = hash * prime_factor + *p;
245
246 h = hash;
247 while (1) {
248 i = ${prefix}_string_map[h & ${strmap.hash_mask}];
249 if (i == none)
250 return -1;
251 e = &${prefix}_string_map_entries[i];
252 if (e->hash == hash && strcmp(str, ${prefix}_strings + e->name) == 0)
253 return e->num;
254 h += prime_step;
255 }
256
257 return -1;
258 }
259
260 static const char *
261 ${prefix}_entry_name(int num)
262 {
263 for (int i = 0; i < ARRAY_SIZE(${prefix}_string_map_entries); i++) {
264 if (${prefix}_string_map_entries[i].num == num)
265 return &${prefix}_strings[${prefix}_string_map_entries[i].name];
266 }
267 return NULL;
268 }
269 </%def>
270
271 ${strmap(instance_strmap, 'instance')}
272 ${strmap(physical_device_strmap, 'physical_device')}
273 ${strmap(device_strmap, 'device')}
274
275 /* Weak aliases for all potential implementations. These will resolve to
276 * NULL if they're not defined, which lets the resolve_entrypoint() function
277 * either pick the correct entry point.
278 */
279
280 % for e in instance_entrypoints:
281 % if e.alias:
282 <% continue %>
283 % endif
284 % if e.guard is not None:
285 #ifdef ${e.guard}
286 % endif
287 ${e.return_type} ${e.prefixed_name('anv')}(${e.decl_params()}) __attribute__ ((weak));
288 % if e.guard is not None:
289 #endif // ${e.guard}
290 % endif
291 % endfor
292
293 const struct anv_instance_dispatch_table anv_instance_dispatch_table = {
294 % for e in instance_entrypoints:
295 % if e.guard is not None:
296 #ifdef ${e.guard}
297 % endif
298 .${e.name} = ${e.prefixed_name('anv')},
299 % if e.guard is not None:
300 #endif // ${e.guard}
301 % endif
302 % endfor
303 };
304
305 % for layer in LAYERS:
306 % for e in physical_device_entrypoints:
307 % if e.alias:
308 <% continue %>
309 % endif
310 % if e.guard is not None:
311 #ifdef ${e.guard}
312 % endif
313 % if layer == 'anv':
314 ${e.return_type} __attribute__ ((weak))
315 ${e.prefixed_name('anv')}(${e.decl_params()})
316 {
317 % if e.params[0].type == 'VkPhysicalDevice':
318 ANV_FROM_HANDLE(anv_physical_device, anv_physical_device, ${e.params[0].name});
319 return anv_physical_device->dispatch.${e.name}(${e.call_params()});
320 % else:
321 assert(!"Unhandled device child trampoline case: ${e.params[0].type}");
322 % endif
323 }
324 % else:
325 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak));
326 % endif
327 % if e.guard is not None:
328 #endif // ${e.guard}
329 % endif
330 % endfor
331
332 const struct anv_physical_device_dispatch_table ${layer}_physical_device_dispatch_table = {
333 % for e in physical_device_entrypoints:
334 % if e.guard is not None:
335 #ifdef ${e.guard}
336 % endif
337 .${e.name} = ${e.prefixed_name(layer)},
338 % if e.guard is not None:
339 #endif // ${e.guard}
340 % endif
341 % endfor
342 };
343 % endfor
344
345
346 % for layer in LAYERS:
347 % for e in device_entrypoints:
348 % if e.alias:
349 <% continue %>
350 % endif
351 % if e.guard is not None:
352 #ifdef ${e.guard}
353 % endif
354 % if layer == 'anv':
355 ${e.return_type} __attribute__ ((weak))
356 ${e.prefixed_name('anv')}(${e.decl_params()})
357 {
358 % if e.params[0].type == 'VkDevice':
359 ANV_FROM_HANDLE(anv_device, anv_device, ${e.params[0].name});
360 return anv_device->dispatch.${e.name}(${e.call_params()});
361 % elif e.params[0].type == 'VkCommandBuffer':
362 ANV_FROM_HANDLE(anv_cmd_buffer, anv_cmd_buffer, ${e.params[0].name});
363 return anv_cmd_buffer->device->dispatch.${e.name}(${e.call_params()});
364 % elif e.params[0].type == 'VkQueue':
365 ANV_FROM_HANDLE(anv_queue, anv_queue, ${e.params[0].name});
366 return anv_queue->device->dispatch.${e.name}(${e.call_params()});
367 % else:
368 assert(!"Unhandled device child trampoline case: ${e.params[0].type}");
369 % endif
370 }
371 % else:
372 ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak));
373 % endif
374 % if e.guard is not None:
375 #endif // ${e.guard}
376 % endif
377 % endfor
378
379 const struct anv_device_dispatch_table ${layer}_device_dispatch_table = {
380 % for e in device_entrypoints:
381 % if e.guard is not None:
382 #ifdef ${e.guard}
383 % endif
384 .${e.name} = ${e.prefixed_name(layer)},
385 % if e.guard is not None:
386 #endif // ${e.guard}
387 % endif
388 % endfor
389 };
390 % endfor
391
392
393 /** Return true if the core version or extension in which the given entrypoint
394 * is defined is enabled.
395 *
396 * If device is NULL, all device extensions are considered enabled.
397 */
398 bool
399 anv_instance_entrypoint_is_enabled(int index, uint32_t core_version,
400 const struct anv_instance_extension_table *instance)
401 {
402 switch (index) {
403 % for e in instance_entrypoints:
404 case ${e.num}:
405 /* ${e.name} */
406 % if e.core_version:
407 return ${e.core_version.c_vk_version()} <= core_version;
408 % elif e.extensions:
409 % for ext in e.extensions:
410 % if ext.type == 'instance':
411 if (instance->${ext.name[3:]}) return true;
412 % else:
413 /* All device extensions are considered enabled at the instance level */
414 return true;
415 % endif
416 % endfor
417 return false;
418 % else:
419 return true;
420 % endif
421 % endfor
422 default:
423 return false;
424 }
425 }
426
427 /** Return true if the core version or extension in which the given entrypoint
428 * is defined is enabled.
429 *
430 * If device is NULL, all device extensions are considered enabled.
431 */
432 bool
433 anv_physical_device_entrypoint_is_enabled(int index, uint32_t core_version,
434 const struct anv_instance_extension_table *instance)
435 {
436 switch (index) {
437 % for e in physical_device_entrypoints:
438 case ${e.num}:
439 /* ${e.name} */
440 % if e.core_version:
441 return ${e.core_version.c_vk_version()} <= core_version;
442 % elif e.extensions:
443 % for ext in e.extensions:
444 % if ext.type == 'instance':
445 if (instance->${ext.name[3:]}) return true;
446 % else:
447 /* All device extensions are considered enabled at the instance level */
448 return true;
449 % endif
450 % endfor
451 return false;
452 % else:
453 return true;
454 % endif
455 % endfor
456 default:
457 return false;
458 }
459 }
460
461 /** Return true if the core version or extension in which the given entrypoint
462 * is defined is enabled.
463 *
464 * If device is NULL, all device extensions are considered enabled.
465 */
466 bool
467 anv_device_entrypoint_is_enabled(int index, uint32_t core_version,
468 const struct anv_instance_extension_table *instance,
469 const struct anv_device_extension_table *device)
470 {
471 switch (index) {
472 % for e in device_entrypoints:
473 case ${e.num}:
474 /* ${e.name} */
475 % if e.core_version:
476 return ${e.core_version.c_vk_version()} <= core_version;
477 % elif e.extensions:
478 % for ext in e.extensions:
479 % if ext.type == 'instance':
480 <% assert False %>
481 % else:
482 if (!device || device->${ext.name[3:]}) return true;
483 % endif
484 % endfor
485 return false;
486 % else:
487 return true;
488 % endif
489 % endfor
490 default:
491 return false;
492 }
493 }
494
495 int
496 anv_get_instance_entrypoint_index(const char *name)
497 {
498 return instance_string_map_lookup(name);
499 }
500
501 int
502 anv_get_physical_device_entrypoint_index(const char *name)
503 {
504 return physical_device_string_map_lookup(name);
505 }
506
507 int
508 anv_get_device_entrypoint_index(const char *name)
509 {
510 return device_string_map_lookup(name);
511 }
512
513 const char *
514 anv_get_instance_entry_name(int index)
515 {
516 return instance_entry_name(index);
517 }
518
519 const char *
520 anv_get_physical_device_entry_name(int index)
521 {
522 return physical_device_entry_name(index);
523 }
524
525 const char *
526 anv_get_device_entry_name(int index)
527 {
528 return device_entry_name(index);
529 }
530
531 static void * __attribute__ ((noinline))
532 anv_resolve_device_entrypoint(const struct gen_device_info *devinfo, uint32_t index)
533 {
534 const struct anv_device_dispatch_table *genX_table;
535 switch (devinfo->gen) {
536 case 12:
537 genX_table = &gen12_device_dispatch_table;
538 break;
539 case 11:
540 genX_table = &gen11_device_dispatch_table;
541 break;
542 case 10:
543 genX_table = &gen10_device_dispatch_table;
544 break;
545 case 9:
546 genX_table = &gen9_device_dispatch_table;
547 break;
548 case 8:
549 genX_table = &gen8_device_dispatch_table;
550 break;
551 case 7:
552 if (devinfo->is_haswell)
553 genX_table = &gen75_device_dispatch_table;
554 else
555 genX_table = &gen7_device_dispatch_table;
556 break;
557 default:
558 unreachable("unsupported gen\\n");
559 }
560
561 if (genX_table->entrypoints[index])
562 return genX_table->entrypoints[index];
563 else
564 return anv_device_dispatch_table.entrypoints[index];
565 }
566
567 void *
568 anv_lookup_entrypoint(const struct gen_device_info *devinfo, const char *name)
569 {
570 int idx = anv_get_instance_entrypoint_index(name);
571 if (idx >= 0)
572 return anv_instance_dispatch_table.entrypoints[idx];
573
574 idx = anv_get_physical_device_entrypoint_index(name);
575 if (idx >= 0)
576 return anv_physical_device_dispatch_table.entrypoints[idx];
577
578 idx = anv_get_device_entrypoint_index(name);
579 if (idx >= 0)
580 return anv_resolve_device_entrypoint(devinfo, idx);
581
582 return NULL;
583 }""", output_encoding='utf-8')
584
585 U32_MASK = 2**32 - 1
586
587 PRIME_FACTOR = 5024183
588 PRIME_STEP = 19
589
590 class StringIntMapEntry(object):
591 def __init__(self, string, num):
592 self.string = string
593 self.num = num
594
595 # Calculate the same hash value that we will calculate in C.
596 h = 0
597 for c in string:
598 h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK
599 self.hash = h
600
601 self.offset = None
602
603 def round_to_pow2(x):
604 return 2**int(math.ceil(math.log(x, 2)))
605
606 class StringIntMap(object):
607 def __init__(self):
608 self.baked = False
609 self.strings = dict()
610
611 def add_string(self, string, num):
612 assert not self.baked
613 assert string not in self.strings
614 assert 0 <= num < 2**31
615 self.strings[string] = StringIntMapEntry(string, num)
616
617 def bake(self):
618 self.sorted_strings = \
619 sorted(self.strings.values(), key=lambda x: x.string)
620 offset = 0
621 for entry in self.sorted_strings:
622 entry.offset = offset
623 offset += len(entry.string) + 1
624
625 # Save off some values that we'll need in C
626 self.hash_size = round_to_pow2(len(self.strings) * 1.25)
627 self.hash_mask = self.hash_size - 1
628 self.prime_factor = PRIME_FACTOR
629 self.prime_step = PRIME_STEP
630
631 self.mapping = [-1] * self.hash_size
632 self.collisions = [0] * 10
633 for idx, s in enumerate(self.sorted_strings):
634 level = 0
635 h = s.hash
636 while self.mapping[h & self.hash_mask] >= 0:
637 h = h + PRIME_STEP
638 level = level + 1
639 self.collisions[min(level, 9)] += 1
640 self.mapping[h & self.hash_mask] = idx
641
642 EntrypointParam = namedtuple('EntrypointParam', 'type name decl')
643
644 class EntrypointBase(object):
645 def __init__(self, name):
646 self.name = name
647 self.alias = None
648 self.guard = None
649 self.enabled = False
650 self.num = None
651 # Extensions which require this entrypoint
652 self.core_version = None
653 self.extensions = []
654
655 class Entrypoint(EntrypointBase):
656 def __init__(self, name, return_type, params, guard=None):
657 super(Entrypoint, self).__init__(name)
658 self.return_type = return_type
659 self.params = params
660 self.guard = guard
661
662 def is_physical_device_entrypoint(self):
663 return self.params[0].type in ('VkPhysicalDevice', )
664
665 def is_device_entrypoint(self):
666 return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue')
667
668 def prefixed_name(self, prefix):
669 assert self.name.startswith('vk')
670 return prefix + '_' + self.name[2:]
671
672 def decl_params(self):
673 return ', '.join(p.decl for p in self.params)
674
675 def call_params(self):
676 return ', '.join(p.name for p in self.params)
677
678 class EntrypointAlias(EntrypointBase):
679 def __init__(self, name, entrypoint):
680 super(EntrypointAlias, self).__init__(name)
681 self.alias = entrypoint
682
683 def is_physical_device_entrypoint(self):
684 return self.alias.is_physical_device_entrypoint()
685
686 def is_device_entrypoint(self):
687 return self.alias.is_device_entrypoint()
688
689 def prefixed_name(self, prefix):
690 return self.alias.prefixed_name(prefix)
691
692 def get_entrypoints(doc, entrypoints_to_defines):
693 """Extract the entry points from the registry."""
694 entrypoints = OrderedDict()
695
696 for command in doc.findall('./commands/command'):
697 if 'alias' in command.attrib:
698 alias = command.attrib['name']
699 target = command.attrib['alias']
700 entrypoints[alias] = EntrypointAlias(alias, entrypoints[target])
701 else:
702 name = command.find('./proto/name').text
703 ret_type = command.find('./proto/type').text
704 params = [EntrypointParam(
705 type=p.find('./type').text,
706 name=p.find('./name').text,
707 decl=''.join(p.itertext())
708 ) for p in command.findall('./param')]
709 guard = entrypoints_to_defines.get(name)
710 # They really need to be unique
711 assert name not in entrypoints
712 entrypoints[name] = Entrypoint(name, ret_type, params, guard)
713
714 for feature in doc.findall('./feature'):
715 assert feature.attrib['api'] == 'vulkan'
716 version = VkVersion(feature.attrib['number'])
717 if version > MAX_API_VERSION:
718 continue
719
720 for command in feature.findall('./require/command'):
721 e = entrypoints[command.attrib['name']]
722 e.enabled = True
723 assert e.core_version is None
724 e.core_version = version
725
726 supported_exts = dict((ext.name, ext) for ext in EXTENSIONS)
727 for extension in doc.findall('.extensions/extension'):
728 ext_name = extension.attrib['name']
729 if ext_name not in supported_exts:
730 continue
731
732 ext = supported_exts[ext_name]
733 ext.type = extension.attrib['type']
734
735 for command in extension.findall('./require/command'):
736 e = entrypoints[command.attrib['name']]
737 e.enabled = True
738 assert e.core_version is None
739 e.extensions.append(ext)
740
741 return [e for e in entrypoints.values() if e.enabled]
742
743
744 def get_entrypoints_defines(doc):
745 """Maps entry points to extension defines."""
746 entrypoints_to_defines = {}
747
748 platform_define = {}
749 for platform in doc.findall('./platforms/platform'):
750 name = platform.attrib['name']
751 define = platform.attrib['protect']
752 platform_define[name] = define
753
754 for extension in doc.findall('./extensions/extension[@platform]'):
755 platform = extension.attrib['platform']
756 define = platform_define[platform]
757
758 for entrypoint in extension.findall('./require/command'):
759 fullname = entrypoint.attrib['name']
760 entrypoints_to_defines[fullname] = define
761
762 return entrypoints_to_defines
763
764
765 def main():
766 parser = argparse.ArgumentParser()
767 parser.add_argument('--outdir', help='Where to write the files.',
768 required=True)
769 parser.add_argument('--xml',
770 help='Vulkan API XML file.',
771 required=True,
772 action='append',
773 dest='xml_files')
774 args = parser.parse_args()
775
776 entrypoints = []
777
778 for filename in args.xml_files:
779 doc = et.parse(filename)
780 entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc))
781
782 # Manually add CreateDmaBufImageINTEL for which we don't have an extension
783 # defined.
784 entrypoints.append(Entrypoint('vkCreateDmaBufImageINTEL', 'VkResult', [
785 EntrypointParam('VkDevice', 'device', 'VkDevice device'),
786 EntrypointParam('VkDmaBufImageCreateInfo', 'pCreateInfo',
787 'const VkDmaBufImageCreateInfo* pCreateInfo'),
788 EntrypointParam('VkAllocationCallbacks', 'pAllocator',
789 'const VkAllocationCallbacks* pAllocator'),
790 EntrypointParam('VkDeviceMemory', 'pMem', 'VkDeviceMemory* pMem'),
791 EntrypointParam('VkImage', 'pImage', 'VkImage* pImage')
792 ]))
793
794 device_entrypoints = []
795 physical_device_entrypoints = []
796 instance_entrypoints = []
797 for e in entrypoints:
798 if e.is_device_entrypoint():
799 device_entrypoints.append(e)
800 elif e.is_physical_device_entrypoint():
801 physical_device_entrypoints.append(e)
802 else:
803 instance_entrypoints.append(e)
804
805 device_strmap = StringIntMap()
806 for num, e in enumerate(device_entrypoints):
807 device_strmap.add_string(e.name, num)
808 e.num = num
809 device_strmap.bake()
810
811 physical_device_strmap = StringIntMap()
812 for num, e in enumerate(physical_device_entrypoints):
813 physical_device_strmap.add_string(e.name, num)
814 e.num = num
815 physical_device_strmap.bake()
816
817 instance_strmap = StringIntMap()
818 for num, e in enumerate(instance_entrypoints):
819 instance_strmap.add_string(e.name, num)
820 e.num = num
821 instance_strmap.bake()
822
823 # For outputting entrypoints.h we generate a anv_EntryPoint() prototype
824 # per entry point.
825 try:
826 with open(os.path.join(args.outdir, 'anv_entrypoints.h'), 'wb') as f:
827 f.write(TEMPLATE_H.render(instance_entrypoints=instance_entrypoints,
828 physical_device_entrypoints=physical_device_entrypoints,
829 device_entrypoints=device_entrypoints,
830 LAYERS=LAYERS,
831 filename=os.path.basename(__file__)))
832 with open(os.path.join(args.outdir, 'anv_entrypoints.c'), 'wb') as f:
833 f.write(TEMPLATE_C.render(instance_entrypoints=instance_entrypoints,
834 physical_device_entrypoints=physical_device_entrypoints,
835 device_entrypoints=device_entrypoints,
836 LAYERS=LAYERS,
837 instance_strmap=instance_strmap,
838 physical_device_strmap=physical_device_strmap,
839 device_strmap=device_strmap,
840 filename=os.path.basename(__file__)))
841 except Exception:
842 # In the event there's an error, this imports some helpers from mako
843 # to print a useful stack trace and prints it, then exits with
844 # status 1, if python is run with debug; otherwise it just raises
845 # the exception
846 if __debug__:
847 import sys
848 from mako import exceptions
849 sys.stderr.write(exceptions.text_error_template().render() + '\n')
850 sys.exit(1)
851 raise
852
853
854 if __name__ == '__main__':
855 main()