summaryrefslogtreecommitdiffstats
path: root/src/intel/vulkan/anv_entrypoints_gen.py
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-10-13 12:16:14 -0500
committerJason Ekstrand <[email protected]>2018-10-15 13:30:24 -0500
commitae18c53ba6e0cb0b54a6e76caf6fbfa8a180c076 (patch)
tree2e69d7fefe3085922b728aaa1699a6ef2de7403c /src/intel/vulkan/anv_entrypoints_gen.py
parent18cc65edf8480bc83685b3665c8c5268b1da79e6 (diff)
anv: Split dispatch tables into device and instance
There's no reason why we need generate trampoline functions for instance functions or carry N copies of the instance dispatch table around for every hardware generation. Splitting the tables and being more conservative shaves about 34K off .text and about 4K off .data when built with clang. Before splitting dispatch tables: text data bss dec hex filename 3224305 286216 8960 3519481 35b3f9 _install/lib64/libvulkan_intel.so After splitting dispatch tables: text data bss dec hex filename 3190325 282232 8960 3481517 351fad _install/lib64/libvulkan_intel.so Reviewed-by: Lionel Landwerlin <[email protected]>
Diffstat (limited to 'src/intel/vulkan/anv_entrypoints_gen.py')
-rw-r--r--src/intel/vulkan/anv_entrypoints_gen.py242
1 files changed, 178 insertions, 64 deletions
diff --git a/src/intel/vulkan/anv_entrypoints_gen.py b/src/intel/vulkan/anv_entrypoints_gen.py
index e6cd9bbf0a9..beb658b8660 100644
--- a/src/intel/vulkan/anv_entrypoints_gen.py
+++ b/src/intel/vulkan/anv_entrypoints_gen.py
@@ -50,11 +50,11 @@ LAYERS = [
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};
@@ -69,12 +69,45 @@ struct anv_dispatch_table {
};
};
+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_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;
+extern const struct anv_device_dispatch_table anv_tramp_device_dispatch_table;
-% for e in entrypoints:
+% for e in instance_entrypoints:
+ % if e.alias:
+ <% 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 device_entrypoints:
% if e.alias:
<% continue %>
% endif
@@ -129,13 +162,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
@@ -150,14 +184,14 @@ static const struct string_map_entry string_map_entries[] = {
*/
#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};
@@ -172,25 +206,54 @@ 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;
}
return -1;
}
+</%def>
+
+${strmap(instance_strmap, 'instance')}
+${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 e in instance_entrypoints:
+ % if e.alias:
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % 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_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('anv')},
+ % if e.guard is not None:
+#endif // ${e.guard}
+ % endif
+% endfor
+};
+
% for layer in LAYERS:
- % for e in entrypoints:
+ % for e in device_entrypoints:
% if e.alias:
<% continue %>
% endif
@@ -203,8 +266,8 @@ string_map_lookup(const char *str)
% endif
% endfor
- const struct anv_dispatch_table ${layer}_dispatch_table = {
- % for e in entrypoints:
+ 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
@@ -219,8 +282,8 @@ string_map_lookup(const char *str)
/** Trampoline entrypoints for all device functions */
-% for e in entrypoints:
- % if e.alias or not e.is_device_entrypoint():
+% for e in device_entrypoints:
+ % if e.alias:
<% continue %>
% endif
% if e.guard is not None:
@@ -247,11 +310,8 @@ string_map_lookup(const char *str)
% 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_device_dispatch_table anv_tramp_device_dispatch_table = {
+% for e in device_entrypoints:
% if e.guard is not None:
#ifdef ${e.guard}
% endif
@@ -269,26 +329,22 @@ const struct anv_dispatch_table anv_tramp_dispatch_table = {
* 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;
@@ -301,32 +357,74 @@ 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_device_entrypoint_is_enabled(int index, uint32_t core_version,
+ const struct anv_instance_extension_table *instance,
+ const struct anv_device_extension_table *device)
{
- if (devinfo == NULL) {
- return anv_dispatch_table.entrypoints[index];
+ 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_device_entrypoint_index(const char *name)
+{
+ return device_string_map_lookup(name);
+}
- const struct anv_dispatch_table *genX_table;
+static 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 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");
@@ -335,22 +433,21 @@ 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_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
@@ -554,23 +651,40 @@ def main():
EntrypointParam('VkImage', 'pImage', 'VkImage* pImage')
]))
- strmap = StringIntMap()
- for num, e in enumerate(entrypoints):
- strmap.add_string(e.name, num)
+ device_entrypoints = []
+ instance_entrypoints = []
+ for e in entrypoints:
+ if e.is_device_entrypoint():
+ 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()
+
+ 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,
+ 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,
+ device_entrypoints=device_entrypoints,
LAYERS=LAYERS,
- strmap=strmap,
+ instance_strmap=instance_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