}
}
-static void loader_add_instance_extensions(
+static VkResult loader_add_instance_extensions(
const struct loader_instance *inst,
const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
const char *lib_name, struct loader_extension_list *ext_list) {
uint32_t i, count = 0;
VkExtensionProperties *ext_props;
- VkResult res;
+ VkResult res = VK_SUCCESS;
if (!fp_get_props) {
/* No EnumerateInstanceExtensionProperties defined */
- return;
+ goto out;
}
res = fp_get_props(NULL, &count, NULL);
if (res != VK_SUCCESS) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"Error getting Instance extension count from %s", lib_name);
- return;
+ goto out;
}
if (count == 0) {
/* No ExtensionProperties to report */
- return;
+ goto out;
}
ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
if (res != VK_SUCCESS) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"Error getting Instance extensions from %s", lib_name);
- return;
+ goto out;
}
for (i = 0; i < count; i++) {
loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
"Instance Extension: %s (%s) version %s",
ext_props[i].extensionName, lib_name, spec_version);
- loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+ res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Failed to add %s to Instance extension list",
+ lib_name);
+ goto out;
+ }
}
}
-
- return;
+out:
+ return res;
}
/*
VkResult res;
uint32_t i;
- if (!loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
- sizeof(VkExtensionProperties))) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
+ sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ return res;
}
for (i = 0; i < count; i++) {
return VK_SUCCESS;
}
-bool loader_init_generic_list(const struct loader_instance *inst,
+VkResult loader_init_generic_list(const struct loader_instance *inst,
struct loader_generic_list *list_info,
size_t element_size) {
list_info->capacity = 32 * element_size;
list_info->list = loader_instance_heap_alloc(
inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (list_info->list == NULL) {
- return false;
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
}
memset(list_info->list, 0, list_info->capacity);
list_info->count = 0;
- return true;
+ return VK_SUCCESS;
}
void loader_destroy_generic_list(const struct loader_instance *inst,
const VkExtensionProperties *cur_ext;
if (ext_list->list == NULL || ext_list->capacity == 0) {
- loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
+ VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ return res;
+ }
}
- if (ext_list->list == NULL)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
-
for (i = 0; i < prop_list_count; i++) {
cur_ext = &props[i];
uint32_t entry_count, char **entrys) {
uint32_t idx;
if (ext_list->list == NULL || ext_list->capacity == 0) {
- loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
- sizeof(struct loader_dev_ext_props));
+ VkResult res = loader_init_generic_list(
+ inst, (struct loader_generic_list *)ext_list,
+ sizeof(struct loader_dev_ext_props));
+ if (VK_SUCCESS != res) {
+ return res;
+ }
}
- if (ext_list->list == NULL)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
-
// look for duplicates
if (has_vk_dev_ext_property(props, ext_list)) {
return VK_SUCCESS;
return NULL;
}
-
/*
* For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
* the extension must provide two entry points for the loader to use:
* linked directly with the loader.
*/
-void loader_get_icd_loader_instance_extensions(
+VkResult loader_get_icd_loader_instance_extensions(
const struct loader_instance *inst, struct loader_icd_libs *icd_libs,
struct loader_extension_list *inst_exts) {
struct loader_extension_list icd_exts;
+ VkResult res = VK_SUCCESS;
+
loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
"Build ICD instance extension list");
+
// traverse scanned icd list adding non-duplicate extensions to the list
for (uint32_t i = 0; i < icd_libs->count; i++) {
- loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts,
- sizeof(VkExtensionProperties));
- loader_add_instance_extensions(
+ res = loader_init_generic_list(inst,
+ (struct loader_generic_list *)&icd_exts,
+ sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = loader_add_instance_extensions(
inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
icd_libs->list[i].lib_name, &icd_exts);
- loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list);
+ if (VK_SUCCESS == res) {
+ res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count,
+ icd_exts.list);
+ }
loader_destroy_generic_list(inst,
(struct loader_generic_list *)&icd_exts);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
};
// Traverse loader's extensions, adding non-duplicate extensions to the list
debug_report_add_instance_extensions(inst, inst_exts);
+
+out:
+ return res;
}
struct loader_icd *loader_get_icd_and_device(const VkDevice device,
return err;
}
-static void loader_scanned_icd_add(const struct loader_instance *inst,
- struct loader_icd_libs *icd_libs,
- const char *filename, uint32_t api_version) {
+static VkResult loader_scanned_icd_add(const struct loader_instance *inst,
+ struct loader_icd_libs *icd_libs,
+ const char *filename,
+ uint32_t api_version) {
loader_platform_dl_handle handle;
PFN_vkCreateInstance fp_create_inst;
PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version;
struct loader_scanned_icds *new_node;
uint32_t interface_vers;
+ VkResult res = VK_SUCCESS;
/* TODO implement smarter opening/closing of libraries. For now this
* function leaves libraries open and the scanned_icd_clear closes them */
if (!handle) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
loader_platform_open_library_error(filename));
- return;
+ goto out;
}
// Get and settle on an ICD interface version
"ICD (%s) doesn't support interface version compatible"
"with loader, skip this ICD %s",
filename);
- return;
+ goto out;
}
fp_get_proc_addr =
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
loader_platform_get_proc_address_error(
"vk_icdGetInstanceProcAddr"));
- return;
+ goto out;
} else {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"Using deprecated ICD interface of "
"Couldn't get vkCreateInstance via dlsym/loadlibrary "
"for ICD %s",
filename);
- return;
+ goto out;
}
fp_get_inst_ext_props = loader_platform_get_proc_address(
handle, "vkEnumerateInstanceExtensionProperties");
"Couldn't get vkEnumerateInstanceExtensionProperties "
"via dlsym/loadlibrary for ICD %s",
filename);
- return;
+ goto out;
}
} else {
// Use newer interface version 1 or later
"Couldn't get vkCreateInstance via "
"vk_icdGetInstanceProcAddr for ICD %s",
filename);
- return;
+ goto out;
}
fp_get_inst_ext_props =
(PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(
"Couldn't get vkEnumerateInstanceExtensionProperties "
"via vk_icdGetInstanceProcAddr for ICD %s",
filename);
- return;
+ goto out;
}
}
inst, icd_libs->list, icd_libs->capacity, icd_libs->capacity * 2,
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == icd_libs->list) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"realloc failed on icd library list");
- return;
+ goto out;
}
// double capacity
icd_libs->capacity *= 2;
new_node->lib_name = (char *)loader_instance_heap_alloc(
inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == new_node->lib_name) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"Out of memory can't add icd");
- return;
+ goto out;
}
strcpy(new_node->lib_name, filename);
icd_libs->count++;
+
+out:
+
+ return res;
}
static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst,
* A pointer to a cJSON object representing the JSON parse tree.
* This returned buffer should be freed by caller.
*/
-static cJSON *loader_get_json(const struct loader_instance *inst,
- const char *filename) {
- FILE *file;
+static VkResult loader_get_json(const struct loader_instance *inst,
+ const char *filename, cJSON **json) {
+ FILE *file = NULL;
char *json_buf;
- cJSON *json;
size_t len;
+ VkResult res = VK_SUCCESS;
+
+ if (NULL == json) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ *json = NULL;
+
file = fopen(filename, "rb");
if (!file) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"Couldn't open JSON file %s", filename);
- return NULL;
+ goto out;
}
fseek(file, 0, SEEK_END);
len = ftell(file);
fseek(file, 0, SEEK_SET);
json_buf = (char *)loader_stack_alloc(len + 1);
if (json_buf == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"Out of memory can't get JSON file");
- fclose(file);
- return NULL;
+ goto out;
}
if (fread(json_buf, sizeof(char), len, file) != len) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"fread failed can't get JSON file");
- fclose(file);
- return NULL;
+ goto out;
}
- fclose(file);
json_buf[len] = '\0';
// parse text from file
- json = cJSON_Parse(json_buf);
- if (json == NULL)
+ *json = cJSON_Parse(json_buf);
+ if (*json == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"Can't parse JSON file %s", filename);
- return json;
+ goto out;
+ }
+
+out:
+ if (NULL != file) {
+ fclose(file);
+ }
+
+ return res;
}
/**
VkResult res = VK_SUCCESS;
bool lockedMutex = false;
cJSON *json = NULL;
+ uint32_t num_good_icds = 0;
memset(&manifest_files, 0, sizeof(struct loader_manifest_files));
continue;
}
- json = loader_get_json(inst, file_str);
- if (!json) {
+ res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ break;
+ } else if (VK_SUCCESS != res || NULL == json) {
continue;
}
+
cJSON *item, *itemICD;
item = cJSON_GetObjectItem(json, "file_format_version");
if (item == NULL) {
- res = VK_ERROR_INITIALIZATION_FAILED;
- goto out;
+ if (num_good_icds == 0) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ }
+ continue;
}
char *file_vers = cJSON_Print(item);
if (NULL == file_vers) {
// Only reason the print can fail is if there was an allocation
// issue
- res = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto out;
+ if (num_good_icds == 0) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ continue;
}
loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
"Found manifest file %s, version %s", file_str, file_vers);
"Can't find \"library_path\" in ICD JSON file "
"%s, skipping",
file_str);
+ if (num_good_icds == 0) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
cJSON_Free(temp);
cJSON_Delete(json);
json = NULL;
// strip out extra quotes
temp[strlen(temp) - 1] = '\0';
char *library_path = loader_stack_alloc(strlen(temp) + 1);
+ if (NULL == library_path) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Can't allocate space for \"library_path\" in ICD "
+ "JSON file %s, skipping",
+ file_str);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ cJSON_Free(temp);
+ cJSON_Delete(json);
+ json = NULL;
+ goto out;
+ }
strcpy(library_path, &temp[1]);
cJSON_Free(temp);
- if (!library_path || strlen(library_path) == 0) {
+ if (strlen(library_path) == 0) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"Can't find \"library_path\" in ICD JSON file "
"%s, skipping",
vers = loader_make_version(temp);
cJSON_Free(temp);
}
- loader_scanned_icd_add(inst, icds, fullpath, vers);
+ res = loader_scanned_icd_add(inst, icds, fullpath, vers);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ num_good_icds++;
} else {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"Can't find \"library_path\" object in ICD JSON "
continue;
// parse file into JSON struct
- json = loader_get_json(inst, file_str);
- if (!json) {
+ VkResult res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ break;
+ } else if (VK_SUCCESS != res || NULL == json) {
continue;
}
}
// parse file into JSON struct
- json = loader_get_json(inst, file_str);
- if (!json) {
+ res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ break;
+ } else if (VK_SUCCESS != res || NULL == json) {
continue;
}
filtered_extension_names =
loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
if (!filtered_extension_names) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
}
icd_create_info.ppEnabledExtensionNames =
(const char *const *)filtered_extension_names;
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 (NULL == icd) {
- while (NULL != ptr_instance->icds) {
- icd = ptr_instance->icds;
- ptr_instance->icds = icd->next;
- icd->DestroyInstance(icd->instance, pAllocator);
- loader_icd_destroy(ptr_instance, icd, pAllocator);
- }
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
}
icd_create_info.enabledExtensionCount = 0;
struct loader_extension_list icd_exts;
"Build ICD instance extension list");
// traverse scanned icd list adding non-duplicate extensions to the
// list
- loader_init_generic_list(ptr_instance,
+ res = loader_init_generic_list(ptr_instance,
(struct loader_generic_list *)&icd_exts,
sizeof(VkExtensionProperties));
- loader_add_instance_extensions(
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ // If out of memory, bail immediately.
+ goto out;
+ } else if (VK_SUCCESS != res) {
+ // Keep trying if there was some other error.
+ continue;
+ }
+
+ res = loader_add_instance_extensions(
ptr_instance,
icd->this_icd_lib->EnumerateInstanceExtensionProperties,
icd->this_icd_lib->lib_name, &icd_exts);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ // If out of memory, bail immediately.
+ goto out;
+ } else if (VK_SUCCESS != res) {
+ // Keep trying if there was some other error.
+ continue;
+ }
for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) {
prop = get_extension_property(
res = ptr_instance->icd_libs.list[i].CreateInstance(
&icd_create_info, pAllocator, &(icd->instance));
- if (res == VK_SUCCESS)
- success = loader_icd_init_entrys(
- icd, icd->instance,
- ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ // If out of memory, bail immediately.
+ goto out;
+ } else if (VK_SUCCESS != res) {
+ // Keep trying if there was some other error.
+ loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "ICD ignored: failed to CreateInstance in ICD %d", i);
+ continue;
+ }
- if (res != VK_SUCCESS || !success) {
- ptr_instance->icds = ptr_instance->icds->next;
- loader_icd_destroy(ptr_instance, icd, pAllocator);
- loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ if (!loader_icd_init_entrys(
+ icd, icd->instance,
+ ptr_instance->icd_libs.list[i].GetInstanceProcAddr)) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"ICD ignored: failed to CreateInstance and find "
"entrypoints with ICD");
+ continue;
}
}
* from it's initial value, the loader was unable to find
* a suitable ICD.
*/
- if (ptr_instance->icds == NULL) {
- if (res == VK_SUCCESS) {
- return VK_ERROR_INCOMPATIBLE_DRIVER;
- } else {
- return res;
+ if (VK_SUCCESS == res && ptr_instance->icds == NULL) {
+ res = VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+out:
+
+ if (VK_SUCCESS != res) {
+ while (NULL != ptr_instance->icds) {
+ icd = ptr_instance->icds;
+ ptr_instance->icds = icd->next;
+ if (NULL != icd->instance) {
+ icd->DestroyInstance(icd->instance, pAllocator);
+ }
+ loader_icd_destroy(ptr_instance, icd, pAllocator);
}
}
- return VK_SUCCESS;
+ return res;
}
VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(
(const char *const *)filtered_extension_names;
/* Get the physical device (ICD) extensions */
- if (!loader_init_generic_list(phys_dev->this_icd->this_instance,
+ res = loader_init_generic_list(phys_dev->this_icd->this_instance,
(struct loader_generic_list *)&icd_exts,
- sizeof(VkExtensionProperties))) {
- res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
goto out;
}
uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
struct loader_physical_device *phys_dev;
- struct loader_layer_list implicit_layer_list;
+ struct loader_layer_list implicit_layer_list = {0};
+ struct loader_extension_list all_exts = {0};
+ struct loader_extension_list icd_exts = {0};
assert(pLayerName == NULL || strlen(pLayerName) == 0);
/* get device extensions */
res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL,
&icd_ext_count, pProperties);
- if (res != VK_SUCCESS)
- return res;
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
- loader_init_layer_list(icd->this_instance, &implicit_layer_list);
+ if (!loader_init_layer_list(icd->this_instance, &implicit_layer_list)) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
loader_add_layer_implicit(
icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
* it depends on results of environment variables (which can change).
*/
if (pProperties != NULL) {
- struct loader_extension_list icd_exts;
/* initialize dev_extension list within the physicalDevice object */
res = loader_init_device_extensions(icd->this_instance, phys_dev,
icd_ext_count, pProperties,
&icd_exts);
- if (res != VK_SUCCESS)
- return res;
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
/* we need to determine which implicit layers are active,
* and then add their extensions. This can't be cached as
* it depends on results of environment variables (which can
* change).
*/
- struct loader_extension_list all_exts = {0};
- loader_add_to_ext_list(icd->this_instance, &all_exts, icd_exts.count,
- icd_exts.list);
+ res = loader_add_to_ext_list(icd->this_instance, &all_exts,
+ icd_exts.count, icd_exts.list);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
loader_add_layer_implicit(
icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
for (uint32_t j = 0;
j < implicit_layer_list.list[i].device_extension_list.count;
j++) {
- loader_add_to_ext_list(icd->this_instance, &all_exts, 1,
- &implicit_layer_list.list[i]
- .device_extension_list.list[j]
- .props);
+ res = loader_add_to_ext_list(icd->this_instance, &all_exts, 1,
+ &implicit_layer_list.list[i]
+ .device_extension_list.list[j]
+ .props);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
}
}
uint32_t capacity = *pPropertyCount;
} else {
*pPropertyCount = all_exts.count;
}
- loader_destroy_generic_list(icd->this_instance,
- (struct loader_generic_list *)&all_exts);
- loader_destroy_generic_list(icd->this_instance,
- (struct loader_generic_list *)&icd_exts);
} else {
/* just return the count; need to add in the count of implicit layer
* extensions
res = VK_SUCCESS;
}
- loader_destroy_generic_list(
- icd->this_instance, (struct loader_generic_list *)&implicit_layer_list);
+out:
+
+ if (NULL != implicit_layer_list.list) {
+ loader_destroy_generic_list(
+ icd->this_instance,
+ (struct loader_generic_list *)&implicit_layer_list);
+ }
+ if (NULL != all_exts.list) {
+ loader_destroy_generic_list(icd->this_instance,
+ (struct loader_generic_list *)&all_exts);
+ }
+ if (NULL != icd_exts.list) {
+ loader_destroy_generic_list(icd->this_instance,
+ (struct loader_generic_list *)&icd_exts);
+ }
+
return res;
}