loader: Make the ICD library scan happen as needed rather than once
Add a one time loader init routine also since this was done by ICD scan.
Add icd library struct to instance object.
diff --git a/loader/loader.c b/loader/loader.c
index d2c6720..abb834f 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -105,7 +105,7 @@
.DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
};
-LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
+LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
void* loader_heap_alloc(
struct loader_instance *instance,
@@ -794,22 +794,22 @@
* linked directly with the loader.
*/
-void loader_get_icd_loader_instance_extensions(struct loader_extension_list *inst_exts)
+void loader_get_icd_loader_instance_extensions(
+ struct loader_icd_libs *icd_libs,
+ struct loader_extension_list *inst_exts)
{
- struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
struct loader_extension_list icd_exts;
loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
// traverse scanned icd list adding non-duplicate extensions to the list
- while (icd_list != NULL) {
+ for (uint32_t i = 0; i < icd_libs->count; i++) {
loader_init_ext_list(&icd_exts);
- loader_add_global_extensions(icd_list->GetGlobalExtensionProperties,
- icd_list->lib_name,
+ loader_add_global_extensions(icd_libs->list[i].GetGlobalExtensionProperties,
+ icd_libs->list[i].lib_name,
&icd_exts);
loader_add_to_ext_list(inst_exts,
icd_exts.count,
icd_exts.list);
loader_destroy_ext_list(&icd_exts);
- icd_list = icd_list->next;
};
// Traverse loader's extensions, adding non-duplicate extensions to the list
@@ -931,7 +931,31 @@
return icd;
}
-static void loader_scanned_icd_add(const char *filename)
+void loader_scanned_icd_clear(struct loader_icd_libs *icd_libs)
+{
+ if (icd_libs->capacity == 0)
+ return;
+ for (uint32_t i = 0; i < icd_libs->count; i++) {
+ loader_platform_close_library(icd_libs->list[i].handle);
+ free(icd_libs->list[i].lib_name);
+ }
+ free(icd_libs->list);
+ icd_libs->capacity = 0;
+ icd_libs->count = 0;
+ icd_libs->list = NULL;
+}
+
+static void loader_scanned_icd_init(struct loader_icd_libs *icd_libs)
+{
+ loader_scanned_icd_clear(icd_libs);
+ icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
+ icd_libs->list = malloc(icd_libs->capacity);
+
+}
+
+static void loader_scanned_icd_add(
+ struct loader_icd_libs *icd_libs,
+ const char *filename)
{
loader_platform_dl_handle handle;
PFN_vkCreateInstance fp_create_inst;
@@ -939,6 +963,8 @@
PFN_vkGetInstanceProcAddr fp_get_proc_addr;
struct loader_scanned_icds *new_node;
+ /* TODO implement ref counting of libraries, for now this function leaves
+ libraries open and the scanned_icd_clear closes them */
// Used to call: dlopen(filename, RTLD_LAZY);
handle = loader_platform_open_library(filename);
if (!handle) {
@@ -960,28 +986,26 @@
#undef LOOKUP_LD
- new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
- + strlen(filename) + 1);
- if (!new_node) {
- loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
- return;
+ // check for enough capacity
+ if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
+ // double capacity
+ icd_libs->capacity *= 2;
+ icd_libs->list = realloc(icd_libs->list, icd_libs->capacity);
}
+ new_node = &(icd_libs->list[icd_libs->count]);
new_node->handle = handle;
new_node->GetInstanceProcAddr = fp_get_proc_addr;
new_node->CreateInstance = fp_create_inst;
new_node->GetGlobalExtensionProperties = fp_get_global_ext_props;
- new_node->next = loader.scanned_icd_list;
- new_node->lib_name = (char *) (new_node + 1);
+ new_node->lib_name = (char *) malloc(strlen(filename) + 1);
if (!new_node->lib_name) {
loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
return;
}
strcpy(new_node->lib_name, filename);
-
- loader.scanned_icd_list = new_node;
-
+ icd_libs->count++;
}
static bool loader_icd_init_entrys(struct loader_icd *icd,
@@ -1067,6 +1091,15 @@
}
}
+void loader_initialize(void)
+{
+ // initialize a mutex
+ loader_platform_thread_create_mutex(&loader_lock);
+
+ // initialize logging
+ loader_debug_init();
+}
+
struct loader_manifest_files {
uint32_t count;
char **filename_list;
@@ -1598,6 +1631,15 @@
return;
}
+void loader_init_icd_lib_list()
+{
+
+}
+
+void loader_destroy_icd_lib_list()
+{
+
+}
/**
* Try to find the Vulkan ICD driver(s).
*
@@ -1607,20 +1649,14 @@
* manifest files it finds the ICD libraries.
*
* \returns
- * void
+ * a list of icds that were discovered
*/
-void loader_icd_scan(void)
+void loader_icd_scan(struct loader_icd_libs *icds)
{
char *file_str;
struct loader_manifest_files manifest_files;
-
- // convenient place to initialize a mutex
- loader_platform_thread_create_mutex(&loader_lock);
-
- // convenient place to initialize logging
- loader_debug_init();
-
+ loader_scanned_icd_init(icds);
// Get a list of manifest files for ICDs
loader_get_manifest_files("VK_ICD_FILENAMES", false, DEFAULT_VK_DRIVERS_INFO,
&manifest_files);
@@ -1654,7 +1690,7 @@
char *dir = def_dir;
// Print out the paths being searched if debugging is enabled
- loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s at %s\n", icd_file, dir);
+ loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", icd_file, dir);
// strip off extra quotes
if (icd_filename[strlen(icd_filename) - 1] == '"')
@@ -1664,9 +1700,9 @@
#if defined(__linux__)
char full_path[2048];
loader_get_fullpath(icd_filename, dir, sizeof(full_path), full_path);
- loader_scanned_icd_add(full_path);
+ loader_scanned_icd_add(icds, full_path);
#else // WIN32
- loader_scanned_icd_add(icd_filename);
+ loader_scanned_icd_add(icds, icd_filename);
#endif
free(icd_file);
}
@@ -2329,7 +2365,6 @@
VkInstance* pInstance)
{
struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
- struct loader_scanned_icds *scanned_icds;
struct loader_icd *icd;
VkExtensionProperties *prop;
char **filtered_extension_names = NULL;
@@ -2357,9 +2392,8 @@
}
icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
- scanned_icds = loader.scanned_icd_list;
- while (scanned_icds) {
- icd = loader_icd_add(ptr_instance, scanned_icds);
+ for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
+ icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
if (icd) {
icd_create_info.extensionCount = 0;
for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
@@ -2371,12 +2405,12 @@
}
}
- res = scanned_icds->CreateInstance(&icd_create_info,
+ res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
&(icd->instance));
success = loader_icd_init_entrys(
icd,
icd->instance,
- scanned_icds->GetInstanceProcAddr);
+ ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
if (res != VK_SUCCESS || !success)
{
@@ -2387,7 +2421,6 @@
"ICD ignored: failed to CreateInstance and find entrypoints with ICD");
}
}
- scanned_icds = scanned_icds->next;
}
/*
@@ -2448,7 +2481,7 @@
icds = next_icd;
}
-
+ loader_scanned_icd_clear(&ptr_instance->icd_libs);
loader_destroy_ext_list(&ptr_instance->ext_list);
return VK_SUCCESS;
}
@@ -2862,6 +2895,7 @@
struct loader_extension_list *global_ext_list;
struct loader_layer_list instance_layers;
struct loader_extension_list icd_extensions;
+ struct loader_icd_libs icd_libs;
uint32_t copy_size;
if (pCount == NULL) {
@@ -2869,8 +2903,7 @@
}
memset(&icd_extensions, 0, sizeof(icd_extensions));
- /* Scan/discover all ICD libraries in a single-threaded manner */
- loader_platform_thread_once(&once_icd, loader_icd_scan);
+ loader_platform_thread_once(&once_init, loader_initialize);
//TODO do we still need to lock? for loader.global_extensions
loader_platform_thread_lock_mutex(&loader_lock);
@@ -2886,8 +2919,12 @@
}
}
else {
+ /* Scan/discover all ICD libraries */
+ memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
+ loader_icd_scan(&icd_libs);
/* get extensions from all ICD's, merge so no duplicates */
- loader_get_icd_loader_instance_extensions(&icd_extensions);
+ loader_get_icd_loader_instance_extensions(&icd_libs, &icd_extensions);
+ loader_scanned_icd_clear(&icd_libs);
global_ext_list = &icd_extensions;
}
@@ -2927,8 +2964,7 @@
struct loader_layer_list instance_layer_list;
- /* Scan/discover all ICD libraries in a single-threaded manner */
- loader_platform_thread_once(&once_icd, loader_icd_scan);
+ loader_platform_thread_once(&once_init, loader_initialize);
uint32_t copy_size;
diff --git a/loader/loader.h b/loader/loader.h
index 66eba22..2b4e491 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -145,14 +145,21 @@
PFN_vkGetPhysicalDeviceSurfaceSupportWSI GetPhysicalDeviceSurfaceSupportWSI;
/*
- * Fill in the cache of available global extensions that operate
- * with this physical device. This cache will be used to satisfy
+ * Fill in the cache of available device extensions from
+ * this physical device. This cache will be used to satisfy
* calls to GetPhysicalDeviceExtensionProperties
*/
struct loader_extension_list device_extension_cache[MAX_GPUS_PER_ICD];
struct loader_icd *next;
};
+/* per ICD library structure */
+struct loader_icd_libs {
+ size_t capacity;
+ uint32_t count;
+ struct loader_scanned_icds *list;
+};
+
/* per instance structure */
struct loader_instance {
VkLayerInstanceDispatchTable *disp; // must be first entry in structure
@@ -162,6 +169,7 @@
struct loader_icd *icds;
struct loader_instance *next;
struct loader_extension_list ext_list; // icds and loaders extensions
+ struct loader_icd_libs icd_libs;
/* TODO: Should keep track of application provided allocation functions */
struct loader_msg_callback_map_entry *icd_msg_callback_map;
@@ -178,14 +186,14 @@
struct loader_struct {
struct loader_instance *instances;
- struct loader_scanned_icds *scanned_icd_list;
unsigned int loaded_layer_lib_count;
struct loader_lib_info *loaded_layer_lib_list;
-
+ // TODO add ref counting of ICD libraries
char *layer_dirs;
// TODO use this struct loader_layer_library_list scanned_layer_libraries;
+ // TODO add list of icd libraries for ref counting them for closure
};
struct loader_scanned_icds {
@@ -195,8 +203,6 @@
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
PFN_vkCreateInstance CreateInstance;
PFN_vkGetGlobalExtensionProperties GetGlobalExtensionProperties;
- struct loader_scanned_icds *next;
-
};
static inline struct loader_instance *loader_instance(VkInstance instance) {
@@ -230,8 +236,7 @@
/* global variables used across files */
extern struct loader_struct loader;
-extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_icd);
-extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_exts);
+extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init);
extern loader_platform_thread_mutex loader_lock;
extern const VkLayerInstanceDispatchTable instance_disp;
@@ -322,6 +327,7 @@
VkDevice* pDevice);
/* helper function definitions */
+void loader_initialize(void);
bool has_vk_extension_property_array(
const VkExtensionProperties *vk_ext_prop,
const uint32_t count,
@@ -340,11 +346,14 @@
struct loader_layer_list *list,
uint32_t prop_list_count,
const struct loader_layer_properties *props);
-void loader_icd_scan(void);
+void loader_scanned_icd_clear(struct loader_icd_libs *icd_libs);
+void loader_icd_scan(struct loader_icd_libs *icds);
void loader_layer_scan(
struct loader_layer_list *instance_layers,
struct loader_layer_list *device_layers);
-void loader_get_icd_loader_instance_extensions(struct loader_extension_list *inst_exts);
+void loader_get_icd_loader_instance_extensions(
+ struct loader_icd_libs *icd_libs,
+ struct loader_extension_list *inst_exts);
struct loader_icd * loader_get_icd(
const VkPhysicalDevice gpu,
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 3c779c7..0b59373 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -42,12 +42,10 @@
VkInstance* pInstance)
{
struct loader_instance *ptr_instance = NULL;
-
VkResult res = VK_ERROR_INITIALIZATION_FAILED;
struct loader_layer_list instance_layer_list;
- /* Scan/discover all ICD libraries in a single-threaded manner */
- loader_platform_thread_once(&once_icd, loader_icd_scan);
+ loader_platform_thread_once(&once_init, loader_initialize);
/* Due to implicit layers might still need to get layer list even if
* layerCount == 0 and VK_INSTANCE_LAYERS is unset. For now always
@@ -91,10 +89,15 @@
ptr_instance->alloc_callbacks.pfnFree = pCreateInfo->pAllocCb->pfnFree;
}
+ /* Scan/discover all ICD libraries */
+ memset(&ptr_instance->icd_libs, 0, sizeof(ptr_instance->icd_libs));
+ loader_icd_scan(&ptr_instance->icd_libs);
+
/* get extensions from all ICD's, merge so no duplicates, then validate */
- loader_get_icd_loader_instance_extensions(&ptr_instance->ext_list);
+ loader_get_icd_loader_instance_extensions(&ptr_instance->icd_libs, &ptr_instance->ext_list);
res = loader_validate_instance_extensions(&ptr_instance->ext_list, &instance_layer_list, pCreateInfo);
if (res != VK_SUCCESS) {
+ loader_scanned_icd_clear(&ptr_instance->icd_libs);
loader_destroy_ext_list(&ptr_instance->ext_list);
loader_platform_thread_unlock_mutex(&loader_lock);
loader_heap_free(ptr_instance, ptr_instance);
@@ -106,6 +109,7 @@
sizeof(VkLayerInstanceDispatchTable),
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (ptr_instance->disp == NULL) {
+ loader_scanned_icd_clear(&ptr_instance->icd_libs);
loader_destroy_ext_list(&ptr_instance->ext_list);
loader_platform_thread_unlock_mutex(&loader_lock);
loader_heap_free(ptr_instance, ptr_instance);
@@ -118,6 +122,7 @@
/* activate any layers on instance chain */
res = loader_enable_instance_layers(ptr_instance, pCreateInfo, &instance_layer_list);
if (res != VK_SUCCESS) {
+ loader_scanned_icd_clear(&ptr_instance->icd_libs);
loader_destroy_ext_list(&ptr_instance->ext_list);
loader.instances = ptr_instance->next;
loader_platform_thread_unlock_mutex(&loader_lock);