loader: Find ICD entrypoints via vk_icdGetInstanceProcAddr first in ICD library
authorJon Ashburn <jon@lunarg.com>
Thu, 7 Jan 2016 16:44:27 +0000 (09:44 -0700)
committerJon Ashburn <jon@lunarg.com>
Thu, 7 Jan 2016 17:06:00 +0000 (10:06 -0700)
Also support prior method (now deprecated) of looking up vkGetInstanceProcAddr.
But now other globals are gotten from GetInstanceProcAddr calls.

loader/README.md
loader/loader.c

index 24f9558..81e2137 100644 (file)
@@ -1,8 +1,8 @@
 # Loader Description 
 
 ## Overview
-The Loader implements the main VK library (e.g. "vulkan.dll" on Windows and
-"libvulkan.so" on Linux).  It handles layer management and driver management.  The
+The Loader implements the main VK library (e.g. "vulkan-1.dll" on Windows and
+"libvulkan-1.so" on Linux).  It handles layer management and driver management.  The
 loader fully supports multi-gpu operation.  As part of this, it dispatches API
 calls to the correct driver, and to the correct layers, based on the GPU object
 selected by the application.
@@ -24,10 +24,17 @@ See file LinuxICDs.txt  and WindowsICDs.txt for description of how the loader
 finds ICD driver libraries.
 
 ## Interface to driver (ICD)
-- vkCreateInstance exported
-- vkEnumerateInstanceExtensionProperties exported
-- vkGetDeviceProcAddr exported and returns valid function pointers for all the VK API entrypoints
-- vkGetInstanceProcAddr exported and returns valid function pointers for all the VK API entrypoints
+Currently two supported methods of the loader finding ICD entry points are supported:
+1) Recommended
+- vk_icdGetInstanceProcAddr exported in the ICD library and returns valid function pointers for all the VK API entrypoints
+  both core entry points and any instance or device entrypoints
+- all other Vulkan entrypoints either NOT exported from the ICD library or else will not use the official Vulkan function names
+ if they are exported. (NOTE: this requirement is for ICD libraries that include other functionality (such as OpenGL library)
+ and thus could be loaded prior to when the Vulkan loader library is loaded by the app.  Thus the ICD library exported Vulkan symbols must not
+ clash with the loader's exported Vulkan symbols).
+ 2) Deprecated
+ - vkGetInstanceProcAddr exported in the ICD library and returns valid function pointers for all the VK API entrypoints
 - WSI surface extensions (vk_KHR_*surface) handling:
   1. Loader handles the vkCreate*SurfaceKHR() and vkDestroySurfaceKHR()  functions including creating/destroying the VkSurfaceKHR object
   2. VkSurfaceKHR objects have the underlying structure (VKIcdSurface*) as defined in include/vulkan/vk_icd.h
@@ -63,7 +70,12 @@ finds ICD driver libraries.
 ```
 
 Additional Notes:
-
+- loader will filter out extensions requested in vkCreateInstance  and vkCreateDevice
+  before calling into the ICD;
+  Filtering will be of extensions advertised by entities (eg layers) different from the ICD in question
+- loader will not call ICD for vkEnumerate*LayerProperties() as layer properties are obtained from
+  the layer libraries and ICD files.
+- loader will not call ICD for vkEnumerate*ExtensionProperties(pLayerName != NULL) 
 - The ICD may or may not implement a dispatch table.
 - ICD entrypoints can be named anything including the offcial vk name such as vkCreateDevice().  However, beware of interposing by dynamic OS library loaders if the offical names are used.  On Linux, if offical names are used, the ICD library must be linked with -Bsymbolic.
 
index 3b29efb..79ed84b 100644 (file)
@@ -1262,7 +1262,7 @@ static void loader_scanned_icd_add(
 {
     loader_platform_dl_handle handle;
     PFN_vkCreateInstance fp_create_inst;
-    PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
+    PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
     PFN_vkGetInstanceProcAddr fp_get_proc_addr;
     struct loader_scanned_icds *new_node;
 
@@ -1275,19 +1275,26 @@ static void loader_scanned_icd_add(
         return;
     }
 
-#define LOOKUP_LD(func_ptr, func) do {                            \
-    func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
-    if (!func_ptr) {                                           \
-        loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_get_proc_address_error("vk" #func)); \
-        return;                                                \
-    }                                                          \
-} while (0)
-
-    LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
-    LOOKUP_LD(fp_create_inst, CreateInstance);
-    LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
-
-#undef LOOKUP_LD
+    fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
+    if (!fp_get_proc_addr) {
+        fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
+        if (!fp_get_proc_addr) {
+            loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_get_proc_address_error("vk_icdGetInstanceProcAddr"));
+            return;
+        } else {
+            loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Using deprecated ICD interface of vkGetInstanceProcAddr instead of vk_icdGetInstanceProcAddr");
+        }
+    }
+    fp_create_inst = (PFN_vkCreateInstance) fp_get_proc_addr(NULL, "vkCreateInstance");
+    if (!fp_create_inst) {
+        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkCreateInstance via vkGetInstanceProcAddr from ICD");
+        return;
+    }
+    fp_get_inst_ext_props = (PFN_vkEnumerateInstanceExtensionProperties) fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties");
+    if (!fp_get_inst_ext_props) {
+        loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkEnumerateInstanceExtensionProperties via vkGetInstanceProcAddr from ICD");
+        return;
+    }
 
     // check for enough capacity
     if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
@@ -1305,8 +1312,8 @@ static void loader_scanned_icd_add(
     new_node->handle = handle;
     new_node->api_version = api_version;
     new_node->GetInstanceProcAddr = fp_get_proc_addr;
+    new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
     new_node->CreateInstance = fp_create_inst;
-    new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
 
     new_node->lib_name = (char *) loader_heap_alloc(inst,
                                             strlen(filename) + 1,