diff options
-rw-r--r-- | loader/gpa_helper.c | 2 | ||||
-rw-r--r-- | loader/loader.c | 17 | ||||
-rw-r--r-- | loader/unknown_function_handling.c | 126 | ||||
-rw-r--r-- | loader/unknown_function_handling.h | 6 |
4 files changed, 80 insertions, 71 deletions
diff --git a/loader/gpa_helper.c b/loader/gpa_helper.c index 13481ca69..2dea285fb 100644 --- a/loader/gpa_helper.c +++ b/loader/gpa_helper.c @@ -263,7 +263,7 @@ void *trampoline_get_proc_addr(struct loader_instance *inst, const char *funcNam if (NULL != addr) return addr; // Unknown device extensions - addr = loader_dev_ext_gpa(inst, funcName); + addr = loader_dev_ext_gpa_tramp(inst, funcName); return addr; } diff --git a/loader/loader.c b/loader/loader.c index 50e808142..6ff911053 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -3966,9 +3966,8 @@ static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_terminator return addr; } - // Get the terminator, but don't perform checking since it should already - // have been setup if we get here. - addr = loader_phys_dev_ext_gpa_term_no_check(loader_get_instance(inst), pName); + // Check if any drivers support the function, and if so, add it to the unknown function list + addr = loader_phys_dev_ext_gpa_term(loader_get_instance(inst), pName); if (NULL != addr) return addr; // Don't call down the chain, this would be an infinite loop @@ -4031,6 +4030,18 @@ static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_terminator(V return addr; } + // Check if it is an unknown physical device function, to see if any drivers support it. + addr = loader_phys_dev_ext_gpa_term(loader_get_instance(inst), pName); + if (addr) { + return addr; + } + + // Assume it is an unknown device function, check to see if any drivers support it. + addr = loader_dev_ext_gpa_term(loader_get_instance(inst), pName); + if (addr) { + return addr; + } + // Don't call down the chain, this would be an infinite loop loader_log(NULL, VULKAN_LOADER_DEBUG_BIT, 0, "loader_gpa_instance_terminator() unrecognized name %s", pName); return NULL; diff --git a/loader/unknown_function_handling.c b/loader/unknown_function_handling.c index 582c9ab3a..6f3cd13d8 100644 --- a/loader/unknown_function_handling.c +++ b/loader/unknown_function_handling.c @@ -118,13 +118,14 @@ void loader_free_dev_ext_table(struct loader_instance *inst) { * For a given entry point string (funcName), if an existing mapping is found the * trampoline address for that mapping is returned. * Otherwise, this unknown entry point has not been seen yet. - * Next check if a layer or ICD supports it. + * Next check if an ICD supports it, and if is_tramp is true, check if any layer + * supports it by calling down the chain. * If so then a new entry in the function name array is added and that trampoline * address for the new entry is returned. * NULL is returned if the function name array is full or if no discovered layer or * ICD returns a non-NULL GetProcAddr for it. */ -void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) { +void *loader_dev_ext_gpa_impl(struct loader_instance *inst, const char *funcName, bool is_tramp) { // Linearly look through already added functions to make sure we haven't seen it before // if we have, return the function at the index found for (uint32_t i = 0; i < inst->dev_ext_disp_function_count; i++) { @@ -133,12 +134,12 @@ void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) { } // Check if funcName is supported in either ICDs or a layer library - if (!loader_check_icds_for_dev_ext_address(inst, funcName) && - !loader_check_layer_list_for_dev_ext_address(&inst->app_activated_layer_list, funcName)) { - // if support found in layers continue on - return NULL; + if (!loader_check_icds_for_dev_ext_address(inst, funcName)) { + if (!is_tramp || !loader_check_layer_list_for_dev_ext_address(&inst->app_activated_layer_list, funcName)) { + // if support found in layers continue on + return NULL; + } } - if (inst->dev_ext_disp_function_count >= MAX_NUM_UNKNOWN_EXTS) { loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_dev_ext_gpa: Exhausted the unknown device function array!"); return NULL; @@ -160,6 +161,14 @@ void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) { return out_function; } +void *loader_dev_ext_gpa_tramp(struct loader_instance *inst, const char *funcName) { + return loader_dev_ext_gpa_impl(inst, funcName, true); +} + +void *loader_dev_ext_gpa_term(struct loader_instance *inst, const char *funcName) { + return loader_dev_ext_gpa_impl(inst, funcName, false); +} + // Physical Device function handling bool loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) { @@ -223,39 +232,45 @@ void *loader_phys_dev_ext_gpa_impl(struct loader_instance *inst, const char *fun } } + bool has_found = false; + uint32_t new_function_index = 0; // Linearly look through already added functions to make sure we haven't seen it before // if we have, return the function at the index found for (uint32_t i = 0; i < inst->phys_dev_ext_disp_function_count; i++) { if (inst->phys_dev_ext_disp_functions[i] && !strcmp(inst->phys_dev_ext_disp_functions[i], funcName)) { - if (is_tramp) { - return loader_get_phys_dev_ext_tramp(i); - } else { - return loader_get_phys_dev_ext_termin(i); - } + has_found = true; + new_function_index = i; + break; } } - if (inst->phys_dev_ext_disp_function_count >= MAX_NUM_UNKNOWN_EXTS) { - loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_dev_ext_gpa: Exhausted the unknown physical device function array!"); - return NULL; - } - loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, - "loader_phys_dev_ext_gpa: Adding unknown physical function %s to internal store at index %u", funcName, - inst->phys_dev_ext_disp_function_count); + // A never before seen function name, store it in the array + if (!has_found) { + if (inst->phys_dev_ext_disp_function_count >= MAX_NUM_UNKNOWN_EXTS) { + loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, + "loader_dev_ext_gpa: Exhausted the unknown physical device function array!"); + return NULL; + } - // add found function to phys_dev_ext_disp_functions; - size_t funcName_len = strlen(funcName) + 1; - inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count] = - (char *)loader_instance_heap_alloc(inst, funcName_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (NULL == inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count]) { - // failed to allocate memory, return NULL - return NULL; - } - strncpy(inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count], funcName, funcName_len); + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, + "loader_phys_dev_ext_gpa: Adding unknown physical function %s to internal store at index %u", funcName, + inst->phys_dev_ext_disp_function_count); - uint32_t new_function_index = inst->phys_dev_ext_disp_function_count; - // increment the count so that the subsequent logic includes the newly added entry point when searching for functions - inst->phys_dev_ext_disp_function_count++; + // add found function to phys_dev_ext_disp_functions; + size_t funcName_len = strlen(funcName) + 1; + inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count] = + (char *)loader_instance_heap_alloc(inst, funcName_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (NULL == inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count]) { + // failed to allocate memory, return NULL + return NULL; + } + strncpy(inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count], funcName, funcName_len); + + new_function_index = inst->phys_dev_ext_disp_function_count; + // increment the count so that the subsequent logic includes the newly added entry point when searching for functions + inst->phys_dev_ext_disp_function_count++; + has_found = true; + } // Setup the ICD function pointers struct loader_icd_term *icd_term = inst->icd_terms; @@ -265,8 +280,8 @@ void *loader_phys_dev_ext_gpa_impl(struct loader_instance *inst, const char *fun icd_term->phys_dev_ext[new_function_index] = (PFN_PhysDevExt)icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName); if (NULL != icd_term->phys_dev_ext[new_function_index]) { - // Make sure we set the instance dispatch to point to the loader's terminator now since we can at least handle it in - // one ICD. + // Make sure we set the instance dispatch to point to the loader's terminator now since we can at least handle + // it in one ICD. inst->disp->phys_dev_ext[new_function_index] = loader_get_phys_dev_ext_termin(new_function_index); loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "loader_phys_dev_ext_gpa: Driver %s returned ptr %p for %s", @@ -279,18 +294,20 @@ void *loader_phys_dev_ext_gpa_impl(struct loader_instance *inst, const char *fun icd_term = icd_term->next; } - // Now, search for the first layer attached and query using it to get the first entry point. - // Only set the instance dispatch table to it if it isn't NULL. - for (uint32_t i = 0; i < inst->expanded_activated_layer_list.count; i++) { - struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i]; - if (layer_prop->interface_version > 1 && NULL != layer_prop->functions.get_physical_device_proc_addr) { - void *layer_ret_function = - (PFN_PhysDevExt)layer_prop->functions.get_physical_device_proc_addr(inst->instance, funcName); - if (NULL != layer_ret_function) { - inst->disp->phys_dev_ext[new_function_index] = layer_ret_function; - loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "loader_phys_dev_ext_gpa: Layer %s returned ptr %p for %s", - layer_prop->info.layerName, inst->disp->phys_dev_ext[new_function_index], funcName); - break; + // Now if this is being run in the trampoline, search for the first layer attached and query using it to get the first entry + // point. Only set the instance dispatch table to it if it isn't NULL. + if (is_tramp) { + for (uint32_t i = 0; i < inst->expanded_activated_layer_list.count; i++) { + struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i]; + if (layer_prop->interface_version > 1 && NULL != layer_prop->functions.get_physical_device_proc_addr) { + void *layer_ret_function = + (PFN_PhysDevExt)layer_prop->functions.get_physical_device_proc_addr(inst->instance, funcName); + if (NULL != layer_ret_function) { + inst->disp->phys_dev_ext[new_function_index] = layer_ret_function; + loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "loader_phys_dev_ext_gpa: Layer %s returned ptr %p for %s", + layer_prop->info.layerName, inst->disp->phys_dev_ext[new_function_index], funcName); + break; + } } } } @@ -308,22 +325,3 @@ void *loader_phys_dev_ext_gpa_tramp(struct loader_instance *inst, const char *fu void *loader_phys_dev_ext_gpa_term(struct loader_instance *inst, const char *funcName) { return loader_phys_dev_ext_gpa_impl(inst, funcName, false); } -// Returns the terminator if the function is supported in an ICD and if there is an entry for it in -// the function name array. Otherwise return NULL. -void *loader_phys_dev_ext_gpa_term_no_check(struct loader_instance *inst, const char *funcName) { - assert(NULL != inst); - - // We should always check to see if any ICD supports it. - if (!loader_check_icds_for_phys_dev_ext_address(inst, funcName)) { - return NULL; - } - - // Linearly look through already added functions to make sure we haven't seen it before - // if we have, return the function at the index found - for (uint32_t i = 0; i < inst->phys_dev_ext_disp_function_count; i++) { - if (inst->phys_dev_ext_disp_functions[i] && !strcmp(inst->phys_dev_ext_disp_functions[i], funcName)) - return loader_get_phys_dev_ext_termin(i); - } - - return NULL; -} diff --git a/loader/unknown_function_handling.h b/loader/unknown_function_handling.h index 5b7478261..0f5bcd1e1 100644 --- a/loader/unknown_function_handling.h +++ b/loader/unknown_function_handling.h @@ -27,11 +27,11 @@ #include "loader_common.h" void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev); -void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName); +void *loader_dev_ext_gpa_tramp(struct loader_instance *inst, const char *funcName); +void *loader_dev_ext_gpa_term(struct loader_instance *inst, const char *funcName); void *loader_phys_dev_ext_gpa_tramp(struct loader_instance *inst, const char *funcName); void *loader_phys_dev_ext_gpa_term(struct loader_instance *inst, const char *funcName); -void *loader_phys_dev_ext_gpa_term_no_check(struct loader_instance *inst, const char *funcName); void loader_free_dev_ext_table(struct loader_instance *inst); -void loader_free_phys_dev_ext_table(struct loader_instance *inst);
\ No newline at end of file +void loader_free_phys_dev_ext_table(struct loader_instance *inst); |