Technically, the Vulkan spec requires that we return valid entrypoints for all core functionality and any available device extensions. This means that, for gen-specific functions, we need to return a trampoline which looks at the device and calls the right device function. In 99% of cases, the loader will do this for us but, aparently, we're supposed to do it too. It's a tiny increase in binary size for us to carry this around but really not bad.
Before: text data bss dec hex filename 3541775 204112 6136 3752023 394057 libvulkan_intel.so After: text data bss dec hex filename 3551463 205632 6136 3763231 396c1f libvulkan_intel.so --- src/intel/vulkan/anv_device.c | 5 +++- src/intel/vulkan/anv_entrypoints_gen.py | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 2291d69..b24690a 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -581,8 +581,11 @@ VkResult anv_CreateInstance( if (!anv_entrypoint_is_enabled(i, instance->apiVersion, &instance->enabled_extensions, NULL)) { instance->dispatch.entrypoints[i] = NULL; - } else { + } else if (anv_dispatch_table.entrypoints[i] != NULL) { instance->dispatch.entrypoints[i] = anv_dispatch_table.entrypoints[i]; + } else { + instance->dispatch.entrypoints[i] = + anv_tramp_dispatch_table.entrypoints[i]; } } diff --git a/src/intel/vulkan/anv_entrypoints_gen.py b/src/intel/vulkan/anv_entrypoints_gen.py index 5bae194..1bab885 100644 --- a/src/intel/vulkan/anv_entrypoints_gen.py +++ b/src/intel/vulkan/anv_entrypoints_gen.py @@ -71,6 +71,7 @@ struct anv_dispatch_table { %for layer in LAYERS: extern const struct anv_dispatch_table ${layer}_dispatch_table; %endfor +extern const struct anv_dispatch_table anv_tramp_dispatch_table; % for e in entrypoints: % if e.guard is not None: @@ -164,6 +165,48 @@ static const struct anv_entrypoint entrypoints[] = { }; % endfor + +/** Trampoline entrypoints for all device functions */ + +% for e in entrypoints: + % if e.params[0].type not in ('VkDevice', 'VkCommandBuffer'): + <% 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()}); + % else: + ANV_FROM_HANDLE(anv_cmd_buffer, anv_cmd_buffer, ${e.params[0].name}); + return anv_cmd_buffer->device->dispatch.${e.name}(${e.call_params()}); + % endif + } + % 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 e.params[0].type not in ('VkDevice', 'VkCommandBuffer'): + <% continue %> + % endif + % if e.guard is not None: +#ifdef ${e.guard} + % endif + .${e.name} = ${e.prefixed_name('anv_tramp')}, + % if e.guard is not None: +#endif // ${e.guard} + % endif +% endfor +}; + + /** Return true if the core version or extension in which the given entrypoint * is defined is enabled. * @@ -322,6 +365,9 @@ class Entrypoint(object): def decl_params(self): return ', '.join(p.decl for p in self.params) + def call_params(self): + return ', '.join(p.name for p in self.params) + def get_c_hash(self): return cal_hash(self.name) -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev