• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 The Khronos Group Inc.
3  * Copyright (c) 2021 Valve Corporation
4  * Copyright (c) 2021 LunarG, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and/or associated documentation files (the "Materials"), to
8  * deal in the Materials without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Materials, and to permit persons to whom the Materials are
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice(s) and this permission notice shall be included in
14  * all copies or substantial portions of the Materials.
15  *
16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  *
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23  * USE OR OTHER DEALINGS IN THE MATERIALS.
24  *
25  * Author: Charles Giessen <charles@lunarg.com>
26  */
27 
28 #include "shim.h"
29 
redirect_all_paths(std::filesystem::path const & path)30 void PlatformShim::redirect_all_paths(std::filesystem::path const& path) {
31     redirect_category(path, ManifestCategory::implicit_layer);
32     redirect_category(path, ManifestCategory::explicit_layer);
33     redirect_category(path, ManifestCategory::icd);
34 }
35 
parse_env_var_list(std::string const & var)36 std::vector<std::string> parse_env_var_list(std::string const& var) {
37     std::vector<std::string> items;
38     size_t start = 0;
39     size_t len = 0;
40     for (size_t i = 0; i < var.size(); i++) {
41 #if defined(WIN32)
42         if (var[i] == ';') {
43 #elif COMMON_UNIX_PLATFORMS
44         if (var[i] == ':') {
45 #endif
46             if (len != 0) {
47                 // only push back non empty strings
48                 items.push_back(var.substr(start, len));
49             }
50             start = i + 1;
51             len = 0;
52         } else {
53             len++;
54         }
55     }
56     items.push_back(var.substr(start, len));
57 
58     return items;
59 }
60 
61 std::vector<std::filesystem::path> get_folder_contents(std::vector<fs::FolderManager>* folders,
62                                                        std::filesystem::path folder_name) noexcept {
63     for (auto& folder : *folders) {
64         if (folder.location() == folder_name) {
65             return folder.get_files();
66         }
67     }
68     return {};
69 }
70 
71 #if defined(WIN32)
72 
73 D3DKMT_Adapter& D3DKMT_Adapter::add_driver_manifest_path(std::filesystem::path const& src) { return add_path(src, driver_paths); }
74 D3DKMT_Adapter& D3DKMT_Adapter::add_implicit_layer_manifest_path(std::filesystem::path const& src) {
75     return add_path(src, implicit_layer_paths);
76 }
77 D3DKMT_Adapter& D3DKMT_Adapter::add_explicit_layer_manifest_path(std::filesystem::path const& src) {
78     return add_path(src, explicit_layer_paths);
79 }
80 
81 D3DKMT_Adapter& D3DKMT_Adapter::add_path(std::filesystem::path src, std::vector<std::wstring>& dest) {
82     dest.push_back(src.native());
83     return *this;
84 }
85 
86 std::string category_path_name(ManifestCategory category) {
87     if (category == ManifestCategory::implicit_layer) return "ImplicitLayers";
88     if (category == ManifestCategory::explicit_layer)
89         return "ExplicitLayers";
90     else
91         return "Drivers";
92 }
93 
94 void PlatformShim::reset() {
95     hkey_current_user_explicit_layers.clear();
96     hkey_current_user_implicit_layers.clear();
97     hkey_local_machine_explicit_layers.clear();
98     hkey_local_machine_implicit_layers.clear();
99     hkey_local_machine_drivers.clear();
100     hkey_local_machine_settings.clear();
101     hkey_current_user_settings.clear();
102 }
103 
104 void PlatformShim::set_fake_path([[maybe_unused]] ManifestCategory category, [[maybe_unused]] std::filesystem::path const& path) {}
105 void PlatformShim::add_known_path([[maybe_unused]] std::filesystem::path const& path) {}
106 
107 void PlatformShim::add_manifest(ManifestCategory category, std::filesystem::path const& path) {
108     if (category == ManifestCategory::settings) {
109         hkey_local_machine_settings.emplace_back(path);
110     } else if (category == ManifestCategory::implicit_layer) {
111         hkey_local_machine_implicit_layers.emplace_back(path);
112     } else if (category == ManifestCategory::explicit_layer) {
113         hkey_local_machine_explicit_layers.emplace_back(path);
114     } else {
115         hkey_local_machine_drivers.emplace_back(path);
116     }
117 }
118 
119 void PlatformShim::add_unsecured_manifest(ManifestCategory category, std::filesystem::path const& path) {
120     if (category == ManifestCategory::settings) {
121         hkey_current_user_settings.emplace_back(path);
122     } else if (category == ManifestCategory::implicit_layer) {
123         hkey_current_user_implicit_layers.emplace_back(path);
124     } else if (category == ManifestCategory::explicit_layer) {
125         hkey_current_user_explicit_layers.emplace_back(path);
126     }
127 }
128 
129 void PlatformShim::add_dxgi_adapter(GpuType gpu_preference, DXGI_ADAPTER_DESC1 desc1) {
130     uint32_t next_index = static_cast<uint32_t>(dxgi_adapters.size());
131     dxgi_adapters.emplace(next_index, DXGIAdapter{gpu_preference, desc1, next_index});
132 }
133 
134 void PlatformShim::add_d3dkmt_adapter(D3DKMT_Adapter const& adapter) { d3dkmt_adapters.push_back(adapter); }
135 
136 void PlatformShim::set_app_package_path(std::filesystem::path const& path) { app_package_path = path; }
137 
138 // TODO:
139 void PlatformShim::add_CM_Device_ID([[maybe_unused]] std::wstring const& id, [[maybe_unused]] std::filesystem::path const& icd_path,
140                                     [[maybe_unused]] std::filesystem::path const& layer_path) {
141     //     // append a null byte as separator if there is already id's in the list
142     //     if (CM_device_ID_list.size() != 0) {
143     //         CM_device_ID_list += L'\0';  // I'm sure this wont cause issues with std::string down the line... /s
144     //     }
145     //     CM_device_ID_list += id;
146     //     std::string id_str(id.length(), '\0');
147     //     size_t size_written{};
148     //     wcstombs_s(&size_written, &id_str[0], id_str.length(), id.c_str(), id.length());
149 
150     //     std::string device_path = std::string(pnp_registry_path) + "\\" + id_str;
151     //     CM_device_ID_registry_keys.push_back(device_path.c_str());
152     //     add_key_value_string(id_key, "VulkanDriverName", icd_path.c_str());
153     //     add_key_value_string(id_key, "VulkanLayerName", layer_path.c_str());
154     //     // TODO: decide how to handle 32 bit
155     //     // add_key_value_string(id_key, "VulkanDriverNameWoW", icd_path.c_str());
156     //     // add_key_value_string(id_key, "VulkanLayerName", layer_path.c_str());
157 }
158 
159 void PlatformShim::redirect_category(std::filesystem::path const&, ManifestCategory) {}
160 
161 #elif COMMON_UNIX_PLATFORMS
162 
163 #include <dirent.h>
164 #include <unistd.h>
165 
166 std::string category_path_name(ManifestCategory category) {
167     if (category == ManifestCategory::settings) return "settings.d";
168     if (category == ManifestCategory::implicit_layer) return "implicit_layer.d";
169     if (category == ManifestCategory::explicit_layer)
170         return "explicit_layer.d";
171     else
172         return "icd.d";
173 }
174 
175 void PlatformShim::reset() { redirection_map.clear(); }
176 
177 bool PlatformShim::is_fake_path(std::filesystem::path const& path) { return redirection_map.count(path) > 0; }
178 std::filesystem::path const& PlatformShim::get_real_path_from_fake_path(std::filesystem::path const& path) {
179     return redirection_map.at(path);
180 }
181 void PlatformShim::redirect_path(std::filesystem::path const& path, std::filesystem::path const& new_path) {
182     redirection_map[path] = new_path;
183 }
184 void PlatformShim::remove_redirect(std::filesystem::path const& path) { redirection_map.erase(path); }
185 
186 bool PlatformShim::is_known_path(std::filesystem::path const& path) { return known_path_set.count(path) > 0; }
187 void PlatformShim::add_known_path(std::filesystem::path const& path) { known_path_set.insert(path); }
188 void PlatformShim::remove_known_path(std::filesystem::path const& path) { known_path_set.erase(path); }
189 
190 void PlatformShim::add_manifest([[maybe_unused]] ManifestCategory category, [[maybe_unused]] std::filesystem::path const& path) {}
191 void PlatformShim::add_unsecured_manifest([[maybe_unused]] ManifestCategory category,
192                                           [[maybe_unused]] std::filesystem::path const& path) {}
193 
194 void parse_and_add_env_var_override(std::vector<std::string>& paths, std::string env_var_contents) {
195     auto parsed_paths = parse_env_var_list(env_var_contents);
196     paths.insert(paths.end(), parsed_paths.begin(), parsed_paths.end());
197 }
198 
199 void PlatformShim::redirect_category(std::filesystem::path const& new_path, ManifestCategory category) {
200     std::vector<std::string> paths;
201     auto home = std::filesystem::path(get_env_var("HOME"));
202     if (category == ManifestCategory::settings) {
203         redirect_path(home / ".local/share/vulkan" / category_path_name(category), new_path);
204         return;
205     }
206 
207     if (!home.empty()) {
208         paths.push_back((home / ".config"));
209         paths.push_back((home / ".local/share"));
210     }
211     // Don't report errors on apple - these env-vars are not suppose to be defined
212     bool report_errors = true;
213 #if defined(__APPLE__)
214     report_errors = false;
215 #endif
216     parse_and_add_env_var_override(paths, get_env_var("XDG_CONFIG_HOME", report_errors));
217     if (category == ManifestCategory::explicit_layer) {
218         parse_and_add_env_var_override(paths, get_env_var("VK_LAYER_PATH", false));  // don't report failure
219     }
220     if (category == ManifestCategory::implicit_layer) {
221         parse_and_add_env_var_override(paths, get_env_var("VK_IMPLICIT_LAYER_PATH", false));  // don't report failure
222     }
223     parse_and_add_env_var_override(paths, FALLBACK_DATA_DIRS);
224     parse_and_add_env_var_override(paths, FALLBACK_CONFIG_DIRS);
225 
226     auto sys_conf_dir = std::string(SYSCONFDIR);
227     if (!sys_conf_dir.empty()) {
228         paths.push_back(sys_conf_dir);
229     }
230 #if defined(EXTRASYSCONFDIR)
231     // EXTRASYSCONFDIR default is /etc, if SYSCONFDIR wasn't defined, it will have /etc put
232     // as its default. Don't want to double add it
233     auto extra_sys_conf_dir = std::string(EXTRASYSCONFDIR);
234     if (!extra_sys_conf_dir.empty() && sys_conf_dir != extra_sys_conf_dir) {
235         paths.push_back(extra_sys_conf_dir);
236     }
237 #endif
238 
239     for (auto& path : paths) {
240         if (!path.empty()) {
241             redirect_path(std::filesystem::path(path) / "vulkan" / category_path_name(category), new_path);
242         }
243     }
244 }
245 
246 void PlatformShim::set_fake_path(ManifestCategory category, std::filesystem::path const& path) {
247     // use /etc as the 'redirection path' by default since its always searched
248     redirect_path(std::filesystem::path(SYSCONFDIR) / "vulkan" / category_path_name(category), path);
249 }
250 
251 void PlatformShim::redirect_dlopen_name(std::filesystem::path const& filename, std::filesystem::path const& actual_path) {
252     dlopen_redirection_map[filename] = actual_path;
253 }
254 
255 bool PlatformShim::is_dlopen_redirect_name(std::filesystem::path const& filename) {
256     return dlopen_redirection_map.count(filename) == 1;
257 }
258 
259 std::filesystem::path PlatformShim::query_default_redirect_path(ManifestCategory category) {
260     return std::filesystem::path(SYSCONFDIR) / "vulkan" / category_path_name(category);
261 }
262 #endif
263