diff options
author | Charles Giessen <charles@lunarg.com> | 2022-12-06 13:45:15 -0700 |
---|---|---|
committer | Charles Giessen <46324611+charles-lunarg@users.noreply.github.com> | 2023-01-09 16:25:53 -0700 |
commit | 52ffa76190da257f6f0c99c61ebc7a69ebda356e (patch) | |
tree | f4de58e93ba275c394067f04bf16b5c4d266dc14 | |
parent | 12c169db136f8f906803b429df88cb6f50698497 (diff) | |
download | Vulkan-Loader-52ffa76190da257f6f0c99c61ebc7a69ebda356e.tar.gz Vulkan-Loader-52ffa76190da257f6f0c99c61ebc7a69ebda356e.tar.bz2 Vulkan-Loader-52ffa76190da257f6f0c99c61ebc7a69ebda356e.zip |
Add macOS bundles support to test framework
Allow basic tests to be written which exercise the bundle discovery and loading logic
in the loader. This allows testing whether drivers found in bundles disables searching
for drivers on the rest of the system.
This commit also inclues fixes for a half dozen non essential spelling mistakes.
-rw-r--r-- | loader/loader.c | 2 | ||||
-rw-r--r-- | loader/trampoline.c | 6 | ||||
-rw-r--r-- | tests/framework/shim/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/framework/shim/shim.h | 4 | ||||
-rw-r--r-- | tests/framework/shim/shim_common.cpp | 13 | ||||
-rw-r--r-- | tests/framework/shim/unix_shim.cpp | 36 | ||||
-rw-r--r-- | tests/framework/test_environment.cpp | 23 | ||||
-rw-r--r-- | tests/framework/test_environment.h | 7 | ||||
-rw-r--r-- | tests/framework/test_util.h | 2 | ||||
-rw-r--r-- | tests/loader_regression_tests.cpp | 48 |
10 files changed, 130 insertions, 12 deletions
diff --git a/loader/loader.c b/loader/loader.c index c1af4a31..fff5ca9b 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -127,7 +127,7 @@ loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32 bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) { // major version is satisfied return (version.major > required.major) || - // major version is equal, minor version is patch version is gerater to minimum minor + // major version is equal, minor version is patch version is greater to minimum minor (version.major == required.major && version.minor > required.minor) || // major and minor version are equal, patch version is greater or equal to minimum patch (version.major == required.major && version.minor == required.minor && version.patch >= required.patch); diff --git a/loader/trampoline.c b/loader/trampoline.c index 9066a087..740898ff 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -38,7 +38,7 @@ // Trampoline entrypoints are in this file for core Vulkan commands -/* vkGetInstanceProcAddr: Get global level or instance level entrypoint addressess. +/* vkGetInstanceProcAddr: Get global level or instance level entrypoint addresses. * @param instance * @param pName * @return @@ -55,7 +55,7 @@ * * Note: * Vulkan header updated 1.2.193 changed the behavior of vkGetInstanceProcAddr for global entrypoints. They used to always be - * returned regardless of the value of the instance paramtere. The spec was amended in this version to only allow querying global + * returned regardless of the value of the instance parameter. The spec was amended in this version to only allow querying global * level entrypoints with a NULL instance. However, as to not break old applications, the new behavior is only applied if the * instance passed in is both valid and minor version is greater than 1.2, which was when this change in behavior occurred. Only * instances with a newer version will get the new behavior. @@ -2131,7 +2131,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(VkCommandBuffer commandB const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer); if (NULL == disp) { loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0, - "vkCmdCopyImage: Invalid commandBuffer [VUID-vkCmdCopyImage-devcommandBufferice-parameter]"); + "vkCmdCopyImage: Invalid commandBuffer [VUID-vkCmdCopyImage-commandBuffer-parameter]"); abort(); /* Intentionally fail so user can correct issue. */ } diff --git a/tests/framework/shim/CMakeLists.txt b/tests/framework/shim/CMakeLists.txt index 82c2573f..919dd362 100644 --- a/tests/framework/shim/CMakeLists.txt +++ b/tests/framework/shim/CMakeLists.txt @@ -31,6 +31,7 @@ if (WIN32) elseif(UNIX) if(APPLE) add_library(shim-library SHARED unix_shim.cpp) + target_link_libraries(shim-library PRIVATE "-framework CoreFoundation") else() add_library(shim-library STATIC unix_shim.cpp) endif() diff --git a/tests/framework/shim/shim.h b/tests/framework/shim/shim.h index b619465e..44d54dd1 100644 --- a/tests/framework/shim/shim.h +++ b/tests/framework/shim/shim.h @@ -194,6 +194,10 @@ struct PlatformShim { bool use_fake_elevation = false; std::vector<DirEntry> dir_entries; + + #if defined(__APPLE__) + std::string bundle_contents; + #endif #endif }; diff --git a/tests/framework/shim/shim_common.cpp b/tests/framework/shim/shim_common.cpp index 2c16a8a5..02f71b85 100644 --- a/tests/framework/shim/shim_common.cpp +++ b/tests/framework/shim/shim_common.cpp @@ -180,10 +180,15 @@ void PlatformShim::redirect_category(fs::path const& new_path, ManifestCategory paths.push_back((home / ".config").str()); paths.push_back((home / ".local/share").str()); } - parse_and_add_env_var_override(paths, get_env_var("XDG_CONFIG_DIRS")); - parse_and_add_env_var_override(paths, get_env_var("XDG_CONFIG_HOME")); - parse_and_add_env_var_override(paths, get_env_var("XDG_DATA_DIRS")); - parse_and_add_env_var_override(paths, get_env_var("XDG_DATA_HOME")); + // Don't report errors on apple - these env-vars are not suppose to be defined + bool report_errors = true; +#if defined(__APPLE__) + report_errors = false; +#endif + parse_and_add_env_var_override(paths, get_env_var("XDG_CONFIG_DIRS", report_errors)); + parse_and_add_env_var_override(paths, get_env_var("XDG_CONFIG_HOME", report_errors)); + parse_and_add_env_var_override(paths, get_env_var("XDG_DATA_DIRS", report_errors)); + parse_and_add_env_var_override(paths, get_env_var("XDG_DATA_HOME", report_errors)); if (category == ManifestCategory::explicit_layer) { parse_and_add_env_var_override(paths, get_env_var("VK_LAYER_PATH", false)); // don't report failure } diff --git a/tests/framework/shim/unix_shim.cpp b/tests/framework/shim/unix_shim.cpp index e930293b..1f039420 100644 --- a/tests/framework/shim/unix_shim.cpp +++ b/tests/framework/shim/unix_shim.cpp @@ -27,6 +27,12 @@ #include "shim.h" +#include <algorithm> + +#if defined(__APPLE__) +#include <CoreFoundation/CoreFoundation.h> +#endif + static PlatformShim platform_shim; extern "C" { #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) @@ -270,6 +276,29 @@ FRAMEWORK_EXPORT char* __SECURE_GETENV_FUNC_NAME(const char* name) { } #endif +#if defined(__APPLE__) +FRAMEWORK_EXPORT CFBundleRef my_CFBundleGetMainBundle() { + static CFBundleRef global_bundle{}; + return reinterpret_cast<CFBundleRef>(&global_bundle); +} +FRAMEWORK_EXPORT CFURLRef my_CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) { + static CFURLRef global_url{}; + return reinterpret_cast<CFURLRef>(&global_url); +} +FRAMEWORK_EXPORT Boolean my_CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, UInt8* buffer, + CFIndex maxBufLen) { + if (!platform_shim.bundle_contents.empty()) { + size_t copy_len = platform_shim.bundle_contents.size(); + if (copy_len > maxBufLen) { + copy_len = maxBufLen; + } + strncpy(reinterpret_cast<char*>(buffer), platform_shim.bundle_contents.c_str(), copy_len); + return TRUE; + } + return FALSE; +} +#endif + /* Shiming functions on apple is limited by the linker prefering to not use functions in the * executable in loaded dylibs. By adding an interposer, we redirect the linker to use our * version of the function over the real one, thus shimming the system function. @@ -299,5 +328,12 @@ __attribute__((used)) static Interposer _interpose_secure_getenv MACOS_ATTRIB = __attribute__((used)) static Interposer _interpose__secure_getenv MACOS_ATTRIB = {VOIDP_CAST(my__secure_getenv), VOIDP_CAST(__secure_getenv)}; #endif +__attribute__((used)) static Interposer _interpose_CFBundleGetMainBundle MACOS_ATTRIB = {VOIDP_CAST(my_CFBundleGetMainBundle), + VOIDP_CAST(CFBundleGetMainBundle)}; +__attribute__((used)) static Interposer _interpose_CFBundleCopyResourcesDirectoryURL MACOS_ATTRIB = { + VOIDP_CAST(my_CFBundleCopyResourcesDirectoryURL), VOIDP_CAST(CFBundleCopyResourcesDirectoryURL)}; +__attribute__((used)) static Interposer _interpose_CFURLGetFileSystemRepresentation MACOS_ATTRIB = { + VOIDP_CAST(my_CFURLGetFileSystemRepresentation), VOIDP_CAST(CFURLGetFileSystemRepresentation)}; + #endif } // extern "C" diff --git a/tests/framework/test_environment.cpp b/tests/framework/test_environment.cpp index 308230e6..079bbcd9 100644 --- a/tests/framework/test_environment.cpp +++ b/tests/framework/test_environment.cpp @@ -360,6 +360,7 @@ FrameworkEnvironment::FrameworkEnvironment(bool enable_log, bool set_default_sea folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("implicit_layer_manifests")); folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("override_layer_manifests")); folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("app_package_manifests")); + folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("macos_bundle")); platform_shim->redirect_all_paths(get_folder(ManifestLocation::null).location()); if (set_default_search_paths) { @@ -367,6 +368,13 @@ FrameworkEnvironment::FrameworkEnvironment(bool enable_log, bool set_default_sea platform_shim->set_path(ManifestCategory::explicit_layer, get_folder(ManifestLocation::explicit_layer).location()); platform_shim->set_path(ManifestCategory::implicit_layer, get_folder(ManifestLocation::implicit_layer).location()); } +#if defined(__APPLE__) + // Necessary since bundles look in sub folders for manifests, not the test framework folder itself + auto bundle_location = get_folder(ManifestLocation::macos_bundle).location(); + platform_shim->redirect_path(bundle_location / "vulkan/icd.d", bundle_location); + platform_shim->redirect_path(bundle_location / "vulkan/explicit_layer.d", bundle_location); + platform_shim->redirect_path(bundle_location / "vulkan/implicit_layer.d", bundle_location); +#endif } void FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept { @@ -379,6 +387,9 @@ void FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept { if (icd_details.discovery_type == ManifestDiscoveryType::windows_app_package) { folder = &get_folder(ManifestLocation::windows_app_package); } + if (icd_details.discovery_type == ManifestDiscoveryType::macos_bundle) { + folder = &get_folder(ManifestLocation::macos_bundle); + } if (!icd_details.is_fake) { fs::path new_driver_name = fs::path(icd_details.icd_manifest.lib_path).stem() + "_" + std::to_string(cur_icd_index) + fs::path(icd_details.icd_manifest.lib_path).extension(); @@ -415,6 +426,8 @@ void FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept { add_env_var_vk_icd_filenames += (folder->location() / full_json_name).str(); set_env_var("VK_ADD_DRIVER_FILES", add_env_var_vk_icd_filenames); break; + case (ManifestDiscoveryType::macos_bundle): + platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path); case (ManifestDiscoveryType::none): break; #ifdef _WIN32 @@ -456,7 +469,7 @@ void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, Manife if (!env_var_vk_layer_paths.empty()) { env_var_vk_layer_paths += OS_ENV_VAR_LIST_SEPARATOR; } - if(layer_details.is_dir) { + if (layer_details.is_dir) { env_var_vk_layer_paths += fs_ptr->location().str(); } else { env_var_vk_layer_paths += fs_ptr->location().str() + OS_ENV_VAR_LIST_SEPARATOR + layer_details.json_name; @@ -475,6 +488,9 @@ void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, Manife case (ManifestDiscoveryType::override_folder): fs_ptr = &get_folder(ManifestLocation::override_layer); break; + case (ManifestDiscoveryType::macos_bundle): + fs_ptr = &(get_folder(ManifestLocation::macos_bundle)); + break; case (ManifestDiscoveryType::none): break; } @@ -520,6 +536,11 @@ fs::FolderManager& FrameworkEnvironment::get_folder(ManifestLocation location) n // index it directly using the enum location since they will always be in that order return folders.at(static_cast<size_t>(location)); } +#if defined(__APPLE__) +void FrameworkEnvironment::setup_macos_bundle() noexcept { + platform_shim->bundle_contents = get_folder(ManifestLocation::macos_bundle).location().str(); +} +#endif const char* get_platform_wsi_extension(const char* api_selection) { #if defined(VK_USE_PLATFORM_ANDROID_KHR) return "VK_KHR_android_surface"; diff --git a/tests/framework/test_environment.h b/tests/framework/test_environment.h index bcc39bfe..a04c9e2e 100644 --- a/tests/framework/test_environment.h +++ b/tests/framework/test_environment.h @@ -456,6 +456,7 @@ enum class ManifestDiscoveryType { add_env_var, // use the corresponding add-env-var for it override_folder, // add to a special folder for the override layer to use windows_app_package, // let the app package search find it + macos_bundle, // place it in a location only accessible to macos bundles }; struct TestICDDetails { @@ -490,6 +491,7 @@ enum class ManifestLocation { implicit_layer = 6, override_layer = 7, windows_app_package = 8, + macos_bundle = 9, }; struct FrameworkEnvironment { @@ -516,7 +518,10 @@ struct FrameworkEnvironment { fs::path get_layer_manifest_path(size_t index = 0) noexcept; fs::FolderManager& get_folder(ManifestLocation location) noexcept; - +#if defined(__APPLE__) + // Set the path of the app bundle to the appropriate test framework bundle + void setup_macos_bundle() noexcept; +#endif PlatformShimWrapper platform_shim; std::vector<fs::FolderManager> folders; diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h index 4e20eb62..98aa3758 100644 --- a/tests/framework/test_util.h +++ b/tests/framework/test_util.h @@ -169,7 +169,7 @@ struct path { path operator/(std::string const& in) const; path operator/(const char* in) const; - // accesors + // accessors path parent_path() const; bool has_parent_path() const; path filename() const; diff --git a/tests/loader_regression_tests.cpp b/tests/loader_regression_tests.cpp index 204a1c80..0cbfc143 100644 --- a/tests/loader_regression_tests.cpp +++ b/tests/loader_regression_tests.cpp @@ -2347,7 +2347,7 @@ TEST(EnumeratePhysicalDeviceGroups, FakePNext) { // NOTE: This is a fake struct to make sure the pNext chain is properly passed down to the ICD // vkEnumeratePhysicalDeviceGroups. // The two versions must match: - // "FakePNext" test in loader_regresion_tests.cpp + // "FakePNext" test in loader_regression_tests.cpp // "test_vkEnumeratePhysicalDeviceGroups" in test_icd.cpp struct FakePnextSharedWithICD { VkStructureType sType; @@ -3643,3 +3643,49 @@ TEST(ManifestDiscovery, InvalidSymlink) { inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER); } #endif + +#if defined(__APPLE__) +// Add two drivers, one to the bundle and one to the system locations +TEST(ManifestDiscovery, AppleBundles) { + FrameworkEnvironment env{}; + env.setup_macos_bundle(); + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::macos_bundle)); + env.get_test_icd(0).physical_devices.push_back({}); + env.get_test_icd(0).physical_devices.at(0).properties.deviceID = 1337; + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)); + env.get_test_icd(1).physical_devices.push_back({}); + env.get_test_icd(1).physical_devices.at(0).properties.deviceID = 9999; + + InstWrapper inst{env.vulkan_functions}; + ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); + auto physical_devices = inst.GetPhysDevs(); + ASSERT_EQ(1, physical_devices.size()); + + // Verify that this is the 'right' GPU, aka the one from the bundle + VkPhysicalDeviceProperties props{}; + inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props); + ASSERT_EQ(env.get_test_icd(0).physical_devices.at(0).properties.deviceID, props.deviceID); +} + +// Add two drivers, one to the bundle and one using the driver env-var +TEST(ManifestDiscovery, AppleBundlesEnvVarActive) { + FrameworkEnvironment env{}; + env.setup_macos_bundle(); + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::macos_bundle)); + env.get_test_icd(0).physical_devices.push_back({}); + env.get_test_icd(0).physical_devices.at(0).properties.deviceID = 1337; + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::env_var)); + env.get_test_icd(1).physical_devices.push_back({}); + env.get_test_icd(1).physical_devices.at(0).properties.deviceID = 9999; + + InstWrapper inst{env.vulkan_functions}; + ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); + auto physical_devices = inst.GetPhysDevs(); + ASSERT_EQ(1, physical_devices.size()); + + // Verify that this is the 'right' GPU, aka the one from the env-var + VkPhysicalDeviceProperties props{}; + inst->vkGetPhysicalDeviceProperties(physical_devices[0], &props); + ASSERT_EQ(env.get_test_icd(1).physical_devices.at(0).properties.deviceID, props.deviceID); +} +#endif |