Module: Mesa
Branch: master
Commit: 1f79d986afa5a92d7c7d85882714c7feeddc5d14
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=1f79d986afa5a92d7c7d85882714c7feeddc5d14

Author: Jason Ekstrand <[email protected]>
Date:   Tue Jan 16 18:08:09 2018 -0800

anv: Only advertise enabled entrypoints

The Vulkan spec annoyingly requires us to track what core version and
what all extensions are enabled and only advertise those entrypoints.
Any call to vkGet*ProcAddr for an entrypoint for an extension the client
has not explicitly enabled is supposed to return NULL.

Reviewed-by: Samuel Iglesias Gonsálvez <[email protected]>

---

 src/intel/vulkan/anv_device.c           | 26 +++++++++++++++--
 src/intel/vulkan/anv_entrypoints_gen.py | 49 +++++++++++++++++++++++++++++++--
 src/intel/vulkan/anv_private.h          |  5 ++++
 3 files changed, 74 insertions(+), 6 deletions(-)

diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index e70ddf1799..8fcc73eaba 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -574,7 +574,19 @@ VkResult anv_CreateInstance(
 
    instance->apiVersion = client_version;
    instance->enabled_extensions = enabled_extensions;
-   instance->dispatch = anv_dispatch_table;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(instance->dispatch.entrypoints); i++) {
+      /* Vulkan requires that entrypoints for extensions which have not been
+       * enabled must not be advertised.
+       */
+      if (!anv_entrypoint_is_enabled(i, instance->apiVersion,
+                                     &instance->enabled_extensions, NULL)) {
+         instance->dispatch.entrypoints[i] = NULL;
+      } else {
+         instance->dispatch.entrypoints[i] = anv_dispatch_table.entrypoints[i];
+      }
+   }
+
    instance->physicalDeviceCount = -1;
 
    result = vk_debug_report_instance_init(&instance->debug_report_callbacks);
@@ -1289,10 +1301,18 @@ anv_device_init_dispatch(struct anv_device *device)
    }
 
    for (unsigned i = 0; i < ARRAY_SIZE(device->dispatch.entrypoints); i++) {
-      if (genX_table->entrypoints[i])
+      /* Vulkan requires that entrypoints for extensions which have not been
+       * enabled must not be advertised.
+       */
+      if (!anv_entrypoint_is_enabled(i, device->instance->apiVersion,
+                                     &device->instance->enabled_extensions,
+                                     &device->enabled_extensions)) {
+         device->dispatch.entrypoints[i] = NULL;
+      } else if (genX_table->entrypoints[i]) {
          device->dispatch.entrypoints[i] = genX_table->entrypoints[i];
-      else
+      } else {
          device->dispatch.entrypoints[i] = anv_dispatch_table.entrypoints[i];
+      }
    }
 }
 
diff --git a/src/intel/vulkan/anv_entrypoints_gen.py 
b/src/intel/vulkan/anv_entrypoints_gen.py
index ccbc2ffb5e..32359b6b71 100644
--- a/src/intel/vulkan/anv_entrypoints_gen.py
+++ b/src/intel/vulkan/anv_entrypoints_gen.py
@@ -164,6 +164,36 @@ static const struct anv_entrypoint entrypoints[] = {
   };
 % 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}:
+   % if e.core_version:
+      return ${e.core_version.c_vk_version()} <= core_version;
+   % elif e.extension:
+      % if e.extension.type == 'instance':
+      return instance->${e.extension.name[3:]};
+      % else:
+      return !device || device->${e.extension.name[3:]};
+      % endif
+   % else:
+      return true;
+   % endif
+% endfor
+   default:
+      return false;
+   }
+}
+
 static void * __attribute__ ((noinline))
 anv_resolve_entrypoint(const struct gen_device_info *devinfo, uint32_t index)
 {
@@ -279,6 +309,9 @@ class Entrypoint(object):
         self.guard = guard
         self.enabled = False
         self.num = None
+        # Extensions which require this entrypoint
+        self.core_version = None
+        self.extension = None
 
     def prefixed_name(self, prefix):
         assert self.name.startswith('vk')
@@ -303,24 +336,34 @@ def get_entrypoints(doc, entrypoints_to_defines, 
start_index):
     enabled_commands = set()
     for feature in doc.findall('./feature'):
         assert feature.attrib['api'] == 'vulkan'
-        if VkVersion(feature.attrib['number']) > MAX_API_VERSION:
+        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 = set(ext.name for ext in EXTENSIONS)
+    supported_exts = dict((ext.name, ext) for ext in EXTENSIONS)
     for extension in doc.findall('.extensions/extension'):
-        if extension.attrib['name'] not in supported:
+        ext_name = extension.attrib['name']
+        if ext_name not in supported_exts:
             continue
 
         if extension.attrib['supported'] != 'vulkan':
             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
+            assert e.extension is None
+            e.extension = ext
 
     return [e for e in entrypoints.itervalues() if e.enabled]
 
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 45dbcfdcb6..a8b3820ffe 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2820,6 +2820,11 @@ struct anv_query_pool {
 
 int anv_get_entrypoint_index(const char *name);
 
+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);
+
 void *anv_lookup_entrypoint(const struct gen_device_info *devinfo,
                             const char *name);
 

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to