aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Ashburn <jon@lunarg.com>2016-02-10 20:59:26 -0700
committerJon Ashburn <jon@lunarg.com>2016-02-14 09:23:33 -0700
commitabc45636e7d078ea0825bc5c60f12e7b5aa6454d (patch)
tree50b0a0192ef94d0d1fe7df445a87f664816d0f66
parentb6016d806ea0fb79aad3f227aa253ba6a5addebd (diff)
downloadusermoji-abc45636e7d078ea0825bc5c60f12e7b5aa6454d.tar.xz
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.
-rw-r--r--loader/loader.c208
-rw-r--r--loader/loader.h24
-rw-r--r--loader/trampoline.c23
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;
}