anv: Return trampoline entrypoints from GetInstanceProcAddr

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 <siglesias@igalia.com>
This commit is contained in:
Jason Ekstrand 2018-01-20 10:39:16 -08:00
parent eac29f3a6d
commit de00e8227b
2 changed files with 50 additions and 1 deletions

View File

@ -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];
}
}

View File

@ -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)