From 19db95e78eb03d598c60487cc7939a507784530f Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Tue, 3 Sep 2019 13:54:35 +0300 Subject: anv: split instance dispatch table This effectively breaks the instance dispatch table in 2 with entry points using a physical device as first argument getting their own dispatch table. As a result we now have to check instance & physical device dispatch table instead of just the instance dispatch table before. Signed-off-by: Eric Engestrom Signed-off-by: Lionel Landwerlin Reviewed-by: Jason Ekstrand --- src/intel/vulkan/anv_device.c | 18 ++++ src/intel/vulkan/anv_entrypoints_gen.py | 171 ++++++++++++++++++++++++++++++++ src/intel/vulkan/anv_private.h | 10 +- 3 files changed, 198 insertions(+), 1 deletion(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index bb1834e1867..391a5576306 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -750,6 +750,20 @@ VkResult anv_CreateInstance( } } + struct anv_physical_device *pdevice = &instance->physicalDevice; + for (unsigned i = 0; i < ARRAY_SIZE(pdevice->dispatch.entrypoints); i++) { + /* Vulkan requires that entrypoints for extensions which have not been + * enabled must not be advertised. + */ + if (!anv_physical_device_entrypoint_is_enabled(i, instance->app_info.api_version, + &instance->enabled_extensions)) { + pdevice->dispatch.entrypoints[i] = NULL; + } else { + pdevice->dispatch.entrypoints[i] = + anv_physical_device_dispatch_table.entrypoints[i]; + } + } + for (unsigned i = 0; i < ARRAY_SIZE(instance->device_dispatch.entrypoints); i++) { /* Vulkan requires that entrypoints for extensions which have not been * enabled must not be advertised. @@ -1964,6 +1978,10 @@ PFN_vkVoidFunction anv_GetInstanceProcAddr( if (idx >= 0) return instance->dispatch.entrypoints[idx]; + idx = anv_get_physical_device_entrypoint_index(pName); + if (idx >= 0) + return instance->physicalDevice.dispatch.entrypoints[idx]; + idx = anv_get_device_entrypoint_index(pName); if (idx >= 0) return instance->device_dispatch.entrypoints[idx]; diff --git a/src/intel/vulkan/anv_entrypoints_gen.py b/src/intel/vulkan/anv_entrypoints_gen.py index 23ade58ae19..2d5ff460d04 100644 --- a/src/intel/vulkan/anv_entrypoints_gen.py +++ b/src/intel/vulkan/anv_entrypoints_gen.py @@ -70,6 +70,25 @@ struct anv_instance_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)}]; @@ -91,6 +110,9 @@ struct anv_device_dispatch_table { 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_device_dispatch_table ${layer}_device_dispatch_table; %endfor @@ -107,6 +129,21 @@ extern const struct anv_device_dispatch_table ${layer}_device_dispatch_table; % endif % endfor +% for e in physical_device_entrypoints: + % if e.alias: + <% 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 + % for e in device_entrypoints: % if e.alias: <% continue %> @@ -151,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; @@ -217,9 +256,20 @@ ${prefix}_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 @@ -252,6 +302,47 @@ const struct anv_instance_dispatch_table anv_instance_dispatch_table = { % endfor }; +% for layer in LAYERS: + % for e in physical_device_entrypoints: + % if e.alias: + <% 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 == 'VkPhysicalDevice': + ANV_FROM_HANDLE(anv_physical_device, anv_physical_device, ${e.params[0].name}); + return anv_physical_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_physical_device_dispatch_table ${layer}_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(layer)}, + % if e.guard is not None: +#endif // ${e.guard} + % endif + % endfor + }; +% endfor + + % for layer in LAYERS: % for e in device_entrypoints: % if e.alias: @@ -333,6 +424,40 @@ anv_instance_entrypoint_is_enabled(int index, uint32_t core_version, } } +/** 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) +{ + 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; + } +} + /** Return true if the core version or extension in which the given entrypoint * is defined is enabled. * @@ -373,12 +498,36 @@ 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); +} + static void * __attribute__ ((noinline)) anv_resolve_device_entrypoint(const struct gen_device_info *devinfo, uint32_t index) { @@ -422,6 +571,10 @@ anv_lookup_entrypoint(const struct gen_device_info *devinfo, const char *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); @@ -506,6 +659,9 @@ class Entrypoint(EntrypointBase): 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') @@ -524,6 +680,9 @@ 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() @@ -633,10 +792,13 @@ def main(): ])) 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) @@ -646,6 +808,12 @@ def main(): 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) @@ -657,14 +825,17 @@ def main(): try: with open(os.path.join(args.outdir, 'anv_entrypoints.h'), 'wb') as f: 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(instance_entrypoints=instance_entrypoints, + physical_device_entrypoints=physical_device_entrypoints, device_entrypoints=device_entrypoints, LAYERS=LAYERS, instance_strmap=instance_strmap, + physical_device_strmap=physical_device_strmap, device_strmap=device_strmap, filename=os.path.basename(__file__))) except Exception: diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index fa40c71839a..754f69b6c62 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -962,6 +962,7 @@ struct anv_physical_device { bool has_bindless_samplers; struct anv_device_extension_table supported_extensions; + struct anv_physical_device_dispatch_table dispatch; uint32_t eu_total; uint32_t subslice_total; @@ -3693,11 +3694,18 @@ struct anv_query_pool { int anv_get_instance_entrypoint_index(const char *name); int anv_get_device_entrypoint_index(const char *name); +int anv_get_physical_device_entrypoint_index(const char *name); + +const char *anv_get_instance_entry_name(int index); +const char *anv_get_physical_device_entry_name(int index); +const char *anv_get_device_entry_name(int index); bool anv_instance_entrypoint_is_enabled(int index, uint32_t core_version, const struct anv_instance_extension_table *instance); - +bool +anv_physical_device_entrypoint_is_enabled(int index, uint32_t core_version, + const struct anv_instance_extension_table *instance); bool anv_device_entrypoint_is_enabled(int index, uint32_t core_version, const struct anv_instance_extension_table *instance, -- cgit v1.2.1