mirror of
https://github.com/openharmony/third_party_vulkan-loader.git
synced 2026-07-25 07:45:21 -04:00
759d5b4c94
Add "additive" environment variables for adding additional layer paths or driver JSON files instead of replacing default ones. Also, rename VK_ICD_FILENAMES to VK_DRIVER_FILES since we're trying to remove references to ICDs because software driver implementations of Vulkan aren't ICDs (but continue to support the old name as well). Added documentation around these changes to reflect the new name and the new variables.
352 lines
14 KiB
C++
352 lines
14 KiB
C++
/*
|
|
* Copyright (c) 2021-2022 The Khronos Group Inc.
|
|
* Copyright (c) 2021-2022 Valve Corporation
|
|
* Copyright (c) 2021-2022 LunarG, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and/or associated documentation files (the "Materials"), to
|
|
* deal in the Materials without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Materials, and to permit persons to whom the Materials are
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice(s) and this permission notice shall be included in
|
|
* all copies or substantial portions of the Materials.
|
|
*
|
|
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
*
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
|
|
* USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
*
|
|
* Author: Charles Giessen <charles@lunarg.com>
|
|
* Author: Mark Young <markylunarg.com>
|
|
*/
|
|
|
|
#include "test_environment.h"
|
|
|
|
class EnvVarICDOverrideSetup : public ::testing::Test {
|
|
protected:
|
|
virtual void SetUp() {
|
|
remove_env_var("VK_ICD_FILENAMES");
|
|
remove_env_var("VK_DRIVER_FILES");
|
|
remove_env_var("VK_ADD_DRIVER_FILES");
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
remove_env_var("VK_ICD_FILENAMES");
|
|
remove_env_var("VK_DRIVER_FILES");
|
|
remove_env_var("VK_ADD_DRIVER_FILES");
|
|
}
|
|
};
|
|
|
|
// Don't support vk_icdNegotiateLoaderICDInterfaceVersion
|
|
// Loader calls vk_icdGetInstanceProcAddr second
|
|
// does not support vk_icdGetInstanceProcAddr
|
|
// must export vkGetInstanceProcAddr, vkCreateInstance, vkEnumerateInstanceExtensionProperties
|
|
TEST(EnvVarICDOverrideSetup, version_0_none) {
|
|
FrameworkEnvironment env{};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NONE).set_use_env_var_icd_filenames(true));
|
|
|
|
InstWrapper inst{env.vulkan_functions};
|
|
inst.CheckCreate();
|
|
|
|
ASSERT_EQ(env.get_test_icd(0).called_vk_icd_gipa, CalledICDGIPA::vk_gipa);
|
|
}
|
|
|
|
// Don't support vk_icdNegotiateLoaderICDInterfaceVersion
|
|
// the loader calls vk_icdGetInstanceProcAddr first
|
|
TEST(EnvVarICDOverrideSetup, version_1_icd_gipa) {
|
|
FrameworkEnvironment env{};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA).set_use_env_var_icd_filenames(true));
|
|
|
|
InstWrapper inst{env.vulkan_functions};
|
|
inst.CheckCreate();
|
|
|
|
ASSERT_EQ(env.get_test_icd(0).called_vk_icd_gipa, CalledICDGIPA::vk_icd_gipa);
|
|
}
|
|
|
|
// support vk_icdNegotiateLoaderICDInterfaceVersion but not vk_icdGetInstanceProcAddr
|
|
// should assert that `interface_vers == 0` due to version mismatch, only checkable in Debug Mode
|
|
TEST(EnvVarICDOverrideSetup, version_negotiate_interface_version_death_test) {
|
|
FrameworkEnvironment env{};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NEGOTIATE_INTERFACE_VERSION).set_use_env_var_icd_filenames(true));
|
|
|
|
InstWrapper inst{env.vulkan_functions};
|
|
|
|
#if !defined(NDEBUG)
|
|
#if defined(WIN32)
|
|
ASSERT_DEATH(inst.CheckCreate(), "");
|
|
#else
|
|
ASSERT_DEATH(inst.CheckCreate(), "interface_vers == 0");
|
|
#endif
|
|
#else
|
|
inst.CheckCreate();
|
|
#endif
|
|
}
|
|
|
|
// export vk_icdNegotiateLoaderICDInterfaceVersion and vk_icdGetInstanceProcAddr
|
|
TEST(EnvVarICDOverrideSetup, version_2_negotiate_interface_version_and_icd_gipa) {
|
|
FrameworkEnvironment env{};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_use_env_var_icd_filenames(true));
|
|
|
|
InstWrapper inst{env.vulkan_functions};
|
|
inst.CheckCreate();
|
|
|
|
ASSERT_EQ(env.get_test_icd(0).called_vk_icd_gipa, CalledICDGIPA::vk_icd_gipa);
|
|
}
|
|
|
|
// Test VK_DRIVER_FILES environment variable
|
|
TEST(EnvVarICDOverrideSetup, TestOnlyDriverEnvVar) {
|
|
FrameworkEnvironment env{DebugMode::none, true};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NONE).set_use_env_var_icd_filenames(true));
|
|
env.get_test_icd(0).physical_devices.emplace_back("pd0");
|
|
|
|
InstWrapper inst1{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
|
|
inst1.CheckCreate();
|
|
EXPECT_FALSE(
|
|
env.debug_log.find("Ignoring override VK_ICD_FILENAMES, VK_DRIVER_FILES, and VK_ADD_DRIVER_FILES due to high-integrity"));
|
|
|
|
std::array<VkPhysicalDevice, 5> phys_devs_array;
|
|
uint32_t phys_dev_count = 1;
|
|
ASSERT_EQ(inst1->vkEnumeratePhysicalDevices(inst1.inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
|
|
ASSERT_EQ(phys_dev_count, 1);
|
|
|
|
for (uint32_t add = 0; add < 2; ++add) {
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NONE).set_use_env_var_icd_filenames(true));
|
|
env.get_test_icd(add + 1).physical_devices.emplace_back("pd" + std::to_string(add) + "0");
|
|
env.get_test_icd(add + 1).physical_devices.emplace_back("pd" + std::to_string(add) + "1");
|
|
}
|
|
|
|
env.debug_log.clear();
|
|
|
|
InstWrapper inst2{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
|
|
inst2.CheckCreate();
|
|
|
|
phys_dev_count = 5;
|
|
ASSERT_EQ(inst2->vkEnumeratePhysicalDevices(inst2.inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
|
|
ASSERT_EQ(phys_dev_count, 5);
|
|
|
|
env.debug_log.clear();
|
|
|
|
env.platform_shim->set_elevated_privilege(true);
|
|
|
|
InstWrapper inst3{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
|
|
inst3.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
|
|
|
|
EXPECT_TRUE(env.debug_log.find("vkCreateInstance: Found no drivers!"));
|
|
|
|
env.platform_shim->set_elevated_privilege(false);
|
|
|
|
remove_env_var("VK_DRIVER_FILES");
|
|
}
|
|
|
|
#if defined(__linux__) || defined(__FreeBSD__)
|
|
// Make sure the loader reports the correct message based on if USE_UNSAFE_FILE_SEARCH is set or not
|
|
TEST(EnvVarICDOverrideSetup, NonSecureEnvVarLookup) {
|
|
FrameworkEnvironment env{};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
|
|
env.get_test_icd().physical_devices.emplace_back("physical_device_0");
|
|
|
|
DebugUtilsLogger log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
|
|
InstWrapper inst{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst.create_info, log);
|
|
inst.CheckCreate();
|
|
|
|
#if !defined(USE_UNSAFE_FILE_SEARCH)
|
|
ASSERT_FALSE(log.find("Loader is using non-secure environment variable lookup for"));
|
|
#else
|
|
ASSERT_TRUE(log.find("Loader is using non-secure environment variable lookup for"));
|
|
#endif
|
|
}
|
|
|
|
// Check for proper handling of paths specified via environment variables.
|
|
TEST(EnvVarICDOverrideSetup, XDG) {
|
|
// Set up a layer path that includes default and user-specified locations,
|
|
// so that the test app can find them. Include some badly specified elements as well.
|
|
// Need to redirect the 'home' directory
|
|
fs::path HOME = "/home/fake_home";
|
|
set_env_var("HOME", HOME.str());
|
|
set_env_var("XDG_CONFIG_DIRS", ":/tmp/goober:::::/tmp/goober/::::");
|
|
set_env_var("XDG_CONFIG_HOME", ":/tmp/goober:::::/tmp/goober2/::::");
|
|
set_env_var("XDG_DATA_DIRS", "::::/tmp/goober3:/tmp/goober4/with spaces:::");
|
|
set_env_var("XDG_DATA_HOME", "::::/tmp/goober3:/tmp/goober4/with spaces:::");
|
|
|
|
FrameworkEnvironment env{};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
|
|
env.get_test_icd().physical_devices.push_back({});
|
|
|
|
InstWrapper inst{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
|
|
inst.CheckCreate();
|
|
|
|
auto check_paths = [](DebugUtilsLogger const& debug_log, ManifestCategory category, fs::path const& HOME) {
|
|
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober/vulkan") / category_path_name(category)).str()));
|
|
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober2/vulkan") / category_path_name(category)).str()));
|
|
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober3/vulkan") / category_path_name(category)).str()));
|
|
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober4/with spaces/vulkan") / category_path_name(category)).str()));
|
|
};
|
|
check_paths(env.debug_log, ManifestCategory::icd, HOME);
|
|
check_paths(env.debug_log, ManifestCategory::implicit_layer, HOME);
|
|
check_paths(env.debug_log, ManifestCategory::explicit_layer, HOME);
|
|
}
|
|
#endif
|
|
|
|
// Test VK_ADD_DRIVER_FILES environment variable
|
|
TEST(EnvVarICDOverrideSetup, TestOnlyAddDriverEnvVar) {
|
|
FrameworkEnvironment env{DebugMode::none, true};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NONE).set_use_add_env_var_icd_filenames(true));
|
|
env.get_test_icd(0).physical_devices.emplace_back("pd0");
|
|
|
|
InstWrapper inst1{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
|
|
inst1.CheckCreate();
|
|
|
|
std::array<VkPhysicalDevice, 1> phys_devs_array;
|
|
uint32_t phys_dev_count = 1;
|
|
ASSERT_EQ(inst1->vkEnumeratePhysicalDevices(inst1.inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
|
|
ASSERT_EQ(phys_dev_count, 1);
|
|
|
|
env.platform_shim->set_elevated_privilege(true);
|
|
|
|
InstWrapper inst2{env.vulkan_functions};
|
|
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
|
|
inst2.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
|
|
|
|
EXPECT_TRUE(env.debug_log.find("vkCreateInstance: Found no drivers!"));
|
|
|
|
env.platform_shim->set_elevated_privilege(false);
|
|
|
|
remove_env_var("VK_ADD_DRIVER_FILES");
|
|
}
|
|
|
|
// Test Both VK_DRIVER_FILES and VK_ADD_DRIVER_FILES environment variable
|
|
TEST(EnvVarICDOverrideSetup, TestBothDriverEnvVars) {
|
|
FrameworkEnvironment env{DebugMode::none, true};
|
|
|
|
// Add a driver that isn't enabled with the environment variable
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NONE).set_use_env_var_icd_filenames(true));
|
|
env.get_test_icd(0).physical_devices.emplace_back("pd0");
|
|
env.get_test_icd(0).physical_devices.emplace_back("pd1");
|
|
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_NONE).set_use_add_env_var_icd_filenames(true));
|
|
env.get_test_icd(0).physical_devices.emplace_back("pd2");
|
|
|
|
InstWrapper inst{env.vulkan_functions};
|
|
inst.CheckCreate();
|
|
|
|
// The enumerate should now detect both drivers because we used the add
|
|
std::array<VkPhysicalDevice, 3> phys_devs_array;
|
|
uint32_t phys_dev_count = 3;
|
|
ASSERT_EQ(inst->vkEnumeratePhysicalDevices(inst.inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
|
|
ASSERT_EQ(phys_dev_count, 3);
|
|
|
|
remove_env_var("VK_DRIVER_FILES");
|
|
remove_env_var("VK_ADD_DRIVER_FILES");
|
|
}
|
|
|
|
#if defined(__linux__) || defined(__FreeBSD__)
|
|
// Test VK_LAYER_PATH environment variable
|
|
TEST(EnvVarICDOverrideSetup, TestOnlyLayerEnvVar) {
|
|
// Set up a layer path that includes default and user-specified locations,
|
|
// so that the test app can find them. Include some badly specified elements as well.
|
|
// Need to redirect the 'home' directory
|
|
fs::path HOME = "/home/fake_home";
|
|
set_env_var("HOME", HOME.str());
|
|
std::string vk_layer_path = ":/tmp/carol::::/:";
|
|
vk_layer_path += (HOME / "/ with spaces/:::::/tandy:").str();
|
|
set_env_var("VK_LAYER_PATH", vk_layer_path);
|
|
|
|
FrameworkEnvironment env{DebugMode::none, false, true};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
|
|
env.get_test_icd().physical_devices.push_back({});
|
|
env.platform_shim->redirect_path("/tmp/carol", env.explicit_layer_folder.location());
|
|
|
|
const char* layer_name = "TestLayer";
|
|
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");
|
|
|
|
InstWrapper inst1{env.vulkan_functions};
|
|
inst1.create_info.add_layer(layer_name);
|
|
FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
|
|
inst1.CheckCreate();
|
|
|
|
// look for VK_LAYER_PATHS
|
|
EXPECT_TRUE(env.debug_log.find("/tmp/carol"));
|
|
EXPECT_TRUE(env.debug_log.find("/tandy"));
|
|
EXPECT_TRUE(env.debug_log.find((HOME / "/ with spaces/").str()));
|
|
|
|
env.debug_log.clear();
|
|
|
|
env.platform_shim->set_elevated_privilege(true);
|
|
|
|
InstWrapper inst2{env.vulkan_functions};
|
|
inst2.create_info.add_layer(layer_name);
|
|
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
|
|
inst2.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
|
|
|
|
EXPECT_FALSE(env.debug_log.find("/tmp/carol"));
|
|
|
|
env.platform_shim->set_elevated_privilege(false);
|
|
|
|
remove_env_var("VK_LAYER_PATH");
|
|
}
|
|
|
|
// Test VK_ADD_LAYER_PATH environment variable
|
|
TEST(EnvVarICDOverrideSetup, TestOnlyAddLayerEnvVar) {
|
|
// Set up a layer path that includes default and user-specified locations,
|
|
// so that the test app can find them. Include some badly specified elements as well.
|
|
// Need to redirect the 'home' directory
|
|
fs::path HOME = "/home/fake_home";
|
|
set_env_var("HOME", HOME.str());
|
|
std::string vk_layer_path = ":/tmp/carol::::/:";
|
|
vk_layer_path += (HOME / "/ with spaces/:::::/tandy:").str();
|
|
set_env_var("VK_ADD_LAYER_PATH", vk_layer_path);
|
|
|
|
FrameworkEnvironment env{DebugMode::none, false, true};
|
|
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
|
|
env.get_test_icd().physical_devices.push_back({});
|
|
env.platform_shim->redirect_path("/tmp/carol", env.explicit_layer_folder.location());
|
|
|
|
const char* layer_name = "TestLayer";
|
|
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");
|
|
|
|
InstWrapper inst1{env.vulkan_functions};
|
|
inst1.create_info.add_layer(layer_name);
|
|
FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
|
|
inst1.CheckCreate();
|
|
|
|
// look for VK_ADD_LAYER_PATHS
|
|
EXPECT_TRUE(env.debug_log.find("/tmp/carol"));
|
|
EXPECT_TRUE(env.debug_log.find("/tandy"));
|
|
EXPECT_TRUE(env.debug_log.find((HOME / "/ with spaces/").str()));
|
|
|
|
env.debug_log.clear();
|
|
|
|
env.platform_shim->set_elevated_privilege(true);
|
|
|
|
InstWrapper inst2{env.vulkan_functions};
|
|
inst2.create_info.add_layer(layer_name);
|
|
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
|
|
inst2.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
|
|
|
|
EXPECT_FALSE(env.debug_log.find("/tmp/carol"));
|
|
|
|
env.platform_shim->set_elevated_privilege(false);
|
|
|
|
remove_env_var("VK_ADD_LAYER_PATH");
|
|
}
|
|
|
|
#endif
|