X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fintel%2Fvulkan%2Fanv_entrypoints_gen.py;h=ff166186a0b6a9369a88b5bf6d7173af3d6f7f72;hb=e94c22429b64f419d9a66f04fa5ecdad33f7f5ef;hp=d603ac1b20bf35128899e6dfe2af0a56689be8a1;hpb=1a0aba7216e54e117df744c252f152ff3eab6441;p=mesa.git diff --git a/src/intel/vulkan/anv_entrypoints_gen.py b/src/intel/vulkan/anv_entrypoints_gen.py index d603ac1b20b..ff166186a0b 100644 --- a/src/intel/vulkan/anv_entrypoints_gen.py +++ b/src/intel/vulkan/anv_entrypoints_gen.py @@ -23,15 +23,14 @@ # import argparse -import functools import math import os -import xml.etree.cElementTree as et +import xml.etree.ElementTree as et from collections import OrderedDict, namedtuple from mako.template import Template -from anv_extensions import * +from anv_extensions import VkVersion, MAX_API_VERSION, EXTENSIONS # We generate a static hash table for entry point lookup # (vkGetProcAddress). We use a linear congruential generator for our hash @@ -46,16 +45,17 @@ LAYERS = [ 'gen9', 'gen10', 'gen11', + 'gen12', ] TEMPLATE_H = Template("""\ /* This file generated from ${filename}, don't edit directly. */ -struct anv_dispatch_table { +struct anv_instance_dispatch_table { union { - void *entrypoints[${len(entrypoints)}]; + void *entrypoints[${len(instance_entrypoints)}]; struct { - % for e in entrypoints: + % for e in instance_entrypoints: % if e.guard is not None: #ifdef ${e.guard} PFN_${e.name} ${e.name}; @@ -70,12 +70,66 @@ struct anv_dispatch_table { }; }; +struct anv_physical_device_dispatch_table { + union { + void *entrypoints[${len(physical_device_entrypoints)}]; + struct { + % for e in physical_device_entrypoints: + % if e.guard is not None: +#ifdef ${e.guard} + PFN_${e.name} ${e.name}; +#else + void *${e.name}; +# endif + % else: + PFN_${e.name} ${e.name}; + % endif + % endfor + }; + }; +}; + +struct anv_device_dispatch_table { + union { + void *entrypoints[${len(device_entrypoints)}]; + struct { + % for e in device_entrypoints: + % if e.guard is not None: +#ifdef ${e.guard} + PFN_${e.name} ${e.name}; +#else + void *${e.name}; +# endif + % else: + PFN_${e.name} ${e.name}; + % endif + % endfor + }; + }; +}; + +extern const struct anv_instance_dispatch_table anv_instance_dispatch_table; +%for layer in LAYERS: +extern const struct anv_physical_device_dispatch_table ${layer}_physical_device_dispatch_table; +%endfor %for layer in LAYERS: -extern const struct anv_dispatch_table ${layer}_dispatch_table; +extern const struct anv_device_dispatch_table ${layer}_device_dispatch_table; %endfor -extern const struct anv_dispatch_table anv_tramp_dispatch_table; -% for e in entrypoints: +% for e in instance_entrypoints: + % if e.alias and e.alias.enabled: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif + ${e.return_type} ${e.prefixed_name('anv')}(${e.decl_params()}); + % if e.guard is not None: +#endif // ${e.guard} + % endif +% endfor + +% for e in physical_device_entrypoints: % if e.alias: <% continue %> % endif @@ -89,6 +143,21 @@ extern const struct anv_dispatch_table anv_tramp_dispatch_table; #endif // ${e.guard} % endif % endfor + +% for e in device_entrypoints: + % if e.alias and e.alias.enabled: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif + % for layer in LAYERS: + ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}); + % endfor + % if e.guard is not None: +#endif // ${e.guard} + % endif +% endfor """, output_encoding='utf-8') TEMPLATE_C = Template(u"""\ @@ -119,6 +188,8 @@ TEMPLATE_C = Template(u"""\ #include "anv_private.h" +#include "util/macros.h" + struct string_map_entry { uint32_t name; uint32_t hash; @@ -130,13 +201,14 @@ struct string_map_entry { * store the index into this big string. */ -static const char strings[] = +<%def name="strmap(strmap, prefix)"> +static const char ${prefix}_strings[] = % for s in strmap.sorted_strings: "${s.string}\\0" % endfor ; -static const struct string_map_entry string_map_entries[] = { +static const struct string_map_entry ${prefix}_string_map_entries[] = { % for s in strmap.sorted_strings: { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */ % endfor @@ -145,20 +217,20 @@ static const struct string_map_entry string_map_entries[] = { /* Hash table stats: * size ${len(strmap.sorted_strings)} entries * collisions entries: -% for i in xrange(10): +% for i in range(10): * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]} % endfor */ #define none 0xffff -static const uint16_t string_map[${strmap.hash_size}] = { +static const uint16_t ${prefix}_string_map[${strmap.hash_size}] = { % for e in strmap.mapping: ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' }, % endfor }; static int -string_map_lookup(const char *str) +${prefix}_string_map_lookup(const char *str) { static const uint32_t prime_factor = ${strmap.prime_factor}; static const uint32_t prime_step = ${strmap.prime_step}; @@ -173,11 +245,11 @@ string_map_lookup(const char *str) h = hash; while (1) { - i = string_map[h & ${strmap.hash_mask}]; + i = ${prefix}_string_map[h & ${strmap.hash_mask}]; if (i == none) return -1; - e = &string_map_entries[i]; - if (e->hash == hash && strcmp(str, strings + e->name) == 0) + e = &${prefix}_string_map_entries[i]; + if (e->hash == hash && strcmp(str, ${prefix}_strings + e->name) == 0) return e->num; h += prime_step; } @@ -185,78 +257,70 @@ string_map_lookup(const char *str) return -1; } +static const char * +${prefix}_entry_name(int num) +{ + for (int i = 0; i < ARRAY_SIZE(${prefix}_string_map_entries); i++) { + if (${prefix}_string_map_entries[i].num == num) + return &${prefix}_strings[${prefix}_string_map_entries[i].name]; + } + return NULL; +} + + +${strmap(instance_strmap, 'instance')} +${strmap(physical_device_strmap, 'physical_device')} +${strmap(device_strmap, 'device')} + /* Weak aliases for all potential implementations. These will resolve to * NULL if they're not defined, which lets the resolve_entrypoint() function * either pick the correct entry point. */ -% for layer in LAYERS: - % for e in entrypoints: - % if e.alias: - <% continue %> - % endif - % if e.guard is not None: +% for e in instance_entrypoints: + % if e.alias and e.alias.enabled: + <% continue %> + % endif + % if e.guard is not None: #ifdef ${e.guard} - % endif - ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak)); - % if e.guard is not None: + % endif + ${e.return_type} ${e.prefixed_name('anv')}(${e.decl_params()}) __attribute__ ((weak)); + % if e.guard is not None: #endif // ${e.guard} - % endif - % endfor + % endif +% endfor - const struct anv_dispatch_table ${layer}_dispatch_table = { - % for e in entrypoints: - % if e.guard is not None: +const struct anv_instance_dispatch_table anv_instance_dispatch_table = { +% for e in instance_entrypoints: + % if e.guard is not None: #ifdef ${e.guard} - % endif - .${e.name} = ${e.prefixed_name(layer)}, - % if e.guard is not None: + % endif + .${e.name} = ${e.prefixed_name('anv')}, + % if e.guard is not None: #endif // ${e.guard} - % endif - % endfor - }; + % endif % endfor +}; - -/** Trampoline entrypoints for all device functions */ - -% for e in entrypoints: - % if e.alias or not e.is_device_entrypoint(): +% for e in physical_device_entrypoints: + % if e.alias and e.alias.enabled: <% continue %> % endif % if e.guard is not None: #ifdef ${e.guard} % endif - static ${e.return_type} - ${e.prefixed_name('anv_tramp')}(${e.decl_params()}) - { - % if e.params[0].type == 'VkDevice': - ANV_FROM_HANDLE(anv_device, anv_device, ${e.params[0].name}); - return anv_device->dispatch.${e.name}(${e.call_params()}); - % elif e.params[0].type == 'VkCommandBuffer': - ANV_FROM_HANDLE(anv_cmd_buffer, anv_cmd_buffer, ${e.params[0].name}); - return anv_cmd_buffer->device->dispatch.${e.name}(${e.call_params()}); - % elif e.params[0].type == 'VkQueue': - ANV_FROM_HANDLE(anv_queue, anv_queue, ${e.params[0].name}); - return anv_queue->device->dispatch.${e.name}(${e.call_params()}); - % else: - assert(!"Unhandled device child trampoline case: ${e.params[0].type}"); - % endif - } + ${e.return_type} ${e.prefixed_name('anv')}(${e.decl_params()}) __attribute__ ((weak)); % if e.guard is not None: #endif // ${e.guard} % endif % endfor -const struct anv_dispatch_table anv_tramp_dispatch_table = { -% for e in entrypoints: - % if not e.is_device_entrypoint(): - <% continue %> - % endif +const struct anv_physical_device_dispatch_table anv_physical_device_dispatch_table = { +% for e in physical_device_entrypoints: % if e.guard is not None: #ifdef ${e.guard} % endif - .${e.name} = ${e.prefixed_name('anv_tramp')}, + .${e.name} = ${e.prefixed_name('anv')}, % if e.guard is not None: #endif // ${e.guard} % endif @@ -264,32 +328,75 @@ const struct anv_dispatch_table anv_tramp_dispatch_table = { }; +% for layer in LAYERS: + % for e in device_entrypoints: + % if e.alias and e.alias.enabled: + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif + % if layer == 'anv': + ${e.return_type} __attribute__ ((weak)) + ${e.prefixed_name('anv')}(${e.decl_params()}) + { + % if e.params[0].type == 'VkDevice': + ANV_FROM_HANDLE(anv_device, anv_device, ${e.params[0].name}); + return anv_device->dispatch.${e.name}(${e.call_params()}); + % elif e.params[0].type == 'VkCommandBuffer': + ANV_FROM_HANDLE(anv_cmd_buffer, anv_cmd_buffer, ${e.params[0].name}); + return anv_cmd_buffer->device->dispatch.${e.name}(${e.call_params()}); + % elif e.params[0].type == 'VkQueue': + ANV_FROM_HANDLE(anv_queue, anv_queue, ${e.params[0].name}); + return anv_queue->device->dispatch.${e.name}(${e.call_params()}); + % else: + assert(!"Unhandled device child trampoline case: ${e.params[0].type}"); + % endif + } + % else: + ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak)); + % endif + % if e.guard is not None: +#endif // ${e.guard} + % endif + % endfor + + const struct anv_device_dispatch_table ${layer}_device_dispatch_table = { + % for e in device_entrypoints: + % if e.guard is not None: +#ifdef ${e.guard} + % endif + .${e.name} = ${e.prefixed_name(layer)}, + % if e.guard is not None: +#endif // ${e.guard} + % endif + % endfor + }; +% endfor + + /** Return true if the core version or extension in which the given entrypoint * is defined is enabled. * * If device is NULL, all device extensions are considered enabled. */ bool -anv_entrypoint_is_enabled(int index, uint32_t core_version, - const struct anv_instance_extension_table *instance, - const struct anv_device_extension_table *device) +anv_instance_entrypoint_is_enabled(int index, uint32_t core_version, + const struct anv_instance_extension_table *instance) { switch (index) { -% for e in entrypoints: +% for e in instance_entrypoints: case ${e.num}: /* ${e.name} */ % if e.core_version: - % if e.is_device_entrypoint(): - return ${e.core_version.c_vk_version()} <= core_version; - % else: - return !device && ${e.core_version.c_vk_version()} <= core_version; - % endif + return ${e.core_version.c_vk_version()} <= core_version; % elif e.extensions: % for ext in e.extensions: - % if ext.type == 'instance': - if (!device && instance->${ext.name[3:]}) return true; + % if ext.type == 'instance': + if (instance->${ext.name[3:]}) return true; % else: - if (!device || device->${ext.name[3:]}) return true; + /* All device extensions are considered enabled at the instance level */ + return true; % endif % endfor return false; @@ -302,32 +409,135 @@ anv_entrypoint_is_enabled(int index, uint32_t core_version, } } -static void * __attribute__ ((noinline)) -anv_resolve_entrypoint(const struct gen_device_info *devinfo, uint32_t index) +/** Return true if the core version or extension in which the given entrypoint + * is defined is enabled. + * + * If device is NULL, all device extensions are considered enabled. + */ +bool +anv_physical_device_entrypoint_is_enabled(int index, uint32_t core_version, + const struct anv_instance_extension_table *instance) { - if (devinfo == NULL) { - return anv_dispatch_table.entrypoints[index]; + switch (index) { +% for e in physical_device_entrypoints: + case ${e.num}: + /* ${e.name} */ + % if e.core_version: + return ${e.core_version.c_vk_version()} <= core_version; + % elif e.extensions: + % for ext in e.extensions: + % if ext.type == 'instance': + if (instance->${ext.name[3:]}) return true; + % else: + /* All device extensions are considered enabled at the instance level */ + return true; + % endif + % endfor + return false; + % else: + return true; + % endif +% endfor + default: + return false; } +} - const struct anv_dispatch_table *genX_table; +/** Return true if the core version or extension in which the given entrypoint + * is defined is enabled. + * + * If device is NULL, all device extensions are considered enabled. + */ +bool +anv_device_entrypoint_is_enabled(int index, uint32_t core_version, + const struct anv_instance_extension_table *instance, + const struct anv_device_extension_table *device) +{ + switch (index) { +% for e in device_entrypoints: + case ${e.num}: + /* ${e.name} */ + % if e.core_version: + return ${e.core_version.c_vk_version()} <= core_version; + % elif e.extensions: + % for ext in e.extensions: + % if ext.type == 'instance': + <% assert False %> + % else: + if (!device || device->${ext.name[3:]}) return true; + % endif + % endfor + return false; + % else: + return true; + % endif +% endfor + default: + return false; + } +} + +int +anv_get_instance_entrypoint_index(const char *name) +{ + return instance_string_map_lookup(name); +} + +int +anv_get_physical_device_entrypoint_index(const char *name) +{ + return physical_device_string_map_lookup(name); +} + +int +anv_get_device_entrypoint_index(const char *name) +{ + return device_string_map_lookup(name); +} + +const char * +anv_get_instance_entry_name(int index) +{ + return instance_entry_name(index); +} + +const char * +anv_get_physical_device_entry_name(int index) +{ + return physical_device_entry_name(index); +} + +const char * +anv_get_device_entry_name(int index) +{ + return device_entry_name(index); +} + +void * __attribute__ ((noinline)) +anv_resolve_device_entrypoint(const struct gen_device_info *devinfo, uint32_t index) +{ + const struct anv_device_dispatch_table *genX_table; switch (devinfo->gen) { + case 12: + genX_table = &gen12_device_dispatch_table; + break; case 11: - genX_table = &gen11_dispatch_table; + genX_table = &gen11_device_dispatch_table; break; case 10: - genX_table = &gen10_dispatch_table; + genX_table = &gen10_device_dispatch_table; break; case 9: - genX_table = &gen9_dispatch_table; + genX_table = &gen9_device_dispatch_table; break; case 8: - genX_table = &gen8_dispatch_table; + genX_table = &gen8_device_dispatch_table; break; case 7: if (devinfo->is_haswell) - genX_table = &gen75_dispatch_table; + genX_table = &gen75_device_dispatch_table; else - genX_table = &gen7_dispatch_table; + genX_table = &gen7_device_dispatch_table; break; default: unreachable("unsupported gen\\n"); @@ -336,22 +546,25 @@ anv_resolve_entrypoint(const struct gen_device_info *devinfo, uint32_t index) if (genX_table->entrypoints[index]) return genX_table->entrypoints[index]; else - return anv_dispatch_table.entrypoints[index]; -} - -int -anv_get_entrypoint_index(const char *name) -{ - return string_map_lookup(name); + return anv_device_dispatch_table.entrypoints[index]; } void * anv_lookup_entrypoint(const struct gen_device_info *devinfo, const char *name) { - int idx = anv_get_entrypoint_index(name); - if (idx < 0) - return NULL; - return anv_resolve_entrypoint(devinfo, idx); + int idx = anv_get_instance_entrypoint_index(name); + if (idx >= 0) + return anv_instance_dispatch_table.entrypoints[idx]; + + idx = anv_get_physical_device_entrypoint_index(name); + if (idx >= 0) + return anv_physical_device_dispatch_table.entrypoints[idx]; + + idx = anv_get_device_entrypoint_index(name); + if (idx >= 0) + return anv_resolve_device_entrypoint(devinfo, idx); + + return NULL; }""", output_encoding='utf-8') U32_MASK = 2**32 - 1 @@ -383,7 +596,7 @@ class StringIntMap(object): def add_string(self, string, num): assert not self.baked assert string not in self.strings - assert num >= 0 and num < 2**31 + assert 0 <= num < 2**31 self.strings[string] = StringIntMapEntry(string, num) def bake(self): @@ -424,20 +637,23 @@ class EntrypointBase(object): self.core_version = None self.extensions = [] + def prefixed_name(self, prefix): + assert self.name.startswith('vk') + return prefix + '_' + self.name[2:] + class Entrypoint(EntrypointBase): - def __init__(self, name, return_type, params, guard = None): + def __init__(self, name, return_type, params, guard=None): super(Entrypoint, self).__init__(name) self.return_type = return_type self.params = params self.guard = guard + def is_physical_device_entrypoint(self): + return self.params[0].type in ('VkPhysicalDevice', ) + def is_device_entrypoint(self): return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue') - def prefixed_name(self, prefix): - assert self.name.startswith('vk') - return prefix + '_' + self.name[2:] - def decl_params(self): return ', '.join(p.decl for p in self.params) @@ -449,13 +665,32 @@ class EntrypointAlias(EntrypointBase): super(EntrypointAlias, self).__init__(name) self.alias = entrypoint + def is_physical_device_entrypoint(self): + return self.alias.is_physical_device_entrypoint() + def is_device_entrypoint(self): return self.alias.is_device_entrypoint() def prefixed_name(self, prefix): - return self.alias.prefixed_name(prefix) + if self.alias.enabled: + return self.alias.prefixed_name(prefix) + return super(EntrypointAlias, self).prefixed_name(prefix) + + @property + def params(self): + return self.alias.params -def get_entrypoints(doc, entrypoints_to_defines, start_index): + @property + def return_type(self): + return self.alias.return_type + + def decl_params(self): + return self.alias.decl_params() + + def call_params(self): + return self.alias.call_params() + +def get_entrypoints(doc, entrypoints_to_defines): """Extract the entry points from the registry.""" entrypoints = OrderedDict() @@ -468,9 +703,9 @@ def get_entrypoints(doc, entrypoints_to_defines, start_index): name = command.find('./proto/name').text ret_type = command.find('./proto/type').text params = [EntrypointParam( - type = p.find('./type').text, - name = p.find('./name').text, - decl = ''.join(p.itertext()) + type=p.find('./type').text, + name=p.find('./name').text, + decl=''.join(p.itertext()) ) for p in command.findall('./param')] guard = entrypoints_to_defines.get(name) # They really need to be unique @@ -495,9 +730,6 @@ def get_entrypoints(doc, entrypoints_to_defines, start_index): if ext_name not in supported_exts: continue - if extension.attrib['supported'] != 'vulkan': - continue - ext = supported_exts[ext_name] ext.type = extension.attrib['type'] @@ -507,16 +739,22 @@ def get_entrypoints(doc, entrypoints_to_defines, start_index): assert e.core_version is None e.extensions.append(ext) - return [e for e in entrypoints.itervalues() if e.enabled] + return [e for e in entrypoints.values() if e.enabled] def get_entrypoints_defines(doc): """Maps entry points to extension defines.""" entrypoints_to_defines = {} + platform_define = {} + for platform in doc.findall('./platforms/platform'): + name = platform.attrib['name'] + define = platform.attrib['protect'] + platform_define[name] = define + for extension in doc.findall('./extensions/extension[@platform]'): platform = extension.attrib['platform'] - define = 'VK_USE_PLATFORM_' + platform.upper() + '_KHR' + define = platform_define[platform] for entrypoint in extension.findall('./require/command'): fullname = entrypoint.attrib['name'] @@ -540,8 +778,7 @@ def main(): for filename in args.xml_files: doc = et.parse(filename) - entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc), - start_index=len(entrypoints)) + entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc)) # Manually add CreateDmaBufImageINTEL for which we don't have an extension # defined. @@ -555,26 +792,55 @@ def main(): EntrypointParam('VkImage', 'pImage', 'VkImage* pImage') ])) - strmap = StringIntMap() - for num, e in enumerate(entrypoints): - strmap.add_string(e.name, num) + device_entrypoints = [] + physical_device_entrypoints = [] + instance_entrypoints = [] + for e in entrypoints: + if e.is_device_entrypoint(): + device_entrypoints.append(e) + elif e.is_physical_device_entrypoint(): + physical_device_entrypoints.append(e) + else: + instance_entrypoints.append(e) + + device_strmap = StringIntMap() + for num, e in enumerate(device_entrypoints): + device_strmap.add_string(e.name, num) + e.num = num + device_strmap.bake() + + physical_device_strmap = StringIntMap() + for num, e in enumerate(physical_device_entrypoints): + physical_device_strmap.add_string(e.name, num) + e.num = num + physical_device_strmap.bake() + + instance_strmap = StringIntMap() + for num, e in enumerate(instance_entrypoints): + instance_strmap.add_string(e.name, num) e.num = num - strmap.bake() + instance_strmap.bake() # For outputting entrypoints.h we generate a anv_EntryPoint() prototype # per entry point. try: with open(os.path.join(args.outdir, 'anv_entrypoints.h'), 'wb') as f: - f.write(TEMPLATE_H.render(entrypoints=entrypoints, + f.write(TEMPLATE_H.render(instance_entrypoints=instance_entrypoints, + physical_device_entrypoints=physical_device_entrypoints, + device_entrypoints=device_entrypoints, LAYERS=LAYERS, filename=os.path.basename(__file__))) with open(os.path.join(args.outdir, 'anv_entrypoints.c'), 'wb') as f: - f.write(TEMPLATE_C.render(entrypoints=entrypoints, + f.write(TEMPLATE_C.render(instance_entrypoints=instance_entrypoints, + physical_device_entrypoints=physical_device_entrypoints, + device_entrypoints=device_entrypoints, LAYERS=LAYERS, - strmap=strmap, + instance_strmap=instance_strmap, + physical_device_strmap=physical_device_strmap, + device_strmap=device_strmap, filename=os.path.basename(__file__))) except Exception: - # In the even there's an error this imports some helpers from mako + # In the event there's an error, this imports some helpers from mako # to print a useful stack trace and prints it, then exits with # status 1, if python is run with debug; otherwise it just raises # the exception