[Mesa-dev] [PATCH 3/4] anv: Use central api generation scripts.

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Tue Aug 7 23:14:33 UTC 2018


This became kind of messy as python imports cannot really look up
parent/sibling directories. I saw some scripts use sys.path but
that became even more messy due to import locations.

I also move the selections of the dispatch table out of the
generation script because it is not easily shared, and generating
it did not really win anything anyway.
---
 src/intel/Android.vulkan.mk             |   9 +
 src/intel/Makefile.vulkan.am            |  25 +-
 src/intel/vulkan/anv_device.c           |  46 ++
 src/intel/vulkan/anv_entrypoints_gen.py | 537 +-----------------------
 src/intel/vulkan/anv_extensions.py      |  68 +--
 src/intel/vulkan/anv_extensions_gen.py  | 177 +-------
 src/intel/vulkan/meson.build            |  15 +-
 src/vulkan/util/vk_extensions.py        |   5 +-
 8 files changed, 98 insertions(+), 784 deletions(-)

diff --git a/src/intel/Android.vulkan.mk b/src/intel/Android.vulkan.mk
index 09dc22875a1..af59963c66d 100644
--- a/src/intel/Android.vulkan.mk
+++ b/src/intel/Android.vulkan.mk
@@ -27,6 +27,11 @@ VK_ENTRYPOINTS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_entrypoints_ge
 
 VK_EXTENSIONS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_extensions_gen.py
 
+vulkan_api_generators_py := \
+	$(MESA_TOP)/src/vulkan/util/vk_entrypoints_gen.py \
+	$(MESA_TOP)/src/vulkan/util/vk_extensions_gen.py \
+	$(MESA_TOP)/src/vulkan/util/vk_extensions.py
+
 VULKAN_COMMON_INCLUDES := \
 	$(MESA_TOP)/include \
 	$(MESA_TOP)/src/mapi \
@@ -65,6 +70,7 @@ $(intermediates)/vulkan/dummy.c:
 	$(hide) touch $@
 
 $(intermediates)/vulkan/anv_entrypoints.h: $(intermediates)/vulkan/dummy.c
+	PYTHONPATH=$(MESA_TOP)/src/vulkan/util \
 	$(VK_ENTRYPOINTS_SCRIPT) \
 		--outdir $(dir $@) \
 		--xml $(MESA_TOP)/src/vulkan/registry/vk.xml
@@ -242,18 +248,21 @@ LOCAL_GENERATED_SOURCES += $(intermediates)/vulkan/anv_extensions.h
 
 $(intermediates)/vulkan/anv_entrypoints.c:
 	@mkdir -p $(dir $@)
+	PYTHONPATH=$(MESA_TOP)/src/vulkan/util \
 	$(VK_ENTRYPOINTS_SCRIPT) \
 		--xml $(MESA_TOP)/src/vulkan/registry/vk.xml \
 		--outdir $(dir $@)
 
 $(intermediates)/vulkan/anv_extensions.c:
 	@mkdir -p $(dir $@)
+	PYTHONPATH=$(MESA_TOP)/src/vulkan/util \
 	$(VK_EXTENSIONS_SCRIPT) \
 		--xml $(MESA_TOP)/src/vulkan/registry/vk.xml \
 		--out-c $@
 
 $(intermediates)/vulkan/anv_extensions.h:
 	@mkdir -p $(dir $@)
+	PYTHONPATH=$(MESA_TOP)/src/vulkan/util \
 	$(VK_EXTENSIONS_SCRIPT) \
 		--xml $(MESA_TOP)/src/vulkan/registry/vk.xml \
 		--out-h $@
diff --git a/src/intel/Makefile.vulkan.am b/src/intel/Makefile.vulkan.am
index 9555d98095b..91577bc9026 100644
--- a/src/intel/Makefile.vulkan.am
+++ b/src/intel/Makefile.vulkan.am
@@ -24,10 +24,17 @@
 # out and we'll fail at `make dist'
 vulkan_api_xml = $(top_srcdir)/src/vulkan/registry/vk.xml
 
+vulkan_api_generators_py = \
+	$(top_srcdir)/src/vulkan/util/vk_entrypoints_gen.py \
+	$(top_srcdir)/src/vulkan/util/vk_extensions_gen.py \
+	$(top_srcdir)/src/vulkan/util/vk_extensions.py
+
 vulkan/anv_entrypoints.c: vulkan/anv_entrypoints_gen.py \
 			  vulkan/anv_extensions.py \
-			  $(vulkan_api_xml)
+			  $(vulkan_api_xml) \
+			  $(vulkan_api_generators_py)
 	$(MKDIR_GEN)
+	PYTHONPATH=$(top_srcdir)/src/vulkan/util \
 	$(AM_V_GEN)$(PYTHON2) $(srcdir)/vulkan/anv_entrypoints_gen.py \
 		--xml $(vulkan_api_xml) \
 		--outdir $(builddir)/vulkan
@@ -35,16 +42,20 @@ vulkan/anv_entrypoints.h: vulkan/anv_entrypoints.c
 
 vulkan/anv_extensions.c: vulkan/anv_extensions_gen.py \
 			 vulkan/anv_extensions.py \
-			 $(vulkan_api_xml)
+			 $(vulkan_api_xml) \
+			 $(vulkan_api_generators_py)
 	$(MKDIR_GEN)
+	PYTHONPATH=$(top_srcdir)/src/vulkan/util \
 	$(AM_V_GEN)$(PYTHON2) $(srcdir)/vulkan/anv_extensions_gen.py \
 		--xml $(vulkan_api_xml) \
 		--out-c $@
 
 vulkan/anv_extensions.h: vulkan/anv_extensions_gen.py \
 			 vulkan/anv_extensions.py \
-			 $(vulkan_api_xml)
+			 $(vulkan_api_xml) \
+			 $(vulkan_api_generators_py)
 	$(MKDIR_GEN)
+	PYTHONPATH=$(top_srcdir)/src/vulkan/util \
 	$(AM_V_GEN)$(PYTHON2) $(srcdir)/vulkan/anv_extensions_gen.py \
 		--xml $(vulkan_api_xml) \
 		--out-h $@
@@ -63,13 +74,17 @@ EXTRA_DIST += \
 	vulkan/anv_icd.py \
 	vulkan/TODO
 
-vulkan/dev_icd.json : vulkan/anv_extensions.py vulkan/anv_icd.py
+vulkan/dev_icd.json : vulkan/anv_extensions.py vulkan/anv_icd.py \
+		      $(vulkan_api_generators_py)
 	$(MKDIR_GEN)
+	PYTHONPATH=$(top_srcdir)/src/vulkan/util \
 	$(AM_V_GEN)$(PYTHON2) $(srcdir)/vulkan/anv_icd.py \
 		--lib-path="${abs_top_builddir}/${LIB_DIR}" --out $@
 
-vulkan/intel_icd. at host_cpu@.json : vulkan/anv_extensions.py vulkan/anv_icd.py
+vulkan/intel_icd. at host_cpu@.json : vulkan/anv_extensions.py vulkan/anv_icd.py \
+				   $(vulkan_api_generators_py)
 	$(MKDIR_GEN)
+	PYTHONPATH=$(top_srcdir)/src/vulkan/util \
 	$(AM_V_GEN)$(PYTHON2) $(srcdir)/vulkan/anv_icd.py \
 		--lib-path="${libdir}" --out $@
 
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index c40b94d69f3..9f1dc930c34 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -1251,6 +1251,52 @@ anv_GetDeviceGroupPeerMemoryFeatures(
                           VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
 }
 
+static void * __attribute__ ((noinline))
+anv_resolve_entrypoint(const struct gen_device_info *devinfo, uint32_t index)
+{
+   if (devinfo == NULL) {
+      return anv_dispatch_table.entrypoints[index];
+   }
+
+   const struct anv_dispatch_table *genX_table;
+   switch (devinfo->gen) {
+   case 11:
+      genX_table = &gen11_dispatch_table;
+      break;
+   case 10:
+      genX_table = &gen10_dispatch_table;
+      break;
+   case 9:
+      genX_table = &gen9_dispatch_table;
+      break;
+   case 8:
+      genX_table = &gen8_dispatch_table;
+      break;
+   case 7:
+      if (devinfo->is_haswell)
+         genX_table = &gen75_dispatch_table;
+      else
+         genX_table = &gen7_dispatch_table;
+      break;
+   default:
+      unreachable("unsupported gen\\n");
+   }
+
+   if (genX_table->entrypoints[index])
+      return genX_table->entrypoints[index];
+   else
+      return anv_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);
+}
+
 PFN_vkVoidFunction anv_GetInstanceProcAddr(
     VkInstance                                  _instance,
     const char*                                 pName)
diff --git a/src/intel/vulkan/anv_entrypoints_gen.py b/src/intel/vulkan/anv_entrypoints_gen.py
index e6cd9bbf0a9..219369ecc67 100644
--- a/src/intel/vulkan/anv_entrypoints_gen.py
+++ b/src/intel/vulkan/anv_entrypoints_gen.py
@@ -23,14 +23,10 @@
 #
 
 import argparse
-import math
 import os
-import xml.etree.cElementTree as et
 
-from collections import OrderedDict, namedtuple
-from mako.template import Template
-
-from anv_extensions import VkVersion, MAX_API_VERSION, EXTENSIONS
+from anv_extensions import MAX_API_VERSION, EXTENSIONS
+import vk_entrypoints_gen
 
 # We generate a static hash table for entry point lookup
 # (vkGetProcAddress). We use a linear congruential generator for our hash
@@ -47,483 +43,6 @@ LAYERS = [
     'gen11',
 ]
 
-TEMPLATE_H = Template("""\
-/* This file generated from ${filename}, don't edit directly. */
-
-struct anv_dispatch_table {
-   union {
-      void *entrypoints[${len(entrypoints)}];
-      struct {
-      % for e in 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
-      };
-   };
-};
-
-%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.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
-""", output_encoding='utf-8')
-
-TEMPLATE_C = Template(u"""\
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* This file generated from ${filename}, don't edit directly. */
-
-#include "anv_private.h"
-
-struct string_map_entry {
-   uint32_t name;
-   uint32_t hash;
-   uint32_t num;
-};
-
-/* We use a big string constant to avoid lots of reloctions from the entry
- * point table to lots of little strings. The entries in the entry point table
- * store the index into this big string.
- */
-
-static const char strings[] =
-% for s in strmap.sorted_strings:
-    "${s.string}\\0"
-% endfor
-;
-
-static const struct string_map_entry string_map_entries[] = {
-% for s in strmap.sorted_strings:
-    { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */
-% endfor
-};
-
-/* Hash table stats:
- * size ${len(strmap.sorted_strings)} entries
- * collisions entries:
-% for i in range(10):
- *     ${i}${'+' if i == 9 else ' '}     ${strmap.collisions[i]}
-% endfor
- */
-
-#define none 0xffff
-static const uint16_t 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)
-{
-    static const uint32_t prime_factor = ${strmap.prime_factor};
-    static const uint32_t prime_step = ${strmap.prime_step};
-    const struct string_map_entry *e;
-    uint32_t hash, h;
-    uint16_t i;
-    const char *p;
-
-    hash = 0;
-    for (p = str; *p; p++)
-        hash = hash * prime_factor + *p;
-
-    h = hash;
-    while (1) {
-        i = 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)
-            return e->num;
-        h += prime_step;
-    }
-
-    return -1;
-}
-
-/* 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 layer in LAYERS:
-  % for e in entrypoints:
-    % if e.alias:
-      <% continue %>
-    % endif
-    % if e.guard is not None:
-#ifdef ${e.guard}
-    % endif
-    ${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak));
-    % if e.guard is not None:
-#endif // ${e.guard}
-    % endif
-  % endfor
-
-  const struct anv_dispatch_table ${layer}_dispatch_table = {
-  % for e in 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
-
-
-/** Trampoline entrypoints for all device functions */
-
-% for e in entrypoints:
-  % if e.alias or not e.is_device_entrypoint():
-    <% 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()});
-    % elif e.params[0].type == 'VkCommandBuffer':
-      ANV_FROM_HANDLE(anv_cmd_buffer, anv_cmd_buffer, ${e.params[0].name});
-      return anv_cmd_buffer->device->dispatch.${e.name}(${e.call_params()});
-    % elif e.params[0].type == 'VkQueue':
-      ANV_FROM_HANDLE(anv_queue, anv_queue, ${e.params[0].name});
-      return anv_queue->device->dispatch.${e.name}(${e.call_params()});
-    % else:
-      assert(!"Unhandled device child trampoline case: ${e.params[0].type}");
-    % 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 not e.is_device_entrypoint():
-    <% 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.
- *
- * 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)
-{
-   switch (index) {
-% for e in 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
-   % elif e.extensions:
-     % for ext in e.extensions:
-       % if ext.type == 'instance':
-      if (!device && instance->${ext.name[3:]}) return true;
-        % else:
-      if (!device || device->${ext.name[3:]}) return true;
-        % endif
-     % endfor
-      return false;
-   % else:
-      return true;
-   % endif
-% endfor
-   default:
-      return false;
-   }
-}
-
-static void * __attribute__ ((noinline))
-anv_resolve_entrypoint(const struct gen_device_info *devinfo, uint32_t index)
-{
-   if (devinfo == NULL) {
-      return anv_dispatch_table.entrypoints[index];
-   }
-
-   const struct anv_dispatch_table *genX_table;
-   switch (devinfo->gen) {
-   case 11:
-      genX_table = &gen11_dispatch_table;
-      break;
-   case 10:
-      genX_table = &gen10_dispatch_table;
-      break;
-   case 9:
-      genX_table = &gen9_dispatch_table;
-      break;
-   case 8:
-      genX_table = &gen8_dispatch_table;
-      break;
-   case 7:
-      if (devinfo->is_haswell)
-         genX_table = &gen75_dispatch_table;
-      else
-         genX_table = &gen7_dispatch_table;
-      break;
-   default:
-      unreachable("unsupported gen\\n");
-   }
-
-   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);
-}
-
-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);
-}""", output_encoding='utf-8')
-
-U32_MASK = 2**32 - 1
-
-PRIME_FACTOR = 5024183
-PRIME_STEP = 19
-
-class StringIntMapEntry(object):
-    def __init__(self, string, num):
-        self.string = string
-        self.num = num
-
-        # Calculate the same hash value that we will calculate in C.
-        h = 0
-        for c in string:
-            h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK
-        self.hash = h
-
-        self.offset = None
-
-def round_to_pow2(x):
-    return 2**int(math.ceil(math.log(x, 2)))
-
-class StringIntMap(object):
-    def __init__(self):
-        self.baked = False
-        self.strings = dict()
-
-    def add_string(self, string, num):
-        assert not self.baked
-        assert string not in self.strings
-        assert num >= 0 and num < 2**31
-        self.strings[string] = StringIntMapEntry(string, num)
-
-    def bake(self):
-        self.sorted_strings = \
-            sorted(self.strings.values(), key=lambda x: x.string)
-        offset = 0
-        for entry in self.sorted_strings:
-            entry.offset = offset
-            offset += len(entry.string) + 1
-
-        # Save off some values that we'll need in C
-        self.hash_size = round_to_pow2(len(self.strings) * 1.25)
-        self.hash_mask = self.hash_size - 1
-        self.prime_factor = PRIME_FACTOR
-        self.prime_step = PRIME_STEP
-
-        self.mapping = [-1] * self.hash_size
-        self.collisions = [0] * 10
-        for idx, s in enumerate(self.sorted_strings):
-            level = 0
-            h = s.hash
-            while self.mapping[h & self.hash_mask] >= 0:
-                h = h + PRIME_STEP
-                level = level + 1
-            self.collisions[min(level, 9)] += 1
-            self.mapping[h & self.hash_mask] = idx
-
-EntrypointParam = namedtuple('EntrypointParam', 'type name decl')
-
-class EntrypointBase(object):
-    def __init__(self, name):
-        self.name = name
-        self.alias = None
-        self.guard = None
-        self.enabled = False
-        self.num = None
-        # Extensions which require this entrypoint
-        self.core_version = None
-        self.extensions = []
-
-class Entrypoint(EntrypointBase):
-    def __init__(self, name, return_type, params, guard = None):
-        super(Entrypoint, self).__init__(name)
-        self.return_type = return_type
-        self.params = params
-        self.guard = guard
-
-    def is_device_entrypoint(self):
-        return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue')
-
-    def prefixed_name(self, prefix):
-        assert self.name.startswith('vk')
-        return prefix + '_' + self.name[2:]
-
-    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)
-
-class EntrypointAlias(EntrypointBase):
-    def __init__(self, name, entrypoint):
-        super(EntrypointAlias, self).__init__(name)
-        self.alias = entrypoint
-
-    def is_device_entrypoint(self):
-        return self.alias.is_device_entrypoint()
-
-    def prefixed_name(self, prefix):
-        return self.alias.prefixed_name(prefix)
-
-def get_entrypoints(doc, entrypoints_to_defines, start_index):
-    """Extract the entry points from the registry."""
-    entrypoints = OrderedDict()
-
-    for command in doc.findall('./commands/command'):
-        if 'alias' in command.attrib:
-            alias = command.attrib['name']
-            target = command.attrib['alias']
-            entrypoints[alias] = EntrypointAlias(alias, entrypoints[target])
-        else:
-            name = command.find('./proto/name').text
-            ret_type = command.find('./proto/type').text
-            params = [EntrypointParam(
-                type = p.find('./type').text,
-                name = p.find('./name').text,
-                decl = ''.join(p.itertext())
-            ) for p in command.findall('./param')]
-            guard = entrypoints_to_defines.get(name)
-            # They really need to be unique
-            assert name not in entrypoints
-            entrypoints[name] = Entrypoint(name, ret_type, params, guard)
-
-    for feature in doc.findall('./feature'):
-        assert feature.attrib['api'] == 'vulkan'
-        version = VkVersion(feature.attrib['number'])
-        if version > MAX_API_VERSION:
-            continue
-
-        for command in feature.findall('./require/command'):
-            e = entrypoints[command.attrib['name']]
-            e.enabled = True
-            assert e.core_version is None
-            e.core_version = version
-
-    supported_exts = dict((ext.name, ext) for ext in EXTENSIONS)
-    for extension in doc.findall('.extensions/extension'):
-        ext_name = extension.attrib['name']
-        if ext_name not in supported_exts:
-            continue
-
-        ext = supported_exts[ext_name]
-        ext.type = extension.attrib['type']
-
-        for command in extension.findall('./require/command'):
-            e = entrypoints[command.attrib['name']]
-            e.enabled = True
-            assert e.core_version is None
-            e.extensions.append(ext)
-
-    return [e for e in entrypoints.values() if e.enabled]
-
-
-def get_entrypoints_defines(doc):
-    """Maps entry points to extension defines."""
-    entrypoints_to_defines = {}
-
-    for extension in doc.findall('./extensions/extension[@platform]'):
-        platform = extension.attrib['platform']
-        ext = '_KHR'
-        if platform.upper() == 'XLIB_XRANDR':
-            ext = '_EXT'
-        define = 'VK_USE_PLATFORM_' + platform.upper() + ext
-
-        for entrypoint in extension.findall('./require/command'):
-            fullname = entrypoint.attrib['name']
-            entrypoints_to_defines[fullname] = define
-
-    return entrypoints_to_defines
-
-
 def main():
     parser = argparse.ArgumentParser()
     parser.add_argument('--outdir', help='Where to write the files.',
@@ -535,54 +54,10 @@ def main():
                         dest='xml_files')
     args = parser.parse_args()
 
-    entrypoints = []
-
-    for filename in args.xml_files:
-        doc = et.parse(filename)
-        entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc),
-                                       start_index=len(entrypoints))
-
-    # Manually add CreateDmaBufImageINTEL for which we don't have an extension
-    # defined.
-    entrypoints.append(Entrypoint('vkCreateDmaBufImageINTEL', 'VkResult', [
-        EntrypointParam('VkDevice', 'device', 'VkDevice device'),
-        EntrypointParam('VkDmaBufImageCreateInfo', 'pCreateInfo',
-                        'const VkDmaBufImageCreateInfo* pCreateInfo'),
-        EntrypointParam('VkAllocationCallbacks', 'pAllocator',
-                        'const VkAllocationCallbacks* pAllocator'),
-        EntrypointParam('VkDeviceMemory', 'pMem', 'VkDeviceMemory* pMem'),
-        EntrypointParam('VkImage', 'pImage', 'VkImage* pImage')
-    ]))
-
-    strmap = StringIntMap()
-    for num, e in enumerate(entrypoints):
-        strmap.add_string(e.name, num)
-        e.num = num
-    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,
-                                      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,
-                                      LAYERS=LAYERS,
-                                      strmap=strmap,
-                                      filename=os.path.basename(__file__)))
-    except Exception:
-        # In the even there's an error this imports some helpers from mako
-        # to print a useful stack trace and prints it, then exits with
-        # status 1, if python is run with debug; otherwise it just raises
-        # the exception
-        if __debug__:
-            import sys
-            from mako import exceptions
-            sys.stderr.write(exceptions.text_error_template().render() + '\n')
-            sys.exit(1)
-        raise
+    vk_entrypoints_gen.generate_entrypoints(MAX_API_VERSION, EXTENSIONS, LAYERS, 'anv', args.xml_files,
+                                            os.path.join(args.outdir, 'anv_entrypoints.c'),
+                                            os.path.join(args.outdir, 'anv_entrypoints.h'),
+                                            has_intel_entrypoints=True)
 
 
 if __name__ == '__main__':
diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py
index 9a65aed1c46..eab48a42a64 100644
--- a/src/intel/vulkan/anv_extensions.py
+++ b/src/intel/vulkan/anv_extensions.py
@@ -24,29 +24,7 @@ COPYRIGHT = """\
  */
 """
 
-import argparse
-import copy
-import re
-import xml.etree.cElementTree as et
-
-def _bool_to_c_expr(b):
-    if b is True:
-        return 'true'
-    elif b is False:
-        return 'false'
-    else:
-        return b
-
-class Extension:
-    def __init__(self, name, ext_version, enable):
-        self.name = name
-        self.ext_version = int(ext_version)
-        self.enable = _bool_to_c_expr(enable)
-
-class ApiVersion:
-    def __init__(self, version, enable):
-        self.version = version
-        self.enable = _bool_to_c_expr(enable)
+from vk_extensions import ApiVersion, Extension, VkVersion
 
 API_PATCH_VERSION = 80
 
@@ -127,50 +105,6 @@ EXTENSIONS = [
     Extension('VK_EXT_post_depth_coverage',               1, 'device->info.gen >= 9'),
 ]
 
-class VkVersion:
-    def __init__(self, string):
-        split = string.split('.')
-        self.major = int(split[0])
-        self.minor = int(split[1])
-        if len(split) > 2:
-            assert len(split) == 3
-            self.patch = int(split[2])
-        else:
-            self.patch = None
-
-        # Sanity check.  The range bits are required by the definition of the
-        # VK_MAKE_VERSION macro
-        assert self.major < 1024 and self.minor < 1024
-        assert self.patch is None or self.patch < 4096
-        assert(str(self) == string)
-
-    def __str__(self):
-        ver_list = [str(self.major), str(self.minor)]
-        if self.patch is not None:
-            ver_list.append(str(self.patch))
-        return '.'.join(ver_list)
-
-    def c_vk_version(self):
-        patch = self.patch if self.patch is not None else 0
-        ver_list = [str(self.major), str(self.minor), str(patch)]
-        return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')'
-
-    def __int_ver(self):
-        # This is just an expansion of VK_VERSION
-        patch = self.patch if self.patch is not None else 0
-        return (self.major << 22) | (self.minor << 12) | patch
-
-    def __gt__(self, other):
-        # If only one of them has a patch version, "ignore" it by making
-        # other's patch version match self.
-        if (self.patch is None) != (other.patch is None):
-            other = copy.copy(other)
-            other.patch = self.patch
-
-        return self.__int_ver() > other.__int_ver()
-
-
-
 MAX_API_VERSION = VkVersion('0.0.0')
 for version in API_VERSIONS:
     version.version = VkVersion(version.version)
diff --git a/src/intel/vulkan/anv_extensions_gen.py b/src/intel/vulkan/anv_extensions_gen.py
index a140c267452..6e8361c7227 100644
--- a/src/intel/vulkan/anv_extensions_gen.py
+++ b/src/intel/vulkan/anv_extensions_gen.py
@@ -25,162 +25,9 @@ COPYRIGHT = """\
 """
 
 import argparse
-import xml.etree.cElementTree as et
-
-from mako.template import Template
 
 from anv_extensions import *
-
-def _init_exts_from_xml(xml):
-    """ Walk the Vulkan XML and fill out extra extension information. """
-
-    xml = et.parse(xml)
-
-    ext_name_map = {}
-    for ext in EXTENSIONS:
-        ext_name_map[ext.name] = ext
-
-    for ext_elem in xml.findall('.extensions/extension'):
-        ext_name = ext_elem.attrib['name']
-        if ext_name not in ext_name_map:
-            continue
-
-        ext = ext_name_map[ext_name]
-        ext.type = ext_elem.attrib['type']
-
-_TEMPLATE_H = Template(COPYRIGHT + """
-
-#ifndef ANV_EXTENSIONS_H
-#define ANV_EXTENSIONS_H
-
-#include "stdbool.h"
-
-#define ANV_INSTANCE_EXTENSION_COUNT ${len(instance_extensions)}
-
-extern const VkExtensionProperties anv_instance_extensions[];
-
-struct anv_instance_extension_table {
-   union {
-      bool extensions[ANV_INSTANCE_EXTENSION_COUNT];
-      struct {
-%for ext in instance_extensions:
-         bool ${ext.name[3:]};
-%endfor
-      };
-   };
-};
-
-extern const struct anv_instance_extension_table anv_instance_extensions_supported;
-
-
-#define ANV_DEVICE_EXTENSION_COUNT ${len(device_extensions)}
-
-extern const VkExtensionProperties anv_device_extensions[];
-
-struct anv_device_extension_table {
-   union {
-      bool extensions[ANV_DEVICE_EXTENSION_COUNT];
-      struct {
-%for ext in device_extensions:
-        bool ${ext.name[3:]};
-%endfor
-      };
-   };
-};
-
-struct anv_physical_device;
-
-void
-anv_physical_device_get_supported_extensions(const struct anv_physical_device *device,
-                                             struct anv_device_extension_table *extensions);
-
-#endif /* ANV_EXTENSIONS_H */
-""")
-
-_TEMPLATE_C = Template(COPYRIGHT + """
-#include "anv_private.h"
-
-#include "vk_util.h"
-
-/* Convert the VK_USE_PLATFORM_* defines to booleans */
-%for platform in ['ANDROID_KHR', 'WAYLAND_KHR', 'XCB_KHR', 'XLIB_KHR', 'DISPLAY_KHR', 'XLIB_XRANDR_EXT']:
-#ifdef VK_USE_PLATFORM_${platform}
-#   undef VK_USE_PLATFORM_${platform}
-#   define VK_USE_PLATFORM_${platform} true
-#else
-#   define VK_USE_PLATFORM_${platform} false
-#endif
-%endfor
-
-/* And ANDROID too */
-#ifdef ANDROID
-#   undef ANDROID
-#   define ANDROID true
-#else
-#   define ANDROID false
-#endif
-
-#define ANV_HAS_SURFACE (VK_USE_PLATFORM_WAYLAND_KHR || \\
-                         VK_USE_PLATFORM_XCB_KHR || \\
-                         VK_USE_PLATFORM_XLIB_KHR || \\
-                         VK_USE_PLATFORM_DISPLAY_KHR)
-
-static const uint32_t MAX_API_VERSION = ${MAX_API_VERSION.c_vk_version()};
-
-VkResult anv_EnumerateInstanceVersion(
-    uint32_t*                                   pApiVersion)
-{
-    *pApiVersion = MAX_API_VERSION;
-    return VK_SUCCESS;
-}
-
-const VkExtensionProperties anv_instance_extensions[ANV_INSTANCE_EXTENSION_COUNT] = {
-%for ext in instance_extensions:
-   {"${ext.name}", ${ext.ext_version}},
-%endfor
-};
-
-const struct anv_instance_extension_table anv_instance_extensions_supported = {
-%for ext in instance_extensions:
-   .${ext.name[3:]} = ${ext.enable},
-%endfor
-};
-
-uint32_t
-anv_physical_device_api_version(struct anv_physical_device *device)
-{
-    uint32_t version = 0;
-
-    uint32_t override = vk_get_version_override();
-    if (override)
-        return MIN2(override, MAX_API_VERSION);
-
-%for version in API_VERSIONS:
-    if (!(${version.enable}))
-        return version;
-    version = ${version.version.c_vk_version()};
-
-%endfor
-    return version;
-}
-
-const VkExtensionProperties anv_device_extensions[ANV_DEVICE_EXTENSION_COUNT] = {
-%for ext in device_extensions:
-   {"${ext.name}", ${ext.ext_version}},
-%endfor
-};
-
-void
-anv_physical_device_get_supported_extensions(const struct anv_physical_device *device,
-                                             struct anv_device_extension_table *extensions)
-{
-   *extensions = (struct anv_device_extension_table) {
-%for ext in device_extensions:
-      .${ext.name[3:]} = ${ext.enable},
-%endfor
-   };
-}
-""")
+import vk_extensions_gen
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser()
@@ -193,23 +40,5 @@ if __name__ == '__main__':
                         dest='xml_files')
     args = parser.parse_args()
 
-    for filename in args.xml_files:
-        _init_exts_from_xml(filename)
-
-    for ext in EXTENSIONS:
-        assert ext.type == 'instance' or ext.type == 'device'
-
-    template_env = {
-        'API_VERSIONS': API_VERSIONS,
-        'MAX_API_VERSION': MAX_API_VERSION,
-        'instance_extensions': [e for e in EXTENSIONS if e.type == 'instance'],
-        'device_extensions': [e for e in EXTENSIONS if e.type == 'device'],
-    }
-
-    if args.out_h:
-        with open(args.out_h, 'w') as f:
-            f.write(_TEMPLATE_H.render(**template_env))
-
-    if args.out_c:
-        with open(args.out_c, 'w') as f:
-            f.write(_TEMPLATE_C.render(**template_env))
+    vk_extensions_gen.generate_extensions(MAX_API_VERSION, API_VERSIONS, EXTENSIONS, 'anv', 
+                                          args.xml_files, args.out_c, args.out_h)
diff --git a/src/intel/vulkan/meson.build b/src/intel/vulkan/meson.build
index e427c7471f4..41f94398679 100644
--- a/src/intel/vulkan/meson.build
+++ b/src/intel/vulkan/meson.build
@@ -25,10 +25,11 @@ anv_entrypoints = custom_target(
   input : ['anv_entrypoints_gen.py', vk_api_xml],
   output : ['anv_entrypoints.h', 'anv_entrypoints.c'],
   command : [
+    'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
     prog_python2, '@INPUT0@', '--xml', '@INPUT1@',
     '--outdir', meson.current_build_dir(),
   ],
-  depend_files : anv_extensions_py,
+  depend_files : [anv_extensions_py, vk_api_generators_py],
 )
 
 anv_extensions_c = custom_target(
@@ -36,10 +37,11 @@ anv_extensions_c = custom_target(
   input : ['anv_extensions_gen.py', vk_api_xml],
   output : 'anv_extensions.c',
   command : [
+   'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
     prog_python2, '@INPUT0@', '--xml', '@INPUT1@',
     '--out-c', '@OUTPUT@',
   ],
-  depend_files : anv_extensions_py,
+  depend_files : [anv_extensions_py, vk_api_generators_py],
 )
 
 anv_extensions_h = custom_target(
@@ -47,10 +49,11 @@ anv_extensions_h = custom_target(
   input : ['anv_extensions_gen.py', vk_api_xml],
   output : 'anv_extensions.h',
   command : [
+    'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
     prog_python2, '@INPUT0@', '--xml', '@INPUT1@',
     '--out-h', '@OUTPUT@',
   ],
-  depend_files : anv_extensions_py,
+  depend_files : [anv_extensions_py, vk_api_generators_py],
 )
 
 intel_icd = custom_target(
@@ -58,11 +61,12 @@ intel_icd = custom_target(
   input : 'anv_icd.py',
   output : 'intel_icd. at 0@.json'.format(host_machine.cpu()),
   command : [
+    'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
     prog_python2, '@INPUT@',
     '--lib-path', join_paths(get_option('prefix'), get_option('libdir')),
     '--out', '@OUTPUT@',
   ],
-  depend_files : anv_extensions_py,
+  depend_files : [anv_extensions_py, vk_api_generators_py],
   build_by_default : true,
   install_dir : with_vulkan_icd_dir,
   install : true,
@@ -73,10 +77,11 @@ dev_icd = custom_target(
   input : 'anv_icd.py',
   output : 'dev_icd. at 0@.json'.format(host_machine.cpu()),
   command : [
+    'env', 'PYTHONPATH=@0@'.format(join_paths(meson.source_root(), 'src/vulkan/util/')),
     prog_python2, '@INPUT@', '--lib-path', meson.current_build_dir(),
     '--out', '@OUTPUT@'
   ],
-  depend_files : files('anv_extensions.py'),
+  depend_files : [anv_extensions_py, vk_api_generators_py],
   build_by_default : true,
   install : false,
 )
diff --git a/src/vulkan/util/vk_extensions.py b/src/vulkan/util/vk_extensions.py
index 4f6667fe86c..79ae3af02ea 100644
--- a/src/vulkan/util/vk_extensions.py
+++ b/src/vulkan/util/vk_extensions.py
@@ -82,11 +82,12 @@ class VkVersion:
         patch = self.patch if self.patch is not None else 0
         return (self.major << 22) | (self.minor << 12) | patch
 
-    def __cmp__(self, other):
+    def __gt__(self, other):
         # If only one of them has a patch version, "ignore" it by making
         # other's patch version match self.
         if (self.patch is None) != (other.patch is None):
             other = copy.copy(other)
             other.patch = self.patch
 
-        return self.__int_ver().__cmp__(other.__int_ver())
+        return self.__int_ver() > other.__int_ver()
+
-- 
2.18.0



More information about the mesa-dev mailing list