From abc45636e7d078ea0825bc5c60f12e7b5aa6454d Mon Sep 17 00:00:00 2001 From: Jon Ashburn Date: Wed, 10 Feb 2016 20:59:26 -0700 Subject: loader: Add feature standard-validation layer from application Adds a validation layer grouping VK_LAYER_LUNARG_standard_validation, which is the set of validation layers in a fixed order. This only adds support for enumerating the meta layer and enabling it explicitly from the app. Environment variable enablement of this layer is not yet added. --- loader/loader.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++- loader/loader.h | 24 +++++- loader/trampoline.c | 23 +++++- 3 files changed, 249 insertions(+), 6 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index affdadf1..106c88f3 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -91,6 +91,8 @@ 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"; + // This table contains the loader's instance dispatch table, which contains // default functions if no instance layers are activated. This contains // pointers to "terminator functions". @@ -1621,6 +1623,178 @@ static void loader_copy_layer_properties(const struct loader_instance *inst, } } +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; + return false; +} + +static bool loader_find_layer_name_array( + const char *name, uint32_t layer_count, + const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]) { + if (!layer_list) + return false; + for (uint32_t j = 0; j < layer_count; j++) + if (!strcmp(name, layer_list[j])) + return true; + 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) exapand_names in layer names are removed. + * Expand names are added to the back/end of the list of layer names. + * @param inst + * @param layer_count + * @param ppp_layer_names + */ +void loader_expand_layer_names( + const 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 ***ppp_layer_names) { + char **pp_layer_names = *ppp_layer_names; + if (!loader_find_layer_name(key_name, *layer_count, + (const char **)pp_layer_names)) + return; // 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); + // In place removal of any expand_names found in layer_name (remove + // duplicates) + // Also remove the key_name + uint32_t src_idx, dst_idx, cnt = *layer_count; + for (src_idx = 0; src_idx < *layer_count; src_idx++) { + if (loader_find_layer_name_array(pp_layer_names[src_idx], expand_count, + expand_names)) { + pp_layer_names[src_idx] = NULL; + cnt--; + } else if (!strcmp(pp_layer_names[src_idx], key_name)) { + pp_layer_names[src_idx] = NULL; + cnt--; + } + } + for (dst_idx = 0; dst_idx < cnt; dst_idx++) { + if (pp_layer_names[dst_idx] == NULL) { + src_idx = dst_idx + 1; + while (src_idx < *layer_count && pp_layer_names[src_idx] == NULL) + src_idx++; + if (src_idx < *layer_count && pp_layer_names[src_idx] != NULL) + pp_layer_names[dst_idx] = pp_layer_names[src_idx]; + } + } + + // Add the expand_names to layer_names + src_idx = 0; + for (dst_idx = cnt; dst_idx < cnt + expand_count; dst_idx++) { + pp_layer_names[dst_idx] = (char *)&expand_names[src_idx++][0]; + } + *layer_count = expand_count + cnt; + return; +} + +/** + * Restores the layer name list and count into the pCreatInfo structure. + * If is_device == tru then pCreateInfo is a device structure else an instance + * structure. + * @param layer_count + * @param layer_names + * @param pCreateInfo + */ +void loader_unexpand_dev_layer_names(uint32_t layer_count, char **layer_names, + const VkDeviceCreateInfo *pCreateInfo) { + uint32_t *p_cnt = (uint32_t *)&pCreateInfo->enabledLayerCount; + *p_cnt = layer_count; + + for (uint32_t i = 0; i < layer_count; i++) { + char **pp_str = (char **)&pCreateInfo->ppEnabledLayerNames[i]; + *pp_str = layer_names[i]; + } +} + +void loader_unexpand_inst_layer_names(uint32_t layer_count, char **layer_names, + const VkInstanceCreateInfo *pCreateInfo) { + uint32_t *p_cnt = (uint32_t *)&pCreateInfo->enabledLayerCount; + *p_cnt = layer_count; + + for (uint32_t i = 0; i < layer_count; i++) { + char **pp_str = (char **)&pCreateInfo->ppEnabledLayerNames[i]; + *pp_str = layer_names[i]; + } +} + +/** + * Searches through the existing instance and device 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 + * @param layer_device_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, + struct loader_layer_list *layer_device_list) { + uint32_t i, j; + bool found; + struct loader_layer_list *layer_list; + + if (!layer_count || (layer_count > layer_instance_list->count && + layer_count > layer_device_list->count)) + return; + + for (j = 0; j < 2; j++) { + if (j == 0) + layer_list = layer_instance_list; + else + layer_list = layer_device_list; + found = true; + for (i = 0; i < layer_count; i++) { + if (loader_find_layer_name_list(layer_names[i], layer_list)) + continue; + found = false; + break; + } + + struct loader_layer_properties *props; + if (found) { + props = loader_get_next_layer_property(inst, layer_list); + 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_API_VERSION; + } + } +} + /** * Given a cJSON struct (json) of the top level JSON object from layer manifest * file, add entry to the layer_list. @@ -2280,7 +2454,7 @@ void loader_layer_scan(const struct loader_instance *inst, uint32_t i; uint32_t implicit; - // Get a list of manifest files for layers + // Get a list of manifest files for explicit layers loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ELAYERS_INFO, &manifest_files[0]); // Pass NULL for environment variable override - implicit layers are not @@ -2335,6 +2509,12 @@ void loader_layer_scan(const struct loader_instance *inst, if (manifest_files[1].count != 0) loader_heap_free(inst, manifest_files[1].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, device_layers); + loader_platform_thread_unlock_mutex(&loader_json_lock); } @@ -3784,10 +3964,26 @@ loader_CreateDevice(VkPhysicalDevice physicalDevice, } } + /* convert any meta layers to the actual layers makes a copy of layer name*/ + uint32_t saved_layer_count = pCreateInfo->enabledLayerCount; + char **saved_layer_names; + saved_layer_names = loader_stack_alloc(sizeof(char*) * pCreateInfo->enabledLayerCount); + for (uint32_t i = 0; i < saved_layer_count; i++) { + saved_layer_names[i] = (char *)pCreateInfo->ppEnabledLayerNames[i]; + } + + loader_expand_layer_names( + inst, std_validation_str, + sizeof(std_validation_names) / sizeof(std_validation_names[0]), + std_validation_names, (uint32_t *)&pCreateInfo->enabledLayerCount, + (char ***)&pCreateInfo->ppEnabledLayerNames); + /* fetch a list of all layers activated, explicit and implicit */ res = loader_enable_device_layers(inst, icd, &activated_layer_list, pCreateInfo, &inst->device_layer_list); if (res != VK_SUCCESS) { + loader_unexpand_dev_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); return res; } @@ -3795,6 +3991,8 @@ loader_CreateDevice(VkPhysicalDevice physicalDevice, res = loader_validate_device_extensions(phys_dev, &activated_layer_list, pCreateInfo); if (res != VK_SUCCESS) { + loader_unexpand_dev_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_destroy_generic_list( inst, (struct loader_generic_list *)&activated_layer_list); return res; @@ -3802,6 +4000,8 @@ loader_CreateDevice(VkPhysicalDevice physicalDevice, dev = loader_add_logical_device(inst, &icd->logical_device_list); if (dev == NULL) { + loader_unexpand_dev_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_destroy_generic_list( inst, (struct loader_generic_list *)&activated_layer_list); return VK_ERROR_OUT_OF_HOST_MEMORY; @@ -3818,6 +4018,8 @@ loader_CreateDevice(VkPhysicalDevice physicalDevice, res = loader_enable_device_layers(inst, icd, &dev->activated_layer_list, pCreateInfo, &inst->device_layer_list); if (res != VK_SUCCESS) { + loader_unexpand_dev_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_remove_logical_device(inst, icd, dev); return res; } @@ -3825,6 +4027,8 @@ loader_CreateDevice(VkPhysicalDevice physicalDevice, res = loader_create_device_chain(physicalDevice, pCreateInfo, pAllocator, inst, icd, dev); if (res != VK_SUCCESS) { + loader_unexpand_dev_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_remove_logical_device(inst, icd, dev); return res; } @@ -3841,6 +4045,8 @@ loader_CreateDevice(VkPhysicalDevice physicalDevice, &dev->loader_dispatch, dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, *pDevice); + loader_unexpand_dev_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); return res; } diff --git a/loader/loader.h b/loader/loader.h index 72639eb0..d40952e3 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -59,12 +59,11 @@ enum layer_type { VK_LAYER_TYPE_DEVICE_EXPLICIT = 0x1, VK_LAYER_TYPE_INSTANCE_EXPLICIT = 0x2, - VK_LAYER_TYPE_GLOBAL_EXPLICIT = - 0x3, // both instance and device layer, bitwise + VK_LAYER_TYPE_GLOBAL_EXPLICIT = 0x3, // instance and device layer, bitwise VK_LAYER_TYPE_DEVICE_IMPLICIT = 0x4, VK_LAYER_TYPE_INSTANCE_IMPLICIT = 0x8, - VK_LAYER_TYPE_GLOBAL_IMPLICIT = - 0xc, // both instance and device layer, bitwise + VK_LAYER_TYPE_GLOBAL_IMPLICIT = 0xc, // instance and device layer, bitwise + VK_LAYER_TYPE_META_EXPLICT = 0x10, }; typedef enum VkStringErrorFlagBits { @@ -84,6 +83,13 @@ static const char UTF8_THREE_BYTE_MASK = 0xF8; static const char UTF8_DATA_BYTE_CODE = 0x80; static const char UTF8_DATA_BYTE_MASK = 0xC0; +static const char std_validation_names[9][VK_MAX_EXTENSION_NAME_SIZE] = { + "VK_LAYER_LUNARG_threading", "VK_LAYER_LUNARG_param_checker", + "VK_LAYER_LUNARG_device_limits", "VK_LAYER_LUNARG_object_tracker", + "VK_LAYER_LUNARG_image", "VK_LAYER_LUNARG_mem_tracker", + "VK_LAYER_LUNARG_draw_state", "VK_LAYER_LUNARG_swapchain", + "VK_LAYER_GOOGLE_unique_objects"}; + // form of all dynamic lists/arrays // only the list element should be changed struct loader_generic_list { @@ -373,6 +379,7 @@ extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init); extern loader_platform_thread_mutex loader_lock; extern loader_platform_thread_mutex loader_json_lock; extern const VkLayerInstanceDispatchTable instance_disp; +extern const char *std_validation_str; struct loader_msg_callback_map_entry { VkDebugReportCallbackEXT icd_obj; @@ -477,6 +484,15 @@ void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list); void loader_delete_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list); +void loader_expand_layer_names( + const 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 ***ppp_layer_names); +void loader_unexpand_dev_layer_names(uint32_t layer_count, char **layer_names, + const VkDeviceCreateInfo *pCreateInfo); +void loader_unexpand_inst_layer_names(uint32_t layer_count, char **layer_names, + const VkInstanceCreateInfo *pCreateInfo); void loader_add_to_layer_list(const struct loader_instance *inst, struct loader_layer_list *list, uint32_t prop_list_count, diff --git a/loader/trampoline.c b/loader/trampoline.c index ff3cd965..473daa62 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -119,6 +119,20 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, } } + /* convert any meta layers to the actual layers makes a copy of layer name*/ + uint32_t saved_layer_count = pCreateInfo->enabledLayerCount; + char **saved_layer_names; + saved_layer_names = loader_stack_alloc(sizeof(char*) * pCreateInfo->enabledLayerCount); + for (uint32_t i = 0; i < saved_layer_count; i++) { + saved_layer_names[i] = (char *)pCreateInfo->ppEnabledLayerNames[i]; + } + + loader_expand_layer_names( + ptr_instance, std_validation_str, + sizeof(std_validation_names) / sizeof(std_validation_names[0]), + std_validation_names, (uint32_t *)&pCreateInfo->enabledLayerCount, + (char ***)&pCreateInfo->ppEnabledLayerNames); + /* Scan/discover all ICD libraries */ memset(&ptr_instance->icd_libs, 0, sizeof(ptr_instance->icd_libs)); loader_icd_scan(ptr_instance, &ptr_instance->icd_libs); @@ -130,6 +144,8 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, ptr_instance, &ptr_instance->ext_list, &ptr_instance->instance_layer_list, pCreateInfo); if (res != VK_SUCCESS) { + loader_unexpand_inst_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list); loader_delete_layer_properties(ptr_instance, @@ -148,6 +164,8 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, loader_heap_alloc(ptr_instance, sizeof(VkLayerInstanceDispatchTable), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (ptr_instance->disp == NULL) { + loader_unexpand_inst_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list); loader_delete_layer_properties(ptr_instance, @@ -169,6 +187,8 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, res = loader_enable_instance_layers(ptr_instance, pCreateInfo, &ptr_instance->instance_layer_list); if (res != VK_SUCCESS) { + loader_unexpand_inst_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list); loader_delete_layer_properties(ptr_instance, @@ -208,7 +228,8 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, /* Remove temporary debug_report callback */ util_DestroyDebugReportCallback(ptr_instance, instance_callback, NULL); - + loader_unexpand_inst_layer_names(saved_layer_count, saved_layer_names, + pCreateInfo); loader_platform_thread_unlock_mutex(&loader_lock); return res; } -- cgit v1.2.3