Skip to content

Commit

Permalink
loader: Do not remove duplicated layers
Browse files Browse the repository at this point in the history
Linux can support multiple ABIs, but Vulkan Layer manifest does not
allow to specify different library paths, based on the ABI.

As a solution, for ICDs, we can simply create multiple manifests, one
per ABI, and the Loader will try them one by one until it finds the
library that is compatible with the executable class.

Instead, for Vulkan Layers, this method doesn't work because the Loader
will discard the manifests that have a duplicated layer name.

To add support for multiple ABIs to Vulkan Layers, and to make the
behavior similar to the ICDs, with this commit we remove the duplicated
layer name check.
Instead we add to the output list all the Vulkan Layers that we find,
and only when we are actually going to dlopen them, we discard the
layers with the same name that we already successfully opened.

Fixes: KhronosGroup#155

Signed-off-by: Ludovico de Nittis <[email protected]>
  • Loading branch information
RyuzakiKK committed Dec 2, 2020
1 parent 730aab9 commit eea83cf
Showing 1 changed file with 50 additions and 45 deletions.
95 changes: 50 additions & 45 deletions loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -1708,10 +1708,13 @@ static bool loaderInitLayerList(const struct loader_instance *inst, struct loade
return true;
}

// Search the given layer list for a list matching the given VkLayerProperties
bool loaderListHasLayerProperty(const VkLayerProperties *vk_layer_prop, const struct loader_layer_list *list) {
for (uint32_t i = 0; i < list->count; i++) {
if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) return true;
// Search the given array of layer names for an entry matching the given VkLayerProperties
bool loaderNamesArrayHasLayerProperty(const VkLayerProperties *vk_layer_prop,
uint32_t layer_names_count, char **layer_names) {
for (uint32_t i = 0; i < layer_names_count; i++) {
if (strcmp(vk_layer_prop->layerName, layer_names[i]) == 0) {
return true;
}
}
return false;
}
Expand All @@ -1727,7 +1730,7 @@ void loaderDestroyLayerList(const struct loader_instance *inst, struct loader_de
layer_list->capacity = 0;
}

// Append non-duplicate layer properties defined in prop_list to the given layer_info list
// Append layer properties defined in prop_list to the given layer_info list
VkResult loaderAddLayerPropertiesToList(const struct loader_instance *inst, struct loader_layer_list *list,
uint32_t prop_list_count, const struct loader_layer_properties *props) {
uint32_t i;
Expand All @@ -1744,11 +1747,6 @@ VkResult loaderAddLayerPropertiesToList(const struct loader_instance *inst, stru
for (i = 0; i < prop_list_count; i++) {
layer = (struct loader_layer_properties *)&props[i];

// Look for duplicates, and skip
if (loaderListHasLayerProperty(&layer->info, list)) {
continue;
}

// Check for enough capacity
if (((list->count + 1) * sizeof(struct loader_layer_properties)) >= list->capacity) {
size_t new_capacity = list->capacity * 2;
Expand All @@ -1771,7 +1769,7 @@ VkResult loaderAddLayerPropertiesToList(const struct loader_instance *inst, stru
}

// Search the given search_list for any layers in the props list. Add these to the
// output layer_list. Don't add duplicates to the output layer_list.
// output layer_list.
static VkResult loaderAddLayerNamesToList(const struct loader_instance *inst, struct loader_layer_list *output_list,
struct loader_layer_list *expanded_output_list, uint32_t name_count,
const char *const *names, const struct loader_layer_list *source_list) {
Expand All @@ -1789,17 +1787,10 @@ static VkResult loaderAddLayerNamesToList(const struct loader_instance *inst, st

// If not a meta-layer, simply add it.
if (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
if (!loaderListHasLayerProperty(&layer_prop->info, output_list)) {
loaderAddLayerPropertiesToList(inst, output_list, 1, layer_prop);
}
if (!loaderListHasLayerProperty(&layer_prop->info, expanded_output_list)) {
loaderAddLayerPropertiesToList(inst, expanded_output_list, 1, layer_prop);
}
loaderAddLayerPropertiesToList(inst, output_list, 1, layer_prop);
loaderAddLayerPropertiesToList(inst, expanded_output_list, 1, layer_prop);
} else {
if (!loaderListHasLayerProperty(&layer_prop->info, output_list) ||
!loaderListHasLayerProperty(&layer_prop->info, expanded_output_list)) {
loaderAddMetaLayer(inst, layer_prop, output_list, expanded_output_list, source_list);
}
loaderAddMetaLayer(inst, layer_prop, output_list, expanded_output_list, source_list);
}
}

Expand Down Expand Up @@ -1903,17 +1894,12 @@ static void loaderAddImplicitLayer(const struct loader_instance *inst, const str

if (enable) {
if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
if (!loaderListHasLayerProperty(&prop->info, target_list)) {
loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
}
if (NULL != expanded_target_list && !loaderListHasLayerProperty(&prop->info, expanded_target_list)) {
loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
if (NULL != expanded_target_list) {
loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, prop);
}
} else {
if (!loaderListHasLayerProperty(&prop->info, target_list) ||
(NULL != expanded_target_list && !loaderListHasLayerProperty(&prop->info, expanded_target_list))) {
loaderAddMetaLayer(inst, prop, target_list, expanded_target_list, source_list);
}
loaderAddMetaLayer(inst, prop, target_list, expanded_target_list, source_list);
}
}
}
Expand All @@ -1924,11 +1910,6 @@ bool loaderAddMetaLayer(const struct loader_instance *inst, const struct loader_
const struct loader_layer_list *source_list) {
bool found = true;

// If the meta-layer isn't present in the unexpanded list, add it.
if (!loaderListHasLayerProperty(&prop->info, target_list)) {
loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
}

// We need to add all the individual component layers
for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
bool found_comp = false;
Expand All @@ -1945,11 +1926,8 @@ bool loaderAddMetaLayer(const struct loader_instance *inst, const struct loader_
if (0 != (search_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
found = loaderAddMetaLayer(inst, search_prop, target_list, expanded_target_list, source_list);
} else {
// Otherwise, just make sure it hasn't already been added to either list before we add it
if (!loaderListHasLayerProperty(&search_prop->info, target_list)) {
loaderAddLayerPropertiesToList(inst, target_list, 1, search_prop);
}
if (NULL != expanded_target_list && !loaderListHasLayerProperty(&search_prop->info, expanded_target_list)) {
loaderAddLayerPropertiesToList(inst, target_list, 1, search_prop);
if (NULL != expanded_target_list) {
loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, search_prop);
}
}
Expand All @@ -1965,7 +1943,7 @@ bool loaderAddMetaLayer(const struct loader_instance *inst, const struct loader_
}

// Add this layer to the overall target list (not the expanded one)
if (found && !loaderListHasLayerProperty(&prop->info, target_list)) {
if (found) {
loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
}

Expand All @@ -1974,7 +1952,6 @@ bool loaderAddMetaLayer(const struct loader_instance *inst, const struct loader_

// Search the source_list for any layer with a name that matches the given name and a type
// that matches the given type. Add all matching layers to the target_list.
// Do not add if found loader_layer_properties is already on the target_list.
VkResult loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
struct loader_layer_list *expanded_target_list) {
Expand All @@ -1985,12 +1962,10 @@ VkResult loaderAddLayerNameToList(const struct loader_instance *inst, const char
if (0 == strcmp(source_prop->info.layerName, name) && (source_prop->type_flags & type_flags) == type_flags) {
// If not a meta-layer, simply add it.
if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
if (!loaderListHasLayerProperty(&source_prop->info, target_list) &&
VK_SUCCESS == loaderAddLayerPropertiesToList(inst, target_list, 1, source_prop)) {
if (VK_SUCCESS == loaderAddLayerPropertiesToList(inst, target_list, 1, source_prop)) {
found = true;
}
if (!loaderListHasLayerProperty(&source_prop->info, expanded_target_list) &&
VK_SUCCESS == loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, source_prop)) {
if (VK_SUCCESS == loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, source_prop)) {
found = true;
}
} else {
Expand Down Expand Up @@ -5923,6 +5898,7 @@ VKAPI_ATTR void VKAPI_CALL loader_layer_destroy_device(VkDevice device, const Vk
VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
struct loader_instance *inst, VkInstance *created_instance) {
uint32_t activated_layers = 0;
char ** activated_layer_names = NULL;
VkLayerInstanceCreateInfo chain_info;
VkLayerInstanceLink *layer_instance_link_info = NULL;
VkInstanceCreateInfo loader_create_info;
Expand Down Expand Up @@ -5951,11 +5927,23 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c
return VK_ERROR_OUT_OF_HOST_MEMORY;
}

activated_layer_names = loader_stack_alloc(sizeof(char *) * inst->expanded_activated_layer_list.count);
if (!activated_layer_names) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_create_instance_chain: Failed to alloc activated layer names array");
return VK_ERROR_OUT_OF_HOST_MEMORY;
}

// Create instance chain of enabled layers
for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) {
struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i];
loader_platform_dl_handle lib_handle;

// Skip it if a Layer with the same name has been already successfully activated
if (loaderNamesArrayHasLayerProperty(&layer_prop->info, activated_layers, activated_layer_names)) {
continue;
}

lib_handle = loaderOpenLayerFile(inst, "instance", layer_prop);
if (!lib_handle) {
continue;
Expand Down Expand Up @@ -6043,6 +6031,8 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c

chain_info.u.pLayerInfo = &layer_instance_link_info[activated_layers];

activated_layer_names[activated_layers] = layer_prop->info.layerName;

loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Insert instance layer %s (%s)", layer_prop->info.layerName,
layer_prop->lib_name);

Expand Down Expand Up @@ -6118,6 +6108,7 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
struct loader_device *dev, PFN_vkGetInstanceProcAddr callingLayer,
PFN_vkGetDeviceProcAddr *layerNextGDPA) {
uint32_t activated_layers = 0;
char ** activated_layer_names = NULL;
VkLayerDeviceLink *layer_device_link_info;
VkLayerDeviceCreateInfo chain_info;
VkDeviceCreateInfo loader_create_info;
Expand Down Expand Up @@ -6179,6 +6170,13 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
return VK_ERROR_OUT_OF_HOST_MEMORY;
}

activated_layer_names = loader_stack_alloc(sizeof(char *) * inst->expanded_activated_layer_list.count);
if (!activated_layer_names) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_create_instance_chain: Failed to alloc activated layer names array");
return VK_ERROR_OUT_OF_HOST_MEMORY;
}

if (dev->expanded_activated_layer_list.count > 0) {
chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
chain_info.function = VK_LAYER_LINK_INFO;
Expand All @@ -6193,6 +6191,11 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
struct loader_layer_properties *layer_prop = &dev->expanded_activated_layer_list.list[i];
loader_platform_dl_handle lib_handle;

// Skip it if a Layer with the same name has been already successfully activated
if (loaderNamesArrayHasLayerProperty(&layer_prop->info, activated_layers, activated_layer_names)) {
continue;
}

lib_handle = loaderOpenLayerFile(inst, "device", layer_prop);
if (!lib_handle || done) {
continue;
Expand Down Expand Up @@ -6246,6 +6249,8 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
nextGIPA = fpGIPA;
nextGDPA = fpGDPA;

activated_layer_names[activated_layers] = layer_prop->info.layerName;

loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Inserted device layer %s (%s)", layer_prop->info.layerName,
layer_prop->lib_name);

Expand Down

0 comments on commit eea83cf

Please sign in to comment.