Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/Vulkan-Loader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Giessen <charles@lunarg.com>2022-07-14 02:04:26 +0300
committerCharles Giessen <charles@lunarg.com>2022-08-15 18:32:06 +0300
commit09afdf64210b11ec653a1001e013b5af4fce8559 (patch)
treecabd5a03fa5d0aef8cb91a40d8c95307c23c4679
parent0635d2561141fce2e1032e5bc6685d353197670e (diff)
Enable layer interception of unknown functionssdk-1.3.224.1sdk-1.3.224.0stabilized_release_2022_07sdk-1.3.224
Re-add previously reverted behavior that allows layers to setup dispatch chains for unknown physical device and device functions during vkCreateInstance. Previously, functions not known to the loader could not be queried by a layer during vkCreateInstance (when dispatch tables should be setup). The change adds support for unknown functions in the trampolines of vkGetInstanceProcAddr and vkGetPhysicalDeviceProcAddr.
-rw-r--r--loader/gpa_helper.c2
-rw-r--r--loader/loader.c17
-rw-r--r--loader/unknown_function_handling.c126
-rw-r--r--loader/unknown_function_handling.h6
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);