Allow implicit layers for all API versions
authorCharles Giessen <charles@lunarg.com>
Thu, 8 Sep 2022 17:50:29 +0000 (11:50 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Thu, 8 Sep 2022 19:48:46 +0000 (13:48 -0600)
This change makes the loader conform to the latests specification
update, 1.3.227, which removes the requirement that implicit layers
API version is at least as high as the application provided API
version.

This change reduces friction for layer developers and API users.

docs/LoaderLayerInterface.md
loader/loader.c
tests/loader_layer_tests.cpp

index 36631684ce179a96fd646247d7450c14cc2e7851..bd6266a609b2c60fa77092bdb439d75890584067 100644 (file)
@@ -1374,14 +1374,23 @@ non-obvious results.
 This not an exhaustive list but should better clarify the behavior of the
 loader in complex situations.
 
-* The API version specified by an implicit layer is used to determine whether
-the layer should be enabled.
-If the layer's API version is less than the version given by the application in `VkApplicationInfo`, the implicit layer is not enabled.
-Thus, any implicit layers must have an API version that is the same or higher
-than the application.
-This applies to implicit meta layers and the override layer.
-Therefore, an application which supports an API version that is newer than any
-implicit meta layers will prevent the meta layer from activating.
+* The Vulkan Loader in versions 1.3.228 and above will enable implicit layers
+regardless of the API version specified by the application in
+`VkApplicationInfo::apiVersion`.
+Previous loader versions (1.3.227 and below) used to have a requirement where
+implicit layer's API version must be equal to or greater than the API version
+of the application for the layer to be enabled.
+The change relaxed the implicit layer loading requirements because it was
+determined that the perceived protection of preventing older layers running
+with newer applications wasn't enough to justify the friction it caused.
+This was due to older layers no longer working with newer applications
+for no apparent reason, as well as older layers having to update the manifest
+to work with newer applications.
+The layer didn't need to do anything else to get their layer working again,
+which meant that a layer didn't need to prove that their layer worked with
+newer API versions.
+Thus, the disabling caused confusion for users but didn't protect them from
+potentially badly behaving layers.
 
 * An implicit layer will ignore its disable environment variable being set if
 it is a component in an active meta layer.
@@ -1713,7 +1722,7 @@ Here's an example of a meta-layer manifest file:
     <td>Optional field which specifies the architecture of the binary associated
         with "library_path". <br />
         Allows the loader to quickly determine if the architecture of the layer
-        matches that of the running application. <br />       
+        matches that of the running application. <br />
         The only valid values are "32" and "64".</td>
     <td><small>N/A</small></td>
   </tr>
index ed0607de587d175fa1f8f1f6521a344225aa0f9e..0ea6009e0536184e19d058da733fce3b3e18c11b 100644 (file)
@@ -957,23 +957,7 @@ bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const
 static void loader_add_implicit_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
                                       struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
                                       const struct loader_layer_list *source_list) {
-    bool enable = loader_implicit_layer_is_enabled(inst, prop);
-
-    // If the implicit layer is supposed to be enable, make sure the layer supports at least the same API version
-    // that the application is asking (i.e. layer's API >= app's API).  If it's not, disable this layer.
-    if (enable) {
-        loader_api_version prop_version = loader_make_version(prop->info.specVersion);
-        if (!loader_check_version_meets_required(inst->app_api_version, prop_version)) {
-            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
-                       "loader_add_implicit_layer: Disabling implicit layer %s for using an old API version %u.%u versus "
-                       "application requested %u.%u",
-                       prop->info.layerName, prop_version.major, prop_version.minor, inst->app_api_version.major,
-                       inst->app_api_version.minor);
-            enable = false;
-        }
-    }
-
-    if (enable) {
+    if (loader_implicit_layer_is_enabled(inst, prop)) {
         if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
             loader_add_layer_properties_to_list(inst, target_list, 1, prop);
             if (NULL != expanded_target_list) {
index de2a7f5f5d86b9a1f7a5144907191be310aa79c9..ec0750047f28bd377830c3dee8c95585e5b5c319 100644 (file)
@@ -661,16 +661,22 @@ TEST(OverrideMetaLayer, OlderVersionThanInstance) {
         ASSERT_TRUE(string_eq(layer_props[0].layerName, regular_layer_name));
         ASSERT_TRUE(string_eq(layer_props[1].layerName, lunarg_meta_layer_name));
     }
-    {  // 1.2 instance
+    {  // 1.3 instance
 
         InstWrapper inst{env.vulkan_functions};
-        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
-
-        inst.create_info.api_version = VK_API_VERSION_1_2;
+        inst.create_info.api_version = VK_API_VERSION_1_3;
         inst.CheckCreate();
-        ASSERT_TRUE(env.debug_log.find(std::string("loader_add_implicit_layer: Disabling implicit layer ") +
-                                       lunarg_meta_layer_name +
-                                       " for using an old API version 1.1 versus application requested 1.2"));
+        VkPhysicalDevice phys_dev = inst.GetPhysDev();
+
+        uint32_t count = 0;
+        env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
+        ASSERT_EQ(2U, count);
+        std::array<VkLayerProperties, 2> layer_props;
+
+        env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, layer_props.data());
+        ASSERT_EQ(2U, count);
+        ASSERT_TRUE(string_eq(layer_props[0].layerName, regular_layer_name));
+        ASSERT_TRUE(string_eq(layer_props[1].layerName, lunarg_meta_layer_name));
     }
 }
 
@@ -725,21 +731,21 @@ TEST(OverrideMetaLayer, OlderMetaLayerWithNewerInstanceVersion) {
     }
 
     {
-        // 1.2 instance
+        // 1.3 instance
         InstWrapper inst{env.vulkan_functions};
-        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
-        inst.create_info.set_api_version(1, 2, 0);
+        inst.create_info.set_api_version(1, 3, 0);
         inst.CheckCreate();
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
-        ASSERT_TRUE(
-            env.debug_log.find("loader_add_implicit_layer: Disabling implicit layer VK_LAYER_LUNARG_override for using an old API "
-                               "version 1.1 versus application requested 1.2"));
+
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        ASSERT_EQ(0U, count);
+        ASSERT_EQ(2U, count);
         std::array<VkLayerProperties, 2> layer_props;
+
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, layer_props.data());
-        ASSERT_EQ(0U, count);
+        ASSERT_EQ(2U, count);
+        ASSERT_TRUE(string_eq(layer_props[0].layerName, regular_layer_name));
+        ASSERT_TRUE(string_eq(layer_props[1].layerName, lunarg_meta_layer_name));
     }
 }
 
@@ -797,24 +803,23 @@ TEST(OverrideMetaLayer, NewerComponentLayerInMetaLayer) {
     }
 
     {
-        // 1.2 instance
+        // 1.3 instance
         InstWrapper inst{env.vulkan_functions};
         FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
-        inst.create_info.set_api_version(1, 2, 0);
+        inst.create_info.set_api_version(1, 3, 0);
         inst.CheckCreate();
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
-        // Meta layer should be disabled since its less than the apiVersion of the instance
-        EXPECT_TRUE(
-            env.debug_log.find("loader_add_implicit_layer: Disabling implicit layer VK_LAYER_LUNARG_override for using an old API "
-                               "version 1.1 versus application requested 1.2"));
+        // Newer component is allowed now
+        EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
         env.debug_log.clear();
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        EXPECT_EQ(0U, count);
+        EXPECT_EQ(2U, count);
         std::array<VkLayerProperties, 2> layer_props;
-        count = 2;
+
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, layer_props.data());
-        EXPECT_EQ(0U, count);
+        EXPECT_EQ(2U, count);
+        EXPECT_TRUE(check_permutation({regular_layer_name, lunarg_meta_layer_name}, layer_props));
     }
 }
 
@@ -2551,7 +2556,10 @@ TEST(TestLayers, NewerInstanceVersionThanImplicitLayer) {
     {  // 1.1 instance - should find the implicit layer
         InstWrapper inst{env.vulkan_functions};
         inst.create_info.set_api_version(1, 1, 0);
+        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
         inst.CheckCreate();
+        EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+        env.debug_log.clear();
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
 
         uint32_t count = 0;
@@ -2562,23 +2570,22 @@ TEST(TestLayers, NewerInstanceVersionThanImplicitLayer) {
         EXPECT_EQ(1U, count);
         ASSERT_TRUE(string_eq(regular_layer_name, layer_props.layerName));
     }
-    {  // 1.2 instance -- instance layer shouldn't be found
-        DebugUtilsLogger log;
+    {  // 1.2 instance -- instance layer should be found
         InstWrapper inst{env.vulkan_functions};
         inst.create_info.set_api_version(1, 2, 0);
-        FillDebugUtilsCreateDetails(inst.create_info, log);
+        FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
         inst.CheckCreate();
-        VkPhysicalDevice phys_dev = inst.GetPhysDev();
-
-        ASSERT_TRUE(log.find(std::string("loader_add_implicit_layer: Disabling implicit layer ") + regular_layer_name +
-                             " for using an old API version 1.1 versus application requested 1.2"));
+        EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+        env.debug_log.clear();
 
+        VkPhysicalDevice phys_dev = inst.GetPhysDev();
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
         VkLayerProperties layer_props{};
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &layer_props);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(regular_layer_name, layer_props.layerName));
     }
 }
 
@@ -2609,55 +2616,54 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
         EXPECT_EQ(layer_count, 1U);
         EXPECT_TRUE(string_eq(layer_props[0].layerName, regular_layer_name));
     }
-    {  // 1.0 instance -- instance layer should be found
+    {  // 1.0 instance
         DebugUtilsLogger log;
         InstWrapper inst{env.vulkan_functions};
         inst.create_info.set_api_version(1, 0, 0);
         FillDebugUtilsCreateDetails(inst.create_info, log);
         inst.CheckCreate();
-        ASSERT_TRUE(log.find(std::string("loader_add_implicit_layer: Disabling implicit layer ") + regular_layer_name +
-                             " for using an old API version 0.1 versus application requested 1.0"));
+        EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
 
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
         VkLayerProperties layer_props{};
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &layer_props);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(regular_layer_name, layer_props.layerName));
     }
-    {  // 1.1 instance -- instance layer should be found
+    {  // 1.1 instance
         DebugUtilsLogger log;
         InstWrapper inst{env.vulkan_functions};
         inst.create_info.set_api_version(1, 1, 0);
         FillDebugUtilsCreateDetails(inst.create_info, log);
         inst.CheckCreate();
-        ASSERT_TRUE(log.find(std::string("loader_add_implicit_layer: Disabling implicit layer ") + regular_layer_name +
-                             " for using an old API version 0.1 versus application requested 1.1"));
+        EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
         VkLayerProperties layer_props{};
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &layer_props);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(regular_layer_name, layer_props.layerName));
     }
-    {  // 1.2 instance -- instance layer shouldn't be found
+    {  // 1.2 instance
         DebugUtilsLogger log;
         InstWrapper inst{env.vulkan_functions};
         inst.create_info.set_api_version(1, 2, 0);
         FillDebugUtilsCreateDetails(inst.create_info, log);
         inst.CheckCreate();
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
-        ASSERT_TRUE(log.find(std::string("loader_add_implicit_layer: Disabling implicit layer ") + regular_layer_name +
-                             " for using an old API version 0.1 versus application requested 1.2"));
-
+        EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
         VkLayerProperties layer_props{};
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &layer_props);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(regular_layer_name, layer_props.layerName));
     }
     {  // application doesn't state its API version
         DebugUtilsLogger log;
@@ -2665,16 +2671,16 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
         inst.create_info.set_fill_in_application_info(false);
         FillDebugUtilsCreateDetails(inst.create_info, log);
         inst.CheckCreate();
-        EXPECT_TRUE(log.find(std::string("loader_add_implicit_layer: Disabling implicit layer ") + regular_layer_name +
-                             " for using an old API version 0.1 versus application requested 1.0"));
+        EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
         VkPhysicalDevice phys_dev = inst.GetPhysDev();
 
         uint32_t count = 0;
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
         VkLayerProperties layer_props{};
         env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, &layer_props);
-        ASSERT_EQ(0U, count);
+        EXPECT_EQ(1U, count);
+        ASSERT_TRUE(string_eq(regular_layer_name, layer_props.layerName));
     }
 }