15db71995Sopenharmony_ci/* 25db71995Sopenharmony_ci * Copyright (c) 2021 The Khronos Group Inc. 35db71995Sopenharmony_ci * Copyright (c) 2021 Valve Corporation 45db71995Sopenharmony_ci * Copyright (c) 2021 LunarG, Inc. 55db71995Sopenharmony_ci * 65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to 85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the 95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are 115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions: 125db71995Sopenharmony_ci * 135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in 145db71995Sopenharmony_ci * all copies or substantial portions of the Materials. 155db71995Sopenharmony_ci * 165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 195db71995Sopenharmony_ci * 205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS. 245db71995Sopenharmony_ci * 255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com> 265db71995Sopenharmony_ci */ 275db71995Sopenharmony_ci 285db71995Sopenharmony_ci#include "shim.h" 295db71995Sopenharmony_ci 305db71995Sopenharmony_ci#include <random> 315db71995Sopenharmony_ci 325db71995Sopenharmony_civoid PlatformShim::redirect_all_paths(fs::path const& path) { 335db71995Sopenharmony_ci redirect_category(path, ManifestCategory::implicit_layer); 345db71995Sopenharmony_ci redirect_category(path, ManifestCategory::explicit_layer); 355db71995Sopenharmony_ci redirect_category(path, ManifestCategory::icd); 365db71995Sopenharmony_ci} 375db71995Sopenharmony_ci 385db71995Sopenharmony_cistd::vector<std::string> parse_env_var_list(std::string const& var) { 395db71995Sopenharmony_ci std::vector<std::string> items; 405db71995Sopenharmony_ci size_t start = 0; 415db71995Sopenharmony_ci size_t len = 0; 425db71995Sopenharmony_ci for (size_t i = 0; i < var.size(); i++) { 435db71995Sopenharmony_ci#if defined(WIN32) 445db71995Sopenharmony_ci if (var[i] == ';') { 455db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS 465db71995Sopenharmony_ci if (var[i] == ':') { 475db71995Sopenharmony_ci#endif 485db71995Sopenharmony_ci if (len != 0) { 495db71995Sopenharmony_ci // only push back non empty strings 505db71995Sopenharmony_ci items.push_back(var.substr(start, len)); 515db71995Sopenharmony_ci } 525db71995Sopenharmony_ci start = i + 1; 535db71995Sopenharmony_ci len = 0; 545db71995Sopenharmony_ci } else { 555db71995Sopenharmony_ci len++; 565db71995Sopenharmony_ci } 575db71995Sopenharmony_ci } 585db71995Sopenharmony_ci items.push_back(var.substr(start, len)); 595db71995Sopenharmony_ci 605db71995Sopenharmony_ci return items; 615db71995Sopenharmony_ci} 625db71995Sopenharmony_ci 635db71995Sopenharmony_cistd::vector<std::string> get_folder_contents(std::vector<fs::FolderManager>* folders, std::string folder_name) noexcept { 645db71995Sopenharmony_ci for (auto& folder : *folders) { 655db71995Sopenharmony_ci if (folder.location() == folder_name) { 665db71995Sopenharmony_ci return folder.get_files(); 675db71995Sopenharmony_ci } 685db71995Sopenharmony_ci } 695db71995Sopenharmony_ci return {}; 705db71995Sopenharmony_ci} 715db71995Sopenharmony_ci 725db71995Sopenharmony_ci#if defined(WIN32) 735db71995Sopenharmony_ci 745db71995Sopenharmony_ciD3DKMT_Adapter& D3DKMT_Adapter::add_driver_manifest_path(fs::path const& src) { return add_path(src, driver_paths); } 755db71995Sopenharmony_ciD3DKMT_Adapter& D3DKMT_Adapter::add_implicit_layer_manifest_path(fs::path const& src) { 765db71995Sopenharmony_ci return add_path(src, implicit_layer_paths); 775db71995Sopenharmony_ci} 785db71995Sopenharmony_ciD3DKMT_Adapter& D3DKMT_Adapter::add_explicit_layer_manifest_path(fs::path const& src) { 795db71995Sopenharmony_ci return add_path(src, explicit_layer_paths); 805db71995Sopenharmony_ci} 815db71995Sopenharmony_ci 825db71995Sopenharmony_ciD3DKMT_Adapter& D3DKMT_Adapter::add_path(fs::path src, std::vector<std::wstring>& dest) { 835db71995Sopenharmony_ci std::wstring dest_path; 845db71995Sopenharmony_ci dest_path.resize(src.size()); 855db71995Sopenharmony_ci MultiByteToWideChar(CP_UTF8, 0, src.c_str(), static_cast<int>(src.size()), &dest_path[0], static_cast<int>(dest_path.size())); 865db71995Sopenharmony_ci dest.push_back(dest_path); 875db71995Sopenharmony_ci return *this; 885db71995Sopenharmony_ci} 895db71995Sopenharmony_ci 905db71995Sopenharmony_cistd::string category_path_name(ManifestCategory category) { 915db71995Sopenharmony_ci if (category == ManifestCategory::implicit_layer) return "ImplicitLayers"; 925db71995Sopenharmony_ci if (category == ManifestCategory::explicit_layer) 935db71995Sopenharmony_ci return "ExplicitLayers"; 945db71995Sopenharmony_ci else 955db71995Sopenharmony_ci return "Drivers"; 965db71995Sopenharmony_ci} 975db71995Sopenharmony_ci 985db71995Sopenharmony_civoid PlatformShim::reset() { 995db71995Sopenharmony_ci hkey_current_user_explicit_layers.clear(); 1005db71995Sopenharmony_ci hkey_current_user_implicit_layers.clear(); 1015db71995Sopenharmony_ci hkey_local_machine_explicit_layers.clear(); 1025db71995Sopenharmony_ci hkey_local_machine_implicit_layers.clear(); 1035db71995Sopenharmony_ci hkey_local_machine_drivers.clear(); 1045db71995Sopenharmony_ci hkey_local_machine_settings.clear(); 1055db71995Sopenharmony_ci hkey_current_user_settings.clear(); 1065db71995Sopenharmony_ci} 1075db71995Sopenharmony_ci 1085db71995Sopenharmony_civoid PlatformShim::set_fake_path([[maybe_unused]] ManifestCategory category, [[maybe_unused]] fs::path const& path) {} 1095db71995Sopenharmony_civoid PlatformShim::add_known_path([[maybe_unused]] fs::path const& path) {} 1105db71995Sopenharmony_ci 1115db71995Sopenharmony_civoid PlatformShim::add_manifest(ManifestCategory category, fs::path const& path) { 1125db71995Sopenharmony_ci if (category == ManifestCategory::settings) { 1135db71995Sopenharmony_ci hkey_local_machine_settings.emplace_back(path.str()); 1145db71995Sopenharmony_ci } else if (category == ManifestCategory::implicit_layer) { 1155db71995Sopenharmony_ci hkey_local_machine_implicit_layers.emplace_back(path.str()); 1165db71995Sopenharmony_ci } else if (category == ManifestCategory::explicit_layer) { 1175db71995Sopenharmony_ci hkey_local_machine_explicit_layers.emplace_back(path.str()); 1185db71995Sopenharmony_ci } else { 1195db71995Sopenharmony_ci hkey_local_machine_drivers.emplace_back(path.str()); 1205db71995Sopenharmony_ci } 1215db71995Sopenharmony_ci} 1225db71995Sopenharmony_ci 1235db71995Sopenharmony_civoid PlatformShim::add_unsecured_manifest(ManifestCategory category, fs::path const& path) { 1245db71995Sopenharmony_ci if (category == ManifestCategory::settings) { 1255db71995Sopenharmony_ci hkey_current_user_settings.emplace_back(path.str()); 1265db71995Sopenharmony_ci } else if (category == ManifestCategory::implicit_layer) { 1275db71995Sopenharmony_ci hkey_current_user_implicit_layers.emplace_back(path.str()); 1285db71995Sopenharmony_ci } else if (category == ManifestCategory::explicit_layer) { 1295db71995Sopenharmony_ci hkey_current_user_explicit_layers.emplace_back(path.str()); 1305db71995Sopenharmony_ci } 1315db71995Sopenharmony_ci} 1325db71995Sopenharmony_ci 1335db71995Sopenharmony_civoid PlatformShim::add_dxgi_adapter(GpuType gpu_preference, DXGI_ADAPTER_DESC1 desc1) { 1345db71995Sopenharmony_ci uint32_t next_index = static_cast<uint32_t>(dxgi_adapters.size()); 1355db71995Sopenharmony_ci dxgi_adapters.emplace(next_index, DXGIAdapter{gpu_preference, desc1, next_index}); 1365db71995Sopenharmony_ci} 1375db71995Sopenharmony_ci 1385db71995Sopenharmony_civoid PlatformShim::add_d3dkmt_adapter(D3DKMT_Adapter const& adapter) { d3dkmt_adapters.push_back(adapter); } 1395db71995Sopenharmony_ci 1405db71995Sopenharmony_civoid PlatformShim::set_app_package_path(fs::path const& path) { 1415db71995Sopenharmony_ci app_package_path.resize(path.size()); 1425db71995Sopenharmony_ci MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, &app_package_path[0], static_cast<int>(app_package_path.size())); 1435db71995Sopenharmony_ci} 1445db71995Sopenharmony_ci 1455db71995Sopenharmony_ci// TODO: 1465db71995Sopenharmony_civoid PlatformShim::add_CM_Device_ID([[maybe_unused]] std::wstring const& id, [[maybe_unused]] fs::path const& icd_path, 1475db71995Sopenharmony_ci [[maybe_unused]] fs::path const& layer_path) { 1485db71995Sopenharmony_ci // // append a null byte as separator if there is already id's in the list 1495db71995Sopenharmony_ci // if (CM_device_ID_list.size() != 0) { 1505db71995Sopenharmony_ci // CM_device_ID_list += L'\0'; // I'm sure this wont cause issues with std::string down the line... /s 1515db71995Sopenharmony_ci // } 1525db71995Sopenharmony_ci // CM_device_ID_list += id; 1535db71995Sopenharmony_ci // std::string id_str(id.length(), '\0'); 1545db71995Sopenharmony_ci // size_t size_written{}; 1555db71995Sopenharmony_ci // wcstombs_s(&size_written, &id_str[0], id_str.length(), id.c_str(), id.length()); 1565db71995Sopenharmony_ci 1575db71995Sopenharmony_ci // std::string device_path = std::string(pnp_registry_path) + "\\" + id_str; 1585db71995Sopenharmony_ci // CM_device_ID_registry_keys.push_back(device_path.c_str()); 1595db71995Sopenharmony_ci // add_key_value_string(id_key, "VulkanDriverName", icd_path.c_str()); 1605db71995Sopenharmony_ci // add_key_value_string(id_key, "VulkanLayerName", layer_path.c_str()); 1615db71995Sopenharmony_ci // // TODO: decide how to handle 32 bit 1625db71995Sopenharmony_ci // // add_key_value_string(id_key, "VulkanDriverNameWoW", icd_path.c_str()); 1635db71995Sopenharmony_ci // // add_key_value_string(id_key, "VulkanLayerName", layer_path.c_str()); 1645db71995Sopenharmony_ci} 1655db71995Sopenharmony_ci 1665db71995Sopenharmony_civoid PlatformShim::redirect_category(fs::path const&, ManifestCategory) {} 1675db71995Sopenharmony_ci 1685db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS 1695db71995Sopenharmony_ci 1705db71995Sopenharmony_ci#include <dirent.h> 1715db71995Sopenharmony_ci#include <unistd.h> 1725db71995Sopenharmony_ci 1735db71995Sopenharmony_cistd::string category_path_name(ManifestCategory category) { 1745db71995Sopenharmony_ci if (category == ManifestCategory::settings) return "settings.d"; 1755db71995Sopenharmony_ci if (category == ManifestCategory::implicit_layer) return "implicit_layer.d"; 1765db71995Sopenharmony_ci if (category == ManifestCategory::explicit_layer) 1775db71995Sopenharmony_ci return "explicit_layer.d"; 1785db71995Sopenharmony_ci else 1795db71995Sopenharmony_ci return "icd.d"; 1805db71995Sopenharmony_ci} 1815db71995Sopenharmony_ci 1825db71995Sopenharmony_civoid PlatformShim::reset() { redirection_map.clear(); } 1835db71995Sopenharmony_ci 1845db71995Sopenharmony_cibool PlatformShim::is_fake_path(fs::path const& path) { return redirection_map.count(path.str()) > 0; } 1855db71995Sopenharmony_cifs::path const& PlatformShim::get_real_path_from_fake_path(fs::path const& path) { return redirection_map.at(path.str()); } 1865db71995Sopenharmony_civoid PlatformShim::redirect_path(fs::path const& path, fs::path const& new_path) { redirection_map[path.str()] = new_path; } 1875db71995Sopenharmony_civoid PlatformShim::remove_redirect(fs::path const& path) { redirection_map.erase(path.str()); } 1885db71995Sopenharmony_ci 1895db71995Sopenharmony_cibool PlatformShim::is_known_path(fs::path const& path) { return known_path_set.count(path.str()) > 0; } 1905db71995Sopenharmony_civoid PlatformShim::add_known_path(fs::path const& path) { known_path_set.insert(path.str()); } 1915db71995Sopenharmony_civoid PlatformShim::remove_known_path(fs::path const& path) { known_path_set.erase(path.str()); } 1925db71995Sopenharmony_ci 1935db71995Sopenharmony_civoid PlatformShim::add_manifest([[maybe_unused]] ManifestCategory category, [[maybe_unused]] fs::path const& path) {} 1945db71995Sopenharmony_civoid PlatformShim::add_unsecured_manifest([[maybe_unused]] ManifestCategory category, [[maybe_unused]] fs::path const& path) {} 1955db71995Sopenharmony_ci 1965db71995Sopenharmony_civoid parse_and_add_env_var_override(std::vector<std::string>& paths, std::string env_var_contents) { 1975db71995Sopenharmony_ci auto parsed_paths = parse_env_var_list(env_var_contents); 1985db71995Sopenharmony_ci paths.insert(paths.end(), parsed_paths.begin(), parsed_paths.end()); 1995db71995Sopenharmony_ci} 2005db71995Sopenharmony_ci 2015db71995Sopenharmony_civoid PlatformShim::redirect_category(fs::path const& new_path, ManifestCategory category) { 2025db71995Sopenharmony_ci std::vector<std::string> paths; 2035db71995Sopenharmony_ci auto home = fs::path(get_env_var("HOME")); 2045db71995Sopenharmony_ci if (category == ManifestCategory::settings) { 2055db71995Sopenharmony_ci redirect_path(home / ".local/share/vulkan" / category_path_name(category), new_path); 2065db71995Sopenharmony_ci return; 2075db71995Sopenharmony_ci } 2085db71995Sopenharmony_ci 2095db71995Sopenharmony_ci if (home.size() != 0) { 2105db71995Sopenharmony_ci paths.push_back((home / ".config").str()); 2115db71995Sopenharmony_ci paths.push_back((home / ".local/share").str()); 2125db71995Sopenharmony_ci } 2135db71995Sopenharmony_ci // Don't report errors on apple - these env-vars are not suppose to be defined 2145db71995Sopenharmony_ci bool report_errors = true; 2155db71995Sopenharmony_ci#if defined(__APPLE__) 2165db71995Sopenharmony_ci report_errors = false; 2175db71995Sopenharmony_ci#endif 2185db71995Sopenharmony_ci parse_and_add_env_var_override(paths, get_env_var("XDG_CONFIG_HOME", report_errors)); 2195db71995Sopenharmony_ci if (category == ManifestCategory::explicit_layer) { 2205db71995Sopenharmony_ci parse_and_add_env_var_override(paths, get_env_var("VK_LAYER_PATH", false)); // don't report failure 2215db71995Sopenharmony_ci } 2225db71995Sopenharmony_ci parse_and_add_env_var_override(paths, FALLBACK_DATA_DIRS); 2235db71995Sopenharmony_ci parse_and_add_env_var_override(paths, FALLBACK_CONFIG_DIRS); 2245db71995Sopenharmony_ci 2255db71995Sopenharmony_ci auto sys_conf_dir = std::string(SYSCONFDIR); 2265db71995Sopenharmony_ci if (!sys_conf_dir.empty()) { 2275db71995Sopenharmony_ci paths.push_back(sys_conf_dir); 2285db71995Sopenharmony_ci } 2295db71995Sopenharmony_ci#if defined(EXTRASYSCONFDIR) 2305db71995Sopenharmony_ci // EXTRASYSCONFDIR default is /etc, if SYSCONFDIR wasn't defined, it will have /etc put 2315db71995Sopenharmony_ci // as its default. Don't want to double add it 2325db71995Sopenharmony_ci auto extra_sys_conf_dir = std::string(EXTRASYSCONFDIR); 2335db71995Sopenharmony_ci if (!extra_sys_conf_dir.empty() && sys_conf_dir != extra_sys_conf_dir) { 2345db71995Sopenharmony_ci paths.push_back(extra_sys_conf_dir); 2355db71995Sopenharmony_ci } 2365db71995Sopenharmony_ci#endif 2375db71995Sopenharmony_ci 2385db71995Sopenharmony_ci for (auto& path : paths) { 2395db71995Sopenharmony_ci if (!path.empty()) { 2405db71995Sopenharmony_ci redirect_path(fs::path(path) / "vulkan" / category_path_name(category), new_path); 2415db71995Sopenharmony_ci } 2425db71995Sopenharmony_ci } 2435db71995Sopenharmony_ci} 2445db71995Sopenharmony_ci 2455db71995Sopenharmony_civoid PlatformShim::set_fake_path(ManifestCategory category, fs::path const& path) { 2465db71995Sopenharmony_ci // use /etc as the 'redirection path' by default since its always searched 2475db71995Sopenharmony_ci redirect_path(fs::path(SYSCONFDIR) / "vulkan" / category_path_name(category), path); 2485db71995Sopenharmony_ci} 2495db71995Sopenharmony_ci 2505db71995Sopenharmony_civoid PlatformShim::redirect_dlopen_name(fs::path const& filename, fs::path const& actual_path) { 2515db71995Sopenharmony_ci dlopen_redirection_map[filename.str()] = actual_path; 2525db71995Sopenharmony_ci} 2535db71995Sopenharmony_ci 2545db71995Sopenharmony_cibool PlatformShim::is_dlopen_redirect_name(fs::path const& filename) { return dlopen_redirection_map.count(filename.str()) == 1; } 2555db71995Sopenharmony_ci 2565db71995Sopenharmony_cifs::path PlatformShim::query_default_redirect_path(ManifestCategory category) { 2575db71995Sopenharmony_ci return fs::path(SYSCONFDIR) / "vulkan" / category_path_name(category); 2585db71995Sopenharmony_ci} 2595db71995Sopenharmony_ci#endif 260