"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/amd/vulkan/radv_entrypoints_gen.py" (16 Sep 2020, 24492 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "radv_entrypoints_gen.py" see the Fossies "Dox" file reference documentation.

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