aboutsummaryrefslogtreecommitdiff
path: root/loader/loader.c
diff options
context:
space:
mode:
authorMark Young <marky@lunarg.com>2017-05-02 10:49:46 -0600
committerMark Young <marky@lunarg.com>2017-05-09 11:01:03 -0600
commit3d876c1544ba6325720a64c248e8eb0214e55d6e (patch)
tree30535ed5f594de4fae64df9c9ab5fbddc1d4264a /loader/loader.c
parent449d28aab53abf93e97f860f33921d79e517c9a1 (diff)
downloadusermoji-3d876c1544ba6325720a64c248e8eb0214e55d6e.tar.xz
loader: Meta-layer support
Integrate Lenny and my changes for Meta-layers. Includes adding initial JSON file for standard_validation. Change-Id: Ibc1da464fad4949e14e171dbc7dd9990621e1081
Diffstat (limited to 'loader/loader.c')
-rw-r--r--loader/loader.c810
1 files changed, 521 insertions, 289 deletions
diff --git a/loader/loader.c b/loader/loader.c
index 48e90647..bc81a759 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -86,8 +86,6 @@ uint32_t g_loader_log_msgs = 0;
loader_platform_thread_mutex loader_lock;
loader_platform_thread_mutex loader_json_lock;
-const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation";
-
LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope alloc_scope) {
@@ -103,6 +101,7 @@ void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t
#endif
pMemory = malloc(size);
}
+
return pMemory;
}
@@ -208,7 +207,6 @@ static inline char *loader_getenv(const char *name, const struct loader_instance
return getenv(name);
}
-
static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
// No allocation of memory necessary for Linux, but we should at least touch
// the inst pointer to get rid of compiler warnings.
@@ -219,8 +217,9 @@ static inline char *loader_secure_getenv(const char *name, const struct loader_i
#elif defined(HAVE___SECURE_GETENV)
return __secure_getenv(name);
#else
-#pragma message("Warning: Falling back to non-secure getenv for environmental lookups! Consider" \
- " updating to a different libc.")
+#pragma message( \
+ "Warning: Falling back to non-secure getenv for environmental lookups! Consider" \
+ " updating to a different libc.")
return loader_getenv(name, inst);
#endif
}
@@ -456,10 +455,9 @@ VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *locati
}
total_size *= 2;
}
- loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
- "Located json file \"%s\" from registry \"%s\\%s\"", name,
- hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR,
- location);
+ loader_log(
+ inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Located json file \"%s\" from registry \"%s\\%s\"", name,
+ hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, location);
if (strlen(*reg_data) == 0) {
(void)snprintf(*reg_data, name_size + 1, "%s", name);
} else {
@@ -638,6 +636,10 @@ void loader_delete_layer_properties(const struct loader_instance *inst, struct l
if (!layer_list) return;
for (i = 0; i < layer_list->count; i++) {
+ if (NULL != layer_list->list[i].component_layer_names) {
+ loader_instance_heap_free(inst, layer_list->list[i].component_layer_names);
+ layer_list->list[i].component_layer_names = NULL;
+ }
loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_list->list[i].instance_extension_list);
dev_ext_list = &layer_list->list[i].device_extension_list;
if (dev_ext_list->capacity > 0 && NULL != dev_ext_list->list && dev_ext_list->list->entrypoint_count > 0) {
@@ -931,6 +933,11 @@ VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct l
return VK_SUCCESS;
}
+// Prototype of loader_add_meta_layer function since we use it in the loader_add_implicit_layer, but can also
+// call loader_add_implicit_layer from loader_add_meta_layer.
+bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ struct loader_layer_list *target_list, const struct loader_layer_list *source_list);
+
// 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.
static VkResult loader_add_layer_names_to_list(const struct loader_instance *inst, struct loader_layer_list *output_list,
@@ -942,7 +949,7 @@ static VkResult loader_add_layer_names_to_list(const struct loader_instance *ins
for (uint32_t i = 0; i < name_count; i++) {
const char *search_target = names[i];
layer_prop = loader_get_layer_property(search_target, search_list);
- if (!layer_prop) {
+ if (NULL == layer_prop) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_add_layer_names_to_list: Unable to find layer"
" %s",
@@ -951,7 +958,14 @@ static VkResult loader_add_layer_names_to_list(const struct loader_instance *ins
continue;
}
- err = loader_add_to_layer_list(inst, output_list, 1, layer_prop);
+ // If not a meta-layer, simply add it.
+ if (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ err = loader_add_to_layer_list(inst, output_list, 1, layer_prop);
+ } else {
+ if (!loader_add_meta_layer(inst, layer_prop, output_list, search_list)) {
+ err = VK_ERROR_LAYER_NOT_PRESENT;
+ }
+ }
}
return err;
@@ -1011,24 +1025,23 @@ VkResult loader_add_to_layer_list(const struct loader_instance *inst, struct loa
for (i = 0; i < prop_list_count; i++) {
layer = (struct loader_layer_properties *)&props[i];
- // look for duplicates
+ // Look for duplicates, and skip
if (has_vk_layer_property(&layer->info, list)) {
continue;
}
- // add to list at end
- // check for enough capacity
- if (list->count * sizeof(struct loader_layer_properties) >= list->capacity) {
- list->list = loader_instance_heap_realloc(inst, list->list, list->capacity, list->capacity * 2,
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ // Check for enough capacity
+ if (((list->count + 1) * sizeof(struct loader_layer_properties)) >= list->capacity) {
+ size_t new_capacity = list->capacity * 2;
+ list->list =
+ loader_instance_heap_realloc(inst, list->list, list->capacity, new_capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == list->list) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_add_to_layer_list: Realloc failed for "
"when attempting to add new layer");
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
- // double capacity
- list->capacity *= 2;
+ list->capacity = new_capacity;
}
memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
@@ -1038,26 +1051,102 @@ VkResult loader_add_to_layer_list(const struct loader_instance *inst, struct loa
return VK_SUCCESS;
}
-// Search the search_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 found_list.
-// Do not add if found loader_layer_properties is already on the found_list.
-void loader_find_layer_name_add_list(const struct loader_instance *inst, const char *name, const enum layer_type type,
- const struct loader_layer_list *search_list, struct loader_layer_list *found_list) {
+// Check the individual implicit layer for the enable/disable environment variable settings. Only add it after
+// every check has passed indicating it should be used.
+static void loader_add_implicit_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ struct loader_layer_list *target_list, const struct loader_layer_list *source_list) {
+ bool enable = false;
+ char *env_value = NULL;
+
+ // if no enable_environment variable is specified, this implicit layer
+ // should always be enabled. Otherwise check if the variable is set
+ if (prop->enable_env_var.name[0] == 0) {
+ enable = true;
+ } else {
+ env_value = loader_secure_getenv(prop->enable_env_var.name, inst);
+ if (env_value && !strcmp(prop->enable_env_var.value, env_value)) enable = true;
+ loader_free_getenv(env_value, inst);
+ }
+
+ // disable_environment has priority, i.e. if both enable and disable
+ // environment variables are set, the layer is disabled. Implicit
+ // layers are required to have a disable_environment variables
+ env_value = loader_secure_getenv(prop->disable_env_var.name, inst);
+ if (env_value) {
+ enable = false;
+ }
+ loader_free_getenv(env_value, inst);
+
+ if (enable) {
+ // If not a meta-layer, simply add it.
+ if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ loader_add_to_layer_list(inst, target_list, 1, prop);
+ } else {
+ loader_add_meta_layer(inst, prop, target_list, source_list);
+ }
+ }
+}
+
+// Add the component layers of a meta-layer to the active list of layers
+bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ struct loader_layer_list *target_list, const struct loader_layer_list *source_list) {
+ bool found = true;
+
+ // 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;
+ const struct loader_layer_properties *search_prop =
+ loader_get_layer_property(prop->component_layer_names[comp_layer], source_list);
+ if (search_prop != NULL) {
+ found_comp = true;
+ if (has_vk_layer_property(&search_prop->info, target_list)) {
+ break;
+ }
+ // If the component layer is itself an implicit layer, check before adding,
+ // otherwise, just add
+ if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
+ loader_add_implicit_layer(inst, search_prop, target_list, source_list);
+ } else {
+ loader_add_to_layer_list(inst, target_list, 1, search_prop);
+ }
+ }
+ if (!found_comp) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_add_meta_layer: Failed to find layer name %s component layer "
+ "%s to activate",
+ search_prop->info.layerName, prop->component_layer_names[comp_layer]);
+ found = false;
+ }
+ }
+ return found;
+}
+
+// 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.
+void loader_find_layer_name_add_list(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) {
bool found = false;
- for (uint32_t i = 0; i < search_list->count; i++) {
- struct loader_layer_properties *layer_prop = &search_list->list[i];
- if (0 == strcmp(layer_prop->info.layerName, name) && (layer_prop->type & type)) {
- // Found a layer with the same name, add to found_list
- if (VK_SUCCESS == loader_add_to_layer_list(inst, found_list, 1, layer_prop)) {
- found = true;
+ for (uint32_t i = 0; i < source_list->count; i++) {
+ struct loader_layer_properties *source_prop = &source_list->list[i];
+ if (0 == strcmp(source_prop->info.layerName, name) && (source_prop->type_flags & type_flags) == type_flags) {
+ // If already, there, keep going.
+ if (has_vk_layer_property(&source_prop->info, target_list)) {
+ continue;
+ }
+ // If not a meta-layer, simply add it.
+ if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ if (VK_SUCCESS == loader_add_to_layer_list(inst, target_list, 1, source_prop)) {
+ found = true;
+ }
+ } else {
+ found = loader_add_meta_layer(inst, source_prop, target_list, source_list);
}
}
}
if (!found) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "loader_find_layer_name_add_list: Failed to find layer name "
- "%s to activate",
- name);
+ "loader_find_layer_name_add_list: Failed to find layer name %s to activate", name);
}
}
@@ -1321,15 +1410,16 @@ bool loader_get_icd_interface_version(PFN_vkNegotiateLoaderICDInterfaceVersion f
}
void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
- if (icd_tramp_list->capacity == 0) return;
- for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
- loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
- loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
+ if (0 != icd_tramp_list->capacity) {
+ for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
+ loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
+ loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
+ }
+ loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
+ icd_tramp_list->capacity = 0;
+ icd_tramp_list->count = 0;
+ icd_tramp_list->scanned_list = NULL;
}
- loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
- icd_tramp_list->capacity = 0;
- icd_tramp_list->count = 0;
- icd_tramp_list->scanned_list = NULL;
}
static VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
@@ -1734,16 +1824,14 @@ VkResult loader_copy_layer_properties(const struct loader_instance *inst, struct
}
static bool loader_find_layer_name_list(const char *name, const struct loader_layer_list *layer_list) {
- if (!layer_list) return false;
- for (uint32_t j = 0; j < layer_list->count; j++)
- if (!strcmp(name, layer_list->list[j].info.layerName)) return true;
- return false;
-}
-
-static bool loader_find_layer_name(const char *name, uint32_t layer_count, const char **layer_list) {
- if (!layer_list) return false;
- for (uint32_t j = 0; j < layer_count; j++)
- if (!strcmp(name, layer_list[j])) return true;
+ if (NULL == layer_list) {
+ return false;
+ }
+ for (uint32_t j = 0; j < layer_list->count; j++) {
+ if (!strcmp(name, layer_list->list[j].info.layerName)) {
+ return true;
+ }
+ }
return false;
}
@@ -1754,118 +1842,182 @@ bool loader_find_layer_name_array(const char *name, uint32_t layer_count, const
return false;
}
-// Searches through an array of layer names (ppp_layer_names) looking for a
-// layer key_name.
-// If not found then simply returns updating nothing.
-// Otherwise, it uses expand_count, expand_names adding them to layer names.
-// Any duplicate (pre-existing) expand_names in layer names are removed.
-// Order is otherwise preserved, with the layer key_name being replaced by the
-// expand_names.
-// @param inst
-// @param layer_count
-// @param ppp_layer_names
-VkResult loader_expand_layer_names(struct loader_instance *inst, const char *key_name, uint32_t expand_count,
- const char expand_names[][VK_MAX_EXTENSION_NAME_SIZE], uint32_t *layer_count,
- char const *const **ppp_layer_names) {
- char const *const *pp_src_layers = *ppp_layer_names;
-
- if (!loader_find_layer_name(key_name, *layer_count, (char const **)pp_src_layers)) {
- inst->activated_layers_are_std_val = false;
- return VK_SUCCESS; // didn't find the key_name in the list.
- }
-
- loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found meta layer %s, replacing with actual layer group", key_name);
-
- inst->activated_layers_are_std_val = true;
- char const **pp_dst_layers = loader_instance_heap_alloc(inst, (expand_count + *layer_count - 1) * sizeof(char const *),
- VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (NULL == pp_dst_layers) {
+const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation";
+
+// Adds the legacy VK_LAYER_LUNARG_standard_validation as a meta-layer if it
+// fails to find it in the list already. This is usually an indication that a
+// newer loader is being used with an older layer set.
+static bool loader_add_legacy_std_val_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list) {
+ uint32_t i;
+ bool success = true;
+ struct loader_layer_properties *props = loader_get_next_layer_property(inst, layer_instance_list);
+ const char std_validation_names[6][VK_MAX_EXTENSION_NAME_SIZE] = {
+ "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
+ "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
+ "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects"};
+ uint32_t layer_count = sizeof(std_validation_names) / sizeof(std_validation_names[0]);
+
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "Adding VK_LAYER_LUNARG_standard_validation using the loader legacy path. This is"
+ " not an error.");
+
+ if (NULL == props) {
+ goto out;
+ }
+
+ memset(props, 0, sizeof(struct loader_layer_properties));
+ props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER | VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER | VK_LAYER_TYPE_FLAG_META_LAYER;
+ strncpy(props->info.description, "LunarG Standard Validation Layer", sizeof(props->info.description));
+ props->info.implementationVersion = 1;
+ strncpy(props->info.layerName, std_validation_str, sizeof(props->info.layerName));
+ props->info.specVersion = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION);
+
+ props->component_layer_names =
+ loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * layer_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == props->component_layer_names) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
- "loader_expand_layer_names:: Failed to allocate space for "
- "std_validation layer names in pp_dst_layers.");
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ "Failed to allocate space for legacy VK_LAYER_LUNARG_standard_validation"
+ " meta-layer component_layers information.");
+ success = false;
+ goto out;
+ }
+ for (i = 0; i < layer_count; i++) {
+ strncpy(props->component_layer_names[i], std_validation_names[i], MAX_STRING_SIZE - 1);
+ props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0';
}
- // copy layers from src to dst, stripping key_name and anything in
- // expand_names.
- uint32_t src_index, dst_index = 0;
- for (src_index = 0; src_index < *layer_count; src_index++) {
- if (loader_find_layer_name_array(pp_src_layers[src_index], expand_count, expand_names)) {
- continue;
- }
+out:
+
+ if (!success && NULL != props && NULL != props->component_layer_names) {
+ loader_instance_heap_free(inst, props->component_layer_names);
+ props->component_layer_names = NULL;
+ }
- if (!strcmp(pp_src_layers[src_index], key_name)) {
- // insert all expand_names in place of key_name
- uint32_t expand_index;
- for (expand_index = 0; expand_index < expand_count; expand_index++) {
- pp_dst_layers[dst_index++] = expand_names[expand_index];
+ return success;
+}
+
+// Verify that all component layers in a meta-layer are valid.
+static bool verify_meta_layer_comp_layers(const struct loader_instance *inst, struct loader_layer_properties *prop,
+ struct loader_layer_list *instance_layers) {
+ bool success = true;
+ uint32_t expected_major = 0;
+ uint32_t expected_minor = 0;
+
+ for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
+ if (!loader_find_layer_name_list(prop->component_layer_names[comp_layer], instance_layers)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Meta-layer %s can't find component layer %s at index %d."
+ " Skipping this layer.",
+ prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer);
+ success = false;
+ break;
+ } else {
+ struct loader_layer_properties *comp_prop =
+ loader_get_layer_property(prop->component_layer_names[comp_layer], instance_layers);
+ if (comp_prop == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Meta-layer %s can't find property for component layer %s at index %d."
+ " Skipping this layer.",
+ prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer);
+ success = false;
+ break;
}
- continue;
- }
- pp_dst_layers[dst_index++] = pp_src_layers[src_index];
- }
+ // Check the version of each layer, they need to at least match MAJOR and MINOR
+ if (comp_layer == 0) {
+ expected_major = VK_VERSION_MAJOR(comp_prop->info.specVersion);
+ expected_minor = VK_VERSION_MINOR(comp_prop->info.specVersion);
+ } else {
+ uint32_t cur_major = VK_VERSION_MAJOR(comp_prop->info.specVersion);
+ uint32_t cur_minor = VK_VERSION_MINOR(comp_prop->info.specVersion);
+ if (cur_major != expected_major || cur_minor != expected_minor) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Meta-layer %s component layer 0 uses API version %d.%d, but component layer "
+ " %d, uses API version %d.%d. Skipping this layer.",
+ prop->info.layerName, expected_major, expected_minor, comp_layer, cur_major, cur_minor);
+ success = false;
+ break;
+ }
+ }
- *ppp_layer_names = pp_dst_layers;
- *layer_count = dst_index;
+ // Make sure the layer isn't using it's own name
+ if (!strcmp(prop->info.layerName, prop->component_layer_names[comp_layer])) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Meta-layer %s lists itself in its component layer list at index %d."
+ " Skipping this layer.",
+ prop->info.layerName, comp_layer);
+ success = false;
+ break;
+ }
+ if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "verify_meta_layer_comp_layers: Adding meta-layer %s which also contains meta-layer %s",
+ prop->info.layerName, comp_prop->info.layerName);
- return VK_SUCCESS;
-}
+ // Make sure if the layer is using a meta-layer in its component list that we also verify that.
+ if (!verify_meta_layer_comp_layers(inst, comp_prop, instance_layers)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Meta-layer %s component layer %s can not find all component layers."
+ " Skipping this layer.",
+ prop->info.layerName, prop->component_layer_names[comp_layer]);
+ success = false;
+ break;
+ }
+ }
-void loader_delete_shadow_inst_layer_names(const struct loader_instance *inst, const VkInstanceCreateInfo *orig,
- VkInstanceCreateInfo *ours) {
- // Free the layer names array iff we had to reallocate it
- if (orig->ppEnabledLayerNames != ours->ppEnabledLayerNames) {
- loader_instance_heap_free(inst, (void *)ours->ppEnabledLayerNames);
- }
-}
+ // Add any instance and device extensions from component layers to this layer
+ // list, so that anyone querying extensions will only need to look at the meta-layer
+ for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Meta-layer %s component layer %s adding instance extension %s",
+ prop->info.layerName, prop->component_layer_names[comp_layer],
+ comp_prop->instance_extension_list.list[ext].extensionName);
+ if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) {
+ loader_add_to_ext_list(inst, &prop->instance_extension_list, 1, &comp_prop->instance_extension_list.list[ext]);
+ }
+ }
-void loader_init_std_validation_props(struct loader_layer_properties *props) {
- memset(props, 0, sizeof(struct loader_layer_properties));
- props->type = VK_LAYER_TYPE_META_EXPLICT;
- strncpy(props->info.description, "LunarG Standard Validation Layer", sizeof(props->info.description));
- props->info.implementationVersion = 1;
- strncpy(props->info.layerName, std_validation_str, sizeof(props->info.layerName));
- // TODO what about specVersion? for now insert loader's built version
- props->info.specVersion = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION);
+ for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Meta-layer %s component layer %s adding device extension %s",
+ prop->info.layerName, prop->component_layer_names[comp_layer],
+ comp_prop->device_extension_list.list[ext].props.extensionName);
+ if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) {
+ loader_add_to_dev_ext_list(inst, &prop->device_extension_list,
+ &comp_prop->device_extension_list.list[ext].props, 0, NULL);
+ }
+ }
+ }
+ }
+ if (success) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Meta-layer %s all %d component layers appear to be valid.",
+ prop->info.layerName, prop->num_component_layers);
+ }
+ return success;
}
-// Searches through the existing instance layer lists looking for
-// the set of required layer names. If found then it adds a meta property to the
-// layer list.
-// Assumes the required layers are the same for both instance and device lists.
-// @param inst
-// @param layer_count number of layers in layer_names
-// @param layer_names array of required layer names
-// @param layer_instance_list
-static void loader_add_layer_property_meta(const struct loader_instance *inst, uint32_t layer_count,
- const char layer_names[][VK_MAX_EXTENSION_NAME_SIZE],
- struct loader_layer_list *layer_instance_list) {
- uint32_t i;
- bool found;
- struct loader_layer_list *layer_list;
+// Verify that all meta-layers in a layer list are valid.
+static void verify_all_meta_layers(const struct loader_instance *inst, struct loader_layer_list *instance_layers) {
+ for (uint32_t i = 0; i < instance_layers->count; i++) {
+ struct loader_layer_properties *prop = &instance_layers->list[i];
- if (0 == layer_count || (!layer_instance_list)) return;
- if (layer_instance_list && (layer_count > layer_instance_list->count)) return;
+ // If this is a meta-layer, make sure it is valid
+ if ((prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) && !verify_meta_layer_comp_layers(inst, prop, instance_layers)) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName);
- layer_list = layer_instance_list;
+ // Delete the component layers
+ prop->num_component_layers = 0;
+ loader_instance_heap_free(inst, prop->component_layer_names);
+ prop->component_layer_names = NULL;
- found = true;
- if (layer_list == NULL) return;
- for (i = 0; i < layer_count; i++) {
- if (loader_find_layer_name_list(layer_names[i], layer_list)) continue;
- found = false;
- break;
- }
+ // Remove the current invalid meta-layer from the layer list
+ for (uint32_t j = i + 1; j < instance_layers->count; j++) {
+ memcpy(&instance_layers->list[j - 1], &instance_layers->list[j], sizeof(struct loader_layer_properties));
+ }
+ instance_layers->count--;
- struct loader_layer_properties *props;
- if (found) {
- props = loader_get_next_layer_property(inst, layer_list);
- if (NULL == props) {
- // Error already triggered in loader_get_next_layer_property.
- return;
+ // Re-verify the remaining list
+ verify_all_meta_layers(inst, instance_layers);
}
- loader_init_std_validation_props(props);
}
}
@@ -1877,14 +2029,17 @@ typedef struct {
uint16_t patch;
} layer_json_version;
-static void loader_read_json_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
- cJSON *layer_node, layer_json_version version, cJSON *item, cJSON *disable_environment,
- bool is_implicit, char *filename) {
+static VkResult loader_read_json_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
+ cJSON *layer_node, layer_json_version version, cJSON *item, cJSON *disable_environment,
+ bool is_implicit, char *filename) {
char *temp;
- char *name, *type, *library_path, *api_version;
+ char *name, *type, *library_path_str, *api_version;
char *implementation_version, *description;
- cJSON *ext_item;
+ cJSON *ext_item, *library_path, *component_layers;
VkExtensionProperties ext_prop;
+ VkResult result = VK_ERROR_INITIALIZATION_FAILED;
+ struct loader_layer_properties *props = NULL;
+ int i, j;
// The following are required in the "layer" object:
// (required) "name"
@@ -1903,7 +2058,7 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
"Didn't find required layer object %s in manifest " \
"JSON file, skipping this layer", \
#var); \
- return; \
+ goto out; \
} \
}
#define GET_JSON_ITEM(node, var) \
@@ -1915,7 +2070,7 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
"Didn't find required layer value %s in manifest JSON " \
"file, skipping this layer", \
#var); \
- return; \
+ goto out; \
} \
temp = cJSON_Print(item); \
if (temp == NULL) { \
@@ -1924,7 +2079,8 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
"Problem accessing layer value %s in manifest JSON " \
"file, skipping this layer", \
#var); \
- return; \
+ result = VK_ERROR_OUT_OF_HOST_MEMORY; \
+ goto out; \
} \
temp[strlen(temp) - 1] = '\0'; \
var = loader_stack_alloc(strlen(temp) + 1); \
@@ -1933,58 +2089,135 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
}
GET_JSON_ITEM(layer_node, name)
GET_JSON_ITEM(layer_node, type)
- GET_JSON_ITEM(layer_node, library_path)
GET_JSON_ITEM(layer_node, api_version)
GET_JSON_ITEM(layer_node, implementation_version)
GET_JSON_ITEM(layer_node, description)
- if (is_implicit) {
- GET_JSON_OBJECT(layer_node, disable_environment)
- }
-#undef GET_JSON_ITEM
-#undef GET_JSON_OBJECT
// Add list entry
- struct loader_layer_properties *props = NULL;
if (!strcmp(type, "DEVICE")) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Device layers are deprecated skipping this layer");
layer_node = layer_node->next;
- return;
+ goto out;
}
+
// Allow either GLOBAL or INSTANCE type interchangeably to handle
// layers that must work with older loaders
if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
if (layer_instance_list == NULL) {
layer_node = layer_node->next;
- return;
+ goto out;
}
props = loader_get_next_layer_property(inst, layer_instance_list);
if (NULL == props) {
// Error already triggered in loader_get_next_layer_property.
- return;
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
}
- props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
- }
-
- if (props == NULL) {
+ props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
+ if (!is_implicit) {
+ props->type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
+ }
+ } else {
layer_node = layer_node->next;
- return;
+ goto out;
}
- strncpy(props->info.layerName, name, sizeof(props->info.layerName));
- props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
+ // Library path no longer required unless component_layers is also not defined
+ library_path = cJSON_GetObjectItem(layer_node, "library_path");
+ component_layers = cJSON_GetObjectItem(layer_node, "component_layers");
+ if (NULL != library_path) {
+ if (NULL != component_layers) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating meta-layer-specific component_layers, but also "
+ "defining layer library path. Both are not compatible, so "
+ "skipping this layer");
+ goto out;
+ }
+ props->num_component_layers = 0;
+ props->component_layer_names = NULL;
- char *fullpath = props->lib_name;
- char *rel_base;
- if (loader_platform_is_path(library_path)) {
- // A relative or absolute path
- char *name_copy = loader_stack_alloc(strlen(filename) + 1);
- strcpy(name_copy, filename);
- rel_base = loader_platform_dirname(name_copy);
- loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
+ temp = cJSON_Print(library_path);
+ if (NULL == temp) {
+ layer_node = layer_node->next;
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Problem accessing layer value library_path in manifest JSON "
+ "file, skipping this layer");
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ library_path_str = loader_stack_alloc(strlen(temp) + 1);
+ strcpy(library_path_str, &temp[1]);
+ cJSON_Free(temp);
+
+ char *fullpath = props->lib_name;
+ char *rel_base;
+ if (NULL != library_path_str) {
+ if (loader_platform_is_path(library_path_str)) {
+ // A relative or absolute path
+ char *name_copy = loader_stack_alloc(strlen(filename) + 1);
+ strcpy(name_copy, filename);
+ rel_base = loader_platform_dirname(name_copy);
+ loader_expand_path(library_path_str, rel_base, MAX_STRING_SIZE, fullpath);
+ } else {
+ // A filename which is assumed in a system directory
+ loader_get_fullpath(library_path_str, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
+ }
+ }
+ } else if (NULL != component_layers) {
+ if (version.major == 1 && (version.minor < 1 || version.patch < 1)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating meta-layer-specific component_layers, but using older "
+ "JSON file version.");
+ }
+ int count = cJSON_GetArraySize(component_layers);
+ props->num_component_layers = count;
+
+ // Allocate buffer for layer names
+ props->component_layer_names =
+ loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == props->component_layer_names) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Copy the component layers into the array
+ for (i = 0; i < count; i++) {
+ cJSON *comp_layer = cJSON_GetArrayItem(component_layers, i);
+ if (NULL != comp_layer) {
+ temp = cJSON_Print(comp_layer);
+ if (NULL == temp) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ strncpy(props->component_layer_names[i], temp + 1, MAX_STRING_SIZE - 1);
+ props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0';
+ cJSON_Free(temp);
+ }
+ }
+
+ // This is now, officially, a meta-layer
+ props->type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Encountered meta-layer %s", name);
+
+ // Make sure we set up other things so we head down the correct branches below
+ library_path_str = NULL;
} else {
- // A filename which is assumed in a system directory
- loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Layer missing both library_path and component_layers fields. One or the "
+ "other MUST be defined. Skipping this layer");
+ goto out;
+ }
+
+ if (is_implicit) {
+ GET_JSON_OBJECT(layer_node, disable_environment)
}
+#undef GET_JSON_ITEM
+#undef GET_JSON_OBJECT
+
+ strncpy(props->info.layerName, name, sizeof(props->info.layerName));
+ props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
props->info.specVersion = loader_make_version(api_version);
props->info.implementationVersion = atoi(implementation_version);
strncpy((char *)props->info.description, description, sizeof(props->info.description));
@@ -1995,7 +2228,7 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
"Didn't find required layer child value disable_environment"
"in manifest JSON file, skipping this layer");
layer_node = layer_node->next;
- return;
+ goto out;
}
strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof(props->disable_env_var.name));
props->disable_env_var.name[sizeof(props->disable_env_var.name) - 1] = '\0';
@@ -2020,6 +2253,9 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
var = loader_stack_alloc(strlen(temp) + 1); \
strcpy(var, &temp[1]); \
cJSON_Free(temp); \
+ } else { \
+ result = VK_ERROR_OUT_OF_HOST_MEMORY; \
+ goto out; \
} \
} \
}
@@ -2031,8 +2267,6 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
char *vkNegotiateLoaderLayerInterfaceVersion = NULL;
char *spec_version = NULL;
char **entry_array = NULL;
- entrypoints = NULL;
- int i, j;
// Layer interface functions
// vkGetInstanceProcAddr
@@ -2146,7 +2380,8 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
temp = cJSON_Print(ext_item);
if (NULL == temp) {
entry_array[j] = NULL;
- continue;
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
}
temp[strlen(temp) - 1] = '\0';
entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
@@ -2168,13 +2403,28 @@ static void loader_read_json_layer(const struct loader_instance *inst, struct lo
props->enable_env_var.value[sizeof(props->enable_env_var.value) - 1] = '\0';
}
}
+
+ result = VK_SUCCESS;
+
+out:
+
#undef GET_JSON_ITEM
#undef GET_JSON_OBJECT
+
+ if (VK_SUCCESS != result && NULL != props) {
+ props->num_component_layers = 0;
+ if (NULL != props->component_layer_names) {
+ loader_instance_heap_free(inst, props->component_layer_names);
+ }
+ props->component_layer_names = NULL;
+ }
+
+ return result;
}
static inline bool is_valid_layer_json_version(const layer_json_version *layer_json) {
// Supported versions are: 1.0.0, 1.0.1, and 1.1.0.
- if ((layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch == 0) ||
+ if ((layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 2) ||
(layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
return true;
}
@@ -2198,24 +2448,24 @@ static inline bool layer_json_supports_layers_tag(const layer_json_version *laye
// layer_list has a new entry and initialized accordingly.
// If the json input object does not have all the required fields no entry
// is added to the list.
-static void loader_add_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
- cJSON *json, bool is_implicit, char *filename) {
+static VkResult loader_add_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
+ cJSON *json, bool is_implicit, char *filename) {
// The following Fields in layer manifest file that are required:
// - “file_format_version”
// - If more than one "layer" object are used, then the "layers" array is
// required
-
+ VkResult result = VK_ERROR_INITIALIZATION_FAILED;
cJSON *item, *layers_node, *layer_node;
layer_json_version json_version = {0, 0, 0};
char *vers_tok;
cJSON *disable_environment = NULL;
item = cJSON_GetObjectItem(json, "file_format_version");
if (item == NULL) {
- return;
+ goto out;
}
char *file_vers = cJSON_PrintUnformatted(item);
if (NULL == file_vers) {
- return;
+ goto out;
}
loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found manifest file %s, version %s", filename, file_vers);
// Get the major/minor/and patch as integers for easier comparison
@@ -2235,7 +2485,7 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru
if (!is_valid_layer_json_version(&json_version)) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"loader_add_layer_properties: %s invalid layer "
- " manifest file version %d.%d.%d. May cause errors.",
+ "manifest file version %d.%d.%d. May cause errors.",
filename, json_version.major, json_version.minor, json_version.patch);
}
cJSON_Free(file_vers);
@@ -2259,10 +2509,10 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru
"\'layers\' array element %d object in manifest "
"JSON file %s. Skipping this file",
curLayer, filename);
- return;
+ goto out;
}
- loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment, is_implicit,
- filename);
+ result = loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment,
+ is_implicit, filename);
}
} else {
// Otherwise, try to read in individual layers
@@ -2272,7 +2522,7 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru
"loader_add_layer_properties: Can not find \'layer\' "
"object in manifest JSON file %s. Skipping this file.",
filename);
- return;
+ goto out;
}
// Loop through all "layer" objects in the file to get a count of them
// first.
@@ -2294,13 +2544,16 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru
filename);
} else {
do {
- loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment, is_implicit,
- filename);
+ result = loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment,
+ is_implicit, filename);
layer_node = layer_node->next;
} while (layer_node != NULL);
}
}
- return;
+
+out:
+
+ return result;
}
// Find the Vulkan library manifest files.
@@ -2321,7 +2574,7 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru
// List has a pointer to string for each manifest filename.
// When done using the list in out_files, pointers should be freed.
// Location or override string lists can be either files or directories as
-//follows:
+// follows:
// | location | override
// --------------------------------
// Win ICD | files | files
@@ -2329,8 +2582,8 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru
// Linux ICD | dirs | files
// Linux Layer| dirs | dirs
static VkResult loader_get_manifest_files(const struct loader_instance *inst, const char *env_override, const char *source_override,
- bool is_layer, bool warn_if_not_present, const char *location, const char *relative_location,
- struct loader_manifest_files *out_files) {
+ bool is_layer, bool warn_if_not_present, const char *location,
+ const char *relative_location, struct loader_manifest_files *out_files) {
const char * override = NULL;
char *override_getenv = NULL;
char *loc, *orig_loc = NULL;
@@ -2386,13 +2639,11 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co
#if !defined(_WIN32)
const char *xdgconfdirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
const char *xdgdatadirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
- if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0')
- xdgconfdirs = FALLBACK_CONFIG_DIRS;
- if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0')
- xdgdatadirs = FALLBACK_DATA_DIRS;
+ if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0') xdgconfdirs = FALLBACK_CONFIG_DIRS;
+ if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0') xdgdatadirs = FALLBACK_DATA_DIRS;
const size_t rel_size = strlen(relative_location);
// Leave space for trailing separators
- loc_size += strlen(xdgconfdirs) + strlen(xdgdatadirs) + 2*rel_size + 2;
+ loc_size += strlen(xdgconfdirs) + strlen(xdgdatadirs) + 2 * rel_size + 2;
for (const char *x = xdgconfdirs; *x; ++x)
if (*x == PATH_SEPARATOR) loc_size += rel_size;
for (const char *x = xdgdatadirs; *x; ++x)
@@ -2754,6 +3005,7 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
if (VK_SUCCESS != res || manifest_files.count == 0) {
goto out;
}
+
loader_platform_thread_lock_mutex(&loader_json_lock);
lockedMutex = true;
for (uint32_t i = 0; i < manifest_files.count; i++) {
@@ -3018,14 +3270,35 @@ void loader_layer_scan(const struct loader_instance *inst, struct loader_layer_l
continue;
}
- loader_add_layer_properties(inst, instance_layers, json, (implicit == 1), file_str);
+ VkResult local_res = loader_add_layer_properties(inst, instance_layers, json, (implicit == 1), file_str);
cJSON_Delete(json);
+
+ if (VK_SUCCESS != local_res) {
+ goto out;
+ }
}
}
- // add a meta layer for validation if the validation layers are all present
- loader_add_layer_property_meta(inst, sizeof(std_validation_names) / sizeof(std_validation_names[0]), std_validation_names,
- instance_layers);
+ // See if "VK_LAYER_LUNARG_standard_validation" already in list.
+ bool found_std_val = false;
+ for (uint32_t i = 0; i < instance_layers->count; i++) {
+ struct loader_layer_properties *props = &instance_layers->list[i];
+ if (strcmp(props->info.layerName, std_validation_str) == 0) {
+ found_std_val = true;
+ break;
+ }
+ }
+
+ // If we didn't find the VK_LAYER_LUNARG_standard_validation meta-layer in
+ // the list, then we need to add it manually. This is likely because we're
+ // dealing with a new loader, but an old layer folder.
+ if (!found_std_val && !loader_add_legacy_std_val_layer(inst, instance_layers)) {
+ goto out;
+ }
+
+ // Verify any meta-layers in the list are valid and all the component layers are
+ // actually present in the available layer list
+ verify_all_meta_layers(inst, instance_layers);
out:
@@ -3052,8 +3325,8 @@ void loader_implicit_layer_scan(const struct loader_instance *inst, struct loade
// Pass NULL for environment variable override - implicit layers are not
// overridden by LAYERS_PATH_ENV
- VkResult res =
- loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO, &manifest_files);
+ VkResult res = loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO,
+ &manifest_files);
if (VK_SUCCESS != res || manifest_files.count == 0) {
return;
}
@@ -3077,17 +3350,16 @@ void loader_implicit_layer_scan(const struct loader_instance *inst, struct loade
continue;
}
- loader_add_layer_properties(inst, instance_layers, json, true, file_str);
+ res = loader_add_layer_properties(inst, instance_layers, json, true, file_str);
loader_instance_heap_free(inst, file_str);
cJSON_Delete(json);
+
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ break;
+ }
}
loader_instance_heap_free(inst, manifest_files.filename_list);
-
- // add a meta layer for validation if the validation layers are all present
- loader_add_layer_property_meta(inst, sizeof(std_validation_names) / sizeof(std_validation_names[0]), std_validation_names,
- instance_layers);
-
loader_platform_thread_unlock_mutex(&loader_json_lock);
}
@@ -3683,82 +3955,43 @@ void loader_deactivate_layers(const struct loader_instance *instance, struct loa
// Go through the search_list and find any layers which match type. If layer
// type match is found in then add it to ext_list.
-static void loader_add_layer_implicit(const struct loader_instance *inst, const enum layer_type type,
- struct loader_layer_list *list, const struct loader_layer_list *search_list) {
- bool enable;
- char *env_value;
- uint32_t i;
- for (i = 0; i < search_list->count; i++) {
- const struct loader_layer_properties *prop = &search_list->list[i];
- if (prop->type & type) {
- // Found an implicit layer, see if it should be enabled
- enable = false;
-
- // if no enable_environment variable is specified, this implicit
- // layer
- // should always be enabled. Otherwise check if the variable is set
- if (prop->enable_env_var.name[0] == 0) {
- enable = true;
- } else {
- env_value = loader_secure_getenv(prop->enable_env_var.name, inst);
- if (env_value && !strcmp(prop->enable_env_var.value, env_value)) enable = true;
- loader_free_getenv(env_value, inst);
- }
-
- // disable_environment has priority, i.e. if both enable and disable
- // environment variables are set, the layer is disabled. Implicit
- // layers
- // are required to have a disable_environment variables
- env_value = loader_secure_getenv(prop->disable_env_var.name, inst);
- if (env_value) {
- enable = false;
- }
- loader_free_getenv(env_value, inst);
-
- if (enable) {
- loader_add_to_layer_list(inst, list, 1, prop);
- }
+static void loader_add_implicit_layers(const struct loader_instance *inst, struct loader_layer_list *target_list,
+ const struct loader_layer_list *source_list) {
+ for (uint32_t src_layer = 0; src_layer < source_list->count; src_layer++) {
+ const struct loader_layer_properties *prop = &source_list->list[src_layer];
+ if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
+ loader_add_implicit_layer(inst, prop, target_list, source_list);
}
}
}
-// Get the layer name(s) from the env_name environment variable. If layer
-// is found in search_list then add it to layer_list. But only add it to
-// layer_list if type matches.
-static void loader_add_layer_env(struct loader_instance *inst, const enum layer_type type, const char *env_name,
- struct loader_layer_list *layer_list, const struct loader_layer_list *search_list) {
- char *layerEnv;
+// Get the layer name(s) from the env_name environment variable. If layer is found in
+// search_list then add it to layer_list. But only add it to layer_list if type_flags matches.
+static void loader_add_env_layers(struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name,
+ struct loader_layer_list *target_list, const struct loader_layer_list *source_list) {
char *next, *name;
-
- layerEnv = loader_secure_getenv(env_name, inst);
- if (layerEnv == NULL) {
- return;
+ char *layer_env = loader_secure_getenv(env_name, inst);
+ if (layer_env == NULL) {
+ goto out;
}
- name = loader_stack_alloc(strlen(layerEnv) + 1);
+ name = loader_stack_alloc(strlen(layer_env) + 1);
if (name == NULL) {
- return;
+ goto out;
}
- strcpy(name, layerEnv);
-
- loader_free_getenv(layerEnv, inst);
+ strcpy(name, layer_env);
while (name && *name) {
next = loader_get_next_path(name);
- if (!strcmp(std_validation_str, name)) {
- // Add meta list of layers
- // Don't attempt to remove duplicate layers already added by app or env var
- loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Expanding meta layer %s found in environment variable",
- std_validation_str);
- if (type == VK_LAYER_TYPE_INSTANCE_EXPLICIT) inst->activated_layers_are_std_val = true;
- for (uint32_t i = 0; i < sizeof(std_validation_names) / sizeof(std_validation_names[0]); i++) {
- loader_find_layer_name_add_list(inst, std_validation_names[i], type, search_list, layer_list);
- }
- } else {
- loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
- }
+ loader_find_layer_name_add_list(inst, name, type_flags, source_list, target_list);
name = next;
}
+out:
+
+ if (layer_env != NULL) {
+ loader_free_getenv(layer_env, inst);
+ }
+
return;
}
@@ -3776,10 +4009,11 @@ VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkIns
}
// Add any implicit layers first
- loader_add_layer_implicit(inst, VK_LAYER_TYPE_INSTANCE_IMPLICIT, &inst->activated_layer_list, instance_layers);
+ loader_add_implicit_layers(inst, &inst->activated_layer_list, instance_layers);
// Add any layers specified via environment variable next
- loader_add_layer_env(inst, VK_LAYER_TYPE_INSTANCE_EXPLICIT, "VK_INSTANCE_LAYERS", &inst->activated_layer_list, instance_layers);
+ loader_add_env_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS", &inst->activated_layer_list,
+ instance_layers);
// Add layers specified by the application
err = loader_add_layer_names_to_list(inst, &inst->activated_layer_list, pCreateInfo->enabledLayerCount,
@@ -4197,7 +4431,7 @@ VkResult loader_validate_layers(const struct loader_instance *inst, const uint32
}
prop = loader_get_layer_property(ppEnabledLayerNames[i], list);
- if (!prop) {
+ if (NULL == prop) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_validate_layers: Layer %d does not exist in "
"the list of available layers",
@@ -4253,7 +4487,7 @@ VkResult loader_validate_instance_extensions(const struct loader_instance *inst,
// Not in global list, search layer extension lists
for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) {
layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[j], instance_layers);
- if (!layer_prop) {
+ if (NULL == layer_prop) {
// Should NOT get here, loader_validate_layers should have already filtered this case out.
continue;
}
@@ -5074,8 +5308,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkP
goto out;
}
- loader_add_layer_implicit(icd_term->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT, &implicit_layer_list,
- &icd_term->this_instance->instance_layer_list);
+ loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, &icd_term->this_instance->instance_layer_list);
// 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).
if (pProperties != NULL) {
@@ -5092,8 +5325,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkP
goto out;
}
- loader_add_layer_implicit(icd_term->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT, &implicit_layer_list,
- &icd_term->this_instance->instance_layer_list);
+ loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, &icd_term->this_instance->instance_layer_list);
for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
for (uint32_t j = 0; j < implicit_layer_list.list[i].device_extension_list.count; j++) {