diff --git a/docs/LoaderDriverInterface.md b/docs/LoaderDriverInterface.md index 791c64c1c..ad600fb4e 100644 --- a/docs/LoaderDriverInterface.md +++ b/docs/LoaderDriverInterface.md @@ -33,6 +33,7 @@ - [Example Linux Driver Search Path](#example-linux-driver-search-path) - [Driver Discovery on Fuchsia](#driver-discovery-on-fuchsia) - [Driver Discovery on macOS](#driver-discovery-on-macos) + - [Use App Bundled Drivers exclusively](#use-app-bundled-drivers-exclusively) - [Example macOS Driver Search Path](#example-macos-driver-search-path) - [Additional Settings For Driver Debugging](#additional-settings-for-driver-debugging) - [Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension](#driver-discovery-using-thevk_lunarg_direct_driver_loading-extension) @@ -512,16 +513,14 @@ The order is similar to the search path on Linux with the exception that the application's bundle resources are searched first: `(bundle)/Contents/Resources/`. -System installed drivers will be ignored if drivers are found inside of the app -bundle. -This is because there is not a standard mechanism in which to distinguish drivers -that happen to be duplicates. -For example, MoltenVK is commonly placed inside application bundles. -If there exists a system installed MoltenVK, the loader will load both the app -bundled and the system installed MoltenVK, leading to potential issues or crashes. -Drivers found through environment variables, such as `VK_DRIVER_FILES`, will be -used regardless of whether there are bundled drivers present or not. +#### Use App Bundled Drivers exclusively +By default, the Vulkan Loader searches various system and user paths +for driver manifests. Defining the environment variable +`VK_LOADER_SEARCH_ONLY_IN_BUNDLE` makes the Vulkan Loader only search +for driver manifests in `(bundle)/Contents/Resources/`. This is +intended for applications including drivers inside of the app bundle +so that any drivers elsewhere on the system do not affect the app. #### Example macOS Driver Search Path diff --git a/docs/LoaderInterfaceArchitecture.md b/docs/LoaderInterfaceArchitecture.md index b0b52c91d..e90e8b104 100644 --- a/docs/LoaderInterfaceArchitecture.md +++ b/docs/LoaderInterfaceArchitecture.md @@ -46,6 +46,7 @@ - [Globs](#globs) - [Case-Insensitive](#case-insensitive) - [Environment Variable Priority](#environment-variable-priority) + - [Multiple Filtering](#multiple-filtering) - [Table of Debug Environment Variables](#table-of-debug-environment-variables) - [Active Environment Variables](#active-environment-variables) - [Deprecated Environment Variables](#deprecated-environment-variables) @@ -1061,6 +1062,26 @@ discovery.   VK_LOADER_DRIVER_ID_FILTER=1-3:13

+ + + VK_LOADER_SEARCH_ONLY_IN_BUNDLE + + + Prevents searching for layer and driver manifests outside of the + Application Bundle. Meant to isolate applications shipping on macOS/iOS + in a bundle from using system installed layers and drivers. + + + macOS/iOS only
+ This functionality is only available with Loaders built with version + 1.4.359 of the Vulkan headers and later. +
+ + export
+   VK_LOADER_SEARCH_ONLY_IN_BUNDLE=1
+
+
+
diff --git a/docs/LoaderLayerInterface.md b/docs/LoaderLayerInterface.md index ea175e132..c07b10afc 100644 --- a/docs/LoaderLayerInterface.md +++ b/docs/LoaderLayerInterface.md @@ -25,6 +25,7 @@ - [Fuchsia Layer Discovery](#fuchsia-layer-discovery) - [macOS Layer Discovery](#macos-layer-discovery) - [Example macOS Implicit Layer Search Path](#example-macos-implicit-layer-search-path) + - [Use App Bundled Layers exclusively](#use-app-bundled-layers-exclusively) - [Layer Filtering](#layer-filtering) - [Layer Enable Filtering](#layer-enable-filtering) - [Layer Disable Filtering](#layer-disable-filtering) @@ -453,6 +454,15 @@ following: /usr/share/vulkan/implicit_layer.d ``` +#### Use App Bundled Layers exclusively + +By default, the Vulkan Loader searches various system and user paths +for layer manifests. Defining the environment variable +`VK_LOADER_SEARCH_ONLY_IN_BUNDLE` makes the Vulkan Loader only search +for layer manifests in `(bundle)/Contents/Resources/`. This is +intended for applications including layers inside of the app bundle +so that any layers elsewhere on the system do not affect the app. + ### Layer Filtering **NOTE:** This functionality is only available with Loaders built with version diff --git a/loader/loader.c b/loader/loader.c index 2574d4f4d..e29184837 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -3501,6 +3501,7 @@ VkResult read_data_files_in_search_paths(const struct loader_instance *inst, enu #if defined(__APPLE__) char *bundle_path = NULL; + char *search_only_in_bundle_env_var = loader_secure_getenv(VK_LOADER_SEARCH_ONLY_IN_BUNDLE_ENV_VAR, inst); #endif #if defined(_WIN32) @@ -3656,6 +3657,8 @@ VkResult read_data_files_in_search_paths(const struct loader_instance *inst, enu } } #elif COMMON_UNIX_PLATFORMS + bool search_outside_of_bundle = true; + rel_size = strlen(relative_location); if (rel_size > 0) { #if defined(__APPLE__) @@ -3714,41 +3717,46 @@ VkResult read_data_files_in_search_paths(const struct loader_instance *inst, enu CFRelease(ref); } } -#endif // __APPLE__ - // Only add the home folders if not NULL - if (NULL != home_config_dir) { - vk_result = copy_data_file_info(inst, home_config_dir, relative_location, rel_size, &search_paths); + if (NULL != search_only_in_bundle_env_var) { + search_outside_of_bundle = false; + } +#endif // __APPLE__ + if (search_outside_of_bundle) { + // Only add the home folders if not NULL + if (NULL != home_config_dir) { + vk_result = copy_data_file_info(inst, home_config_dir, relative_location, rel_size, &search_paths); + if (VK_SUCCESS != vk_result) { + goto out; + } + } + vk_result = copy_data_file_info(inst, xdg_config_dirs, relative_location, rel_size, &search_paths); + if (VK_SUCCESS != vk_result) { + goto out; + } + vk_result = copy_data_file_info(inst, SYSCONFDIR, relative_location, rel_size, &search_paths); if (VK_SUCCESS != vk_result) { goto out; } - } - vk_result = copy_data_file_info(inst, xdg_config_dirs, relative_location, rel_size, &search_paths); - if (VK_SUCCESS != vk_result) { - goto out; - } - vk_result = copy_data_file_info(inst, SYSCONFDIR, relative_location, rel_size, &search_paths); - if (VK_SUCCESS != vk_result) { - goto out; - } #if defined(EXTRASYSCONFDIR) - vk_result = copy_data_file_info(inst, EXTRASYSCONFDIR, relative_location, rel_size, &search_paths); - if (VK_SUCCESS != vk_result) { - goto out; - } + vk_result = copy_data_file_info(inst, EXTRASYSCONFDIR, relative_location, rel_size, &search_paths); + if (VK_SUCCESS != vk_result) { + goto out; + } #endif - // Only add the home folders if not NULL - if (NULL != home_data_dir) { - vk_result = copy_data_file_info(inst, home_data_dir, relative_location, rel_size, &search_paths); + // Only add the home folders if not NULL + if (NULL != home_data_dir) { + vk_result = copy_data_file_info(inst, home_data_dir, relative_location, rel_size, &search_paths); + if (VK_SUCCESS != vk_result) { + goto out; + } + } + vk_result = copy_data_file_info(inst, xdg_data_dirs, relative_location, rel_size, &search_paths); if (VK_SUCCESS != vk_result) { goto out; } } - vk_result = copy_data_file_info(inst, xdg_data_dirs, relative_location, rel_size, &search_paths); - if (VK_SUCCESS != vk_result) { - goto out; - } } #else #warning read_data_files_in_search_paths unsupported platform @@ -3799,6 +3807,7 @@ VkResult read_data_files_in_search_paths(const struct loader_instance *inst, enu #elif COMMON_UNIX_PLATFORMS #if defined(__APPLE__) loader_instance_heap_free(inst, bundle_path); + loader_free_getenv(search_only_in_bundle_env_var, inst); #endif loader_free_getenv(xdg_config_home, inst); loader_free_getenv(xdg_config_dirs, inst); diff --git a/loader/vk_loader_platform.h b/loader/vk_loader_platform.h index 983b820d1..9549017fd 100644 --- a/loader/vk_loader_platform.h +++ b/loader/vk_loader_platform.h @@ -134,6 +134,10 @@ #define VK_VENDOR_ID_FILTER_ENV_VAR "VK_LOADER_VENDOR_ID_FILTER" #define VK_DRIVER_ID_FILTER_ENV_VAR "VK_LOADER_DRIVER_ID_FILTER" +#if defined(__APPLE__) +#define VK_LOADER_SEARCH_ONLY_IN_BUNDLE_ENV_VAR "VK_LOADER_SEARCH_ONLY_IN_BUNDLE" +#endif + // Override layer information #define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override" diff --git a/tests/framework/test_environment.h b/tests/framework/test_environment.h index fe164d401..26acc66f8 100644 --- a/tests/framework/test_environment.h +++ b/tests/framework/test_environment.h @@ -541,7 +541,9 @@ struct FrameworkEnvironment { #if TESTING_COMMON_UNIX_PLATFORMS EnvVarWrapper env_var_home{"HOME", "/home/fake_home"}; -#if !defined(__APPLE__) +#if defined(__APPLE__) + EnvVarWrapper env_var_search_only_in_bundle{"VK_LOADER_SEARCH_ONLY_IN_BUNDLE"}; +#else EnvVarWrapper env_var_xdg_config_home{"XDG_CONFIG_HOME"}; EnvVarWrapper env_var_xdg_config_dirs{"XDG_CONFIG_DIRS"}; EnvVarWrapper env_var_xdg_data_home{"XDG_DATA_HOME"}; diff --git a/tests/loader_regression_tests.cpp b/tests/loader_regression_tests.cpp index eb2196f49..667aae427 100644 --- a/tests/loader_regression_tests.cpp +++ b/tests/loader_regression_tests.cpp @@ -4478,6 +4478,37 @@ TEST(ManifestDiscovery, AppleBundles) { ASSERT_EQ(test_physical_device_0.properties.deviceID, props.deviceID); } +// Add two drivers, one to the bundle and one to the system locations +TEST(ManifestDiscovery, AppleBundlesWithSearchOnlyInBundleEnvVar) { + FrameworkEnvironment env{}; + env.env_var_search_only_in_bundle.set_new_value("1"); + env.setup_macos_bundle(); + env.add_icd(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, + ManifestOptions{}.set_discovery_type(ManifestDiscoveryType::macos_bundle)); + auto& test_physical_device_0 = env.get_test_icd(0).add_and_get_physical_device({}); + test_physical_device_0.properties.deviceID = 1337; + env.add_icd(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA); + auto& test_physical_device_1 = env.get_test_icd(1).add_and_get_physical_device({}); + test_physical_device_1.properties.deviceID = 9999; + + env.add_explicit_layer( + {}, ManifestLayer{}.add_layer( + ManifestLayer::LayerDescription{}.set_name("VK_LAYER_test").set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2))); + + InstWrapper inst{env.vulkan_functions}; + ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); + auto physical_devices = inst.GetPhysDevs(); + ASSERT_EQ(1, physical_devices.size()); + + // should only get bundled driver and layer + VkPhysicalDeviceProperties props{}; + inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props); + ASSERT_EQ(test_physical_device_0.properties.deviceID, props.deviceID); + + // No layers should be found + env.GetLayerProperties(0); +} + // Add two drivers, one to the bundle and one using the driver env-var TEST(ManifestDiscovery, AppleBundlesEnvVarActive) { FrameworkEnvironment env{};