blob: 57152b4cfc290c540812d352b82a95557de67373 [file] [log] [blame]
/*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2021 Valve Corporation
* Copyright (c) 2021 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>
*/
#include "shim.h"
#include <random>
void PlatformShim::redirect_all_paths(fs::path const& path) {
redirect_category(path, ManifestCategory::implicit_layer);
redirect_category(path, ManifestCategory::explicit_layer);
redirect_category(path, ManifestCategory::icd);
}
std::vector<std::string> parse_env_var_list(std::string const& var) {
std::vector<std::string> items;
size_t start = 0;
size_t len = 0;
for (size_t i = 0; i < var.size(); i++) {
#if defined(WIN32)
if (var[i] == ';') {
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
if (var[i] == ':') {
#endif
if (len != 0) {
// only push back non empty strings
items.push_back(var.substr(start, len));
}
start = i + 1;
len = 0;
} else {
len++;
}
}
items.push_back(var.substr(start, len));
return items;
}
#if defined(WIN32)
std::string category_path_name(ManifestCategory category) {
if (category == ManifestCategory::implicit_layer) return "ImplicitLayers";
if (category == ManifestCategory::explicit_layer)
return "ExplicitLayers";
else
return "Drivers";
}
void PlatformShim::reset(DebugMode debug_mode) {
hkey_current_user_explicit_layers.clear();
hkey_current_user_implicit_layers.clear();
hkey_local_machine_explicit_layers.clear();
hkey_local_machine_implicit_layers.clear();
hkey_local_machine_drivers.clear();
}
void PlatformShim::set_path(ManifestCategory category, fs::path const& path) {}
void PlatformShim::add_manifest(ManifestCategory category, fs::path const& path) {
if (category == ManifestCategory::implicit_layer) hkey_local_machine_implicit_layers.emplace_back(path.str());
if (category == ManifestCategory::explicit_layer)
hkey_local_machine_explicit_layers.emplace_back(path.str());
else
hkey_local_machine_drivers.emplace_back(path.str());
}
void PlatformShim::add_dxgi_adapter(fs::path const& manifest_path, GpuType gpu_preference, uint32_t known_driver_index,
DXGI_ADAPTER_DESC1 desc1) {
dxgi_adapters.push_back(DXGIAdapter(manifest_path, gpu_preference, known_driver_index, desc1, next_adapter_handle++));
}
void PlatformShim::add_d3dkmt_adapter(SHIM_D3DKMT_ADAPTERINFO adapter, fs::path const& path) {
d3dkmt_adapters.push_back({adapter, path});
}
// TODO:
void PlatformShim::add_CM_Device_ID(std::wstring const& id, fs::path const& icd_path, fs::path const& layer_path) {
// // append a null byte as separator if there is already id's in the list
// if (CM_device_ID_list.size() != 0) {
// CM_device_ID_list += L'\0'; // I'm sure this wont cause issues with std::string down the line... /s
// }
// CM_device_ID_list += id;
// std::string id_str(id.length(), '\0');
// size_t size_written{};
// wcstombs_s(&size_written, &id_str[0], id_str.length(), id.c_str(), id.length());
// std::string device_path = std::string(pnp_registry_path) + "\\" + id_str;
// CM_device_ID_registry_keys.push_back(device_path.c_str());
// add_key_value_string(id_key, "VulkanDriverName", icd_path.c_str());
// add_key_value_string(id_key, "VulkanLayerName", layer_path.c_str());
// // TODO: decide how to handle 32 bit
// // add_key_value_string(id_key, "VulkanDriverNameWoW", icd_path.c_str());
// // add_key_value_string(id_key, "VulkanLayerName", layer_path.c_str());
}
void PlatformShim::redirect_category(fs::path const& new_path, ManifestCategory search_category) {}
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
#include <dirent.h>
#include <unistd.h>
std::string category_path_name(ManifestCategory category) {
if (category == ManifestCategory::implicit_layer) return "implicit_layer.d";
if (category == ManifestCategory::explicit_layer)
return "explicit_layer.d";
else
return "icd.d";
}
void PlatformShim::reset(DebugMode debug_mode) { redirection_map.clear(); }
void PlatformShim::redirect_path(fs::path const& path, fs::path const& new_path) { redirection_map[path.str()] = new_path; }
void PlatformShim::remove_redirect(fs::path const& path) { redirection_map.erase(path.str()); }
bool PlatformShim::is_fake_path(fs::path const& path) { return redirection_map.count(path.str()) > 0; }
fs::path const& PlatformShim::get_fake_path(fs::path const& path) { return redirection_map.at(path.str()); }
void PlatformShim::add_manifest(ManifestCategory category, fs::path const& path) {}
void parse_and_add_env_var_override(std::vector<std::string>& paths, std::string env_var_contents) {
auto parsed_paths = parse_env_var_list(env_var_contents);
paths.insert(paths.end(), parsed_paths.begin(), parsed_paths.end());
}
void PlatformShim::redirect_category(fs::path const& new_path, ManifestCategory category) {
std::vector<std::string> paths;
auto home = fs::path(get_env_var("HOME"));
if (home.size() != 0) {
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"));
if (category == ManifestCategory::explicit_layer) {
parse_and_add_env_var_override(paths, get_env_var("VK_LAYER_PATH", false)); // don't report failure
}
parse_and_add_env_var_override(paths, FALLBACK_DATA_DIRS);
parse_and_add_env_var_override(paths, FALLBACK_CONFIG_DIRS);
auto sys_conf_dir = std::string(SYSCONFDIR);
if (!sys_conf_dir.empty()) {
paths.push_back(sys_conf_dir);
}
#if defined(EXTRASYSCONFDIR)
// EXTRASYSCONFDIR default is /etc, if SYSCONFDIR wasn't defined, it will have /etc put
// as its default. Don't want to double add it
auto extra_sys_conf_dir = std::string(EXTRASYSCONFDIR);
if (!extra_sys_conf_dir.empty() && sys_conf_dir != extra_sys_conf_dir) {
paths.push_back(extra_sys_conf_dir);
}
#endif
for (auto& path : paths) {
if (!path.empty()) {
redirect_path(fs::path(path) / "vulkan" / category_path_name(category), new_path);
}
}
}
void PlatformShim::set_path(ManifestCategory category, fs::path const& path) {
// use /etc as the 'redirection path' by default since its always searched
redirect_path(fs::path(SYSCONFDIR) / "vulkan" / category_path_name(category), path);
}
#endif