From de00e8227b00740e3fe91c5c8fd0b2498751606c Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Sat, 20 Jan 2018 10:39:16 -0800 Subject: [PATCH] anv: Return trampoline entrypoints from GetInstanceProcAddr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Samuel Iglesias Gonsálvez --- 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 8fcc73eaba1..0cba17aa169 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -582,8 +582,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 5bae1949a80..1bab885180d 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)