Log ERROR when layers in VK_INSTANCE_LAYERS are missing
authorCharles Giessen <charles@lunarg.com>
Tue, 18 Apr 2023 19:40:33 +0000 (13:40 -0600)
committerCharles Giessen <charles@lunarg.com>
Tue, 16 May 2023 23:03:28 +0000 (17:03 -0600)
It is unhelpful to have zero diagnostics emitted when the layers listed in
VK_INSTANCE_LAYERS are not found.

loader/loader_environment.c
tests/loader_layer_tests.cpp

index 58e224e76f1eed8f1fba1254bc609a9eee590101..24a47ff2e379e47d04ad7e3ff26e96fedb491839 100644 (file)
@@ -439,24 +439,32 @@ VkResult loader_add_environment_layers(struct loader_instance *inst, const enum
                 char *next = loader_get_next_path(name);
 
                 if (strlen(name) > 0) {
+                    bool found = false;
                     for (uint32_t i = 0; i < source_list->count; i++) {
                         struct loader_layer_properties *source_prop = &source_list->list[i];
 
-                        if (0 == strcmp(name, source_prop->info.layerName) &&
-                            !loader_find_layer_name_in_list(source_prop->info.layerName, target_list)) {
-                            if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
-                                res = loader_add_layer_properties_to_list(inst, target_list, 1, source_prop);
-                                if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
-                                res = loader_add_layer_properties_to_list(inst, expanded_target_list, 1, source_prop);
-                                if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
-                            } else {
-                                res = loader_add_meta_layer(inst, enable_filter, disable_filter, source_prop, target_list,
-                                                            expanded_target_list, source_list, NULL);
-                                if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
+                        if (0 == strcmp(name, source_prop->info.layerName)) {
+                            found = true;
+                            // Only add it if it doesn't already appear in the layer list
+                            if (!loader_find_layer_name_in_list(source_prop->info.layerName, target_list)) {
+                                if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+                                    res = loader_add_layer_properties_to_list(inst, target_list, 1, source_prop);
+                                    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
+                                    res = loader_add_layer_properties_to_list(inst, expanded_target_list, 1, source_prop);
+                                    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
+                                } else {
+                                    res = loader_add_meta_layer(inst, enable_filter, disable_filter, source_prop, target_list,
+                                                                expanded_target_list, source_list, NULL);
+                                    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
+                                }
+                                break;
                             }
-                            break;
                         }
                     }
+                    if (!found) {
+                        loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+                                   "Layer \"%s\" was not found but was requested by env var VK_INSTANCE_LAYERS!", name);
+                    }
                 }
                 name = next;
             }
index c8cc7b48a4a7d2ea84696793d5ddbe7336b36032..7f3a8dfe4935727576e37526c17dfaf7889ee41a 100644 (file)
@@ -4768,6 +4768,93 @@ TEST(TestLayers, EnvironVkInstanceLayersAndDisableFilters) {
     ASSERT_TRUE(env.debug_log.find_prefix_then_postfix(explicit_layer_name_2, "disabled because name matches filter of env var"));
 }
 
+// Verify that layers enabled through VK_INSTANCE_LAYERS which were not found get the proper error message
+TEST(TestLayers, NonExistantLayerInVK_INSTANCE_LAYERS) {
+    FrameworkEnvironment env;
+    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
+    env.get_test_icd().add_physical_device({});
+
+    const char* layer_name = "VK_LAYER_test_layer";
+    env.add_explicit_layer(
+        ManifestLayer{}.add_layer(
+            ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
+        "test_layer.json");
+
+    EnvVarWrapper layers_enable_env_var{"VK_INSTANCE_LAYERS", "VK_LAYER_I_dont_exist"};
+    {
+        InstWrapper inst{env.vulkan_functions};
+        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
+        inst.CheckCreate();
+
+        ASSERT_TRUE(
+            env.debug_log.find("Layer \"VK_LAYER_I_dont_exist\" was not found but was requested by env var VK_INSTANCE_LAYERS!"));
+        auto phys_dev = inst.GetPhysDev();
+        uint32_t count = 1;
+        ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr));
+        ASSERT_EQ(0U, count);
+    }
+    // Make sure layers that do exist are loaded
+    env.debug_log.clear();
+    layers_enable_env_var.add_to_list(layer_name);
+    {
+        InstWrapper inst{env.vulkan_functions};
+        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
+        inst.CheckCreate();
+        ASSERT_TRUE(
+            env.debug_log.find("Layer \"VK_LAYER_I_dont_exist\" was not found but was requested by env var VK_INSTANCE_LAYERS!"));
+        auto phys_dev = inst.GetPhysDev();
+        uint32_t count = 1;
+        VkLayerProperties enabled_layer_prop{};
+        ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &enabled_layer_prop));
+        ASSERT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(enabled_layer_prop.layerName, layer_name));
+    }
+    // Make sure that if the layer appears twice in the env-var nothing bad happens
+    env.debug_log.clear();
+    layers_enable_env_var.add_to_list("VK_LAYER_I_dont_exist");
+    {
+        InstWrapper inst{env.vulkan_functions};
+        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
+        inst.CheckCreate();
+        ASSERT_TRUE(
+            env.debug_log.find("Layer \"VK_LAYER_I_dont_exist\" was not found but was requested by env var VK_INSTANCE_LAYERS!"));
+        auto phys_dev = inst.GetPhysDev();
+        uint32_t count = 1;
+        VkLayerProperties enabled_layer_prop{};
+        ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &enabled_layer_prop));
+        ASSERT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(enabled_layer_prop.layerName, layer_name));
+    }
+}
+
+// Verify that if the same layer appears twice in VK_INSTANCE_LAYERS nothing bad happens
+TEST(TestLayers, DuplicatesInEnvironVK_INSTANCE_LAYERS) {
+    FrameworkEnvironment env;
+    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
+    env.get_test_icd().add_physical_device({});
+
+    const char* layer_name = "VK_LAYER_test_layer";
+    env.add_explicit_layer(
+        ManifestLayer{}.add_layer(
+            ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
+        "test_layer.json");
+
+    EnvVarWrapper layers_enable_env_var{"VK_INSTANCE_LAYERS"};
+
+    layers_enable_env_var.add_to_list(layer_name);
+    layers_enable_env_var.add_to_list(layer_name);
+
+    InstWrapper inst{env.vulkan_functions};
+    FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
+    inst.CheckCreate();
+    auto phys_dev = inst.GetPhysDev();
+    uint32_t count = 1;
+    VkLayerProperties enabled_layer_prop{};
+    ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &enabled_layer_prop));
+    ASSERT_EQ(1U, count);
+    ASSERT_TRUE(string_eq(enabled_layer_prop.layerName, layer_name));
+}
+
 TEST(TestLayers, AppEnabledExplicitLayerFails) {
     FrameworkEnvironment env;
     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));