blob: f9d76e4c812183032333785c70445f4820eb9c75 [file] [log] [blame]
Jon Ashburnbe582642014-12-22 12:04:40 -07001/**************************************************************************
2 *
Jeremy Gebben50edce62022-01-03 14:54:40 -07003 * Copyright 2014-2022 Valve Software
4 * Copyright 2015-2022 Google Inc.
5 * Copyright 2019-2022 LunarG, Inc.
Jon Ashburnbe582642014-12-22 12:04:40 -07006 * All Rights Reserved.
7 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06008 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Jon Ashburnbe582642014-12-22 12:04:40 -070011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * http://www.apache.org/licenses/LICENSE-2.0
Jon Ashburnbe582642014-12-22 12:04:40 -070013 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060014 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
Jon Ashburnbe582642014-12-22 12:04:40 -070019 *
Jon Ashburne922f712015-11-03 13:41:23 -070020 * Author: Jon Ashburn <jon@lunarg.com>
21 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
22 * Author: Tobin Ehlis <tobin@lunarg.com>
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060023 * Author: Mark Lobodzinski <mark@lunarg.com>
Jon Ashburnbe582642014-12-22 12:04:40 -070024 **************************************************************************/
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060025#include "vk_layer_config.h"
Petr Kraus6c4bdce2019-08-27 17:35:01 +020026
Petr Krausc53604b2019-09-06 00:31:48 +020027#include <string.h>
Lenny Komow807ebf02016-09-30 14:15:25 -060028#include <fstream>
29#include <iostream>
Lenny Komow5c57fcb2018-10-02 09:18:51 -060030#include <sstream>
Lenny Komow807ebf02016-09-30 14:15:25 -060031#include <string>
32#include <sys/stat.h>
Petr Krausc53604b2019-09-06 00:31:48 +020033
Lenny Komow807ebf02016-09-30 14:15:25 -060034#include <vulkan/vk_layer.h>
Mark Lobodzinski103c58a2020-01-29 13:20:00 -070035// sdk_platform header redefines NOMINMAX
36#undef NOMINMAX
Petr Krausc53604b2019-09-06 00:31:48 +020037#include <vulkan/vk_sdk_platform.h>
38#include "vk_layer_utils.h"
Jon Ashburnbe582642014-12-22 12:04:40 -070039
Mark Lobodzinskid5aa8de2018-02-02 13:58:41 -070040#if defined(_WIN32)
Martin Herkt094130b2018-03-06 22:44:13 +010041#include <windows.h>
Mark Lobodzinskif5b17152020-06-09 10:16:31 -060042#include <direct.h>
43#define GetCurrentDir _getcwd
44#else
45#include <unistd.h>
46#define GetCurrentDir getcwd
Mark Lobodzinskid5aa8de2018-02-02 13:58:41 -070047#endif
48
Petr Krausc53604b2019-09-06 00:31:48 +020049using std::string;
50
Jon Ashburn5484e0c2016-03-08 17:48:44 -070051class ConfigFile {
Petr Kraus4ed81e32019-09-02 23:41:19 +020052 public:
Jon Ashburnbe582642014-12-22 12:04:40 -070053 ConfigFile();
Petr Krausc53604b2019-09-06 00:31:48 +020054 ~ConfigFile(){};
Jon Ashburnbe582642014-12-22 12:04:40 -070055
Petr Krausc53604b2019-09-06 00:31:48 +020056 const char *GetOption(const string &option);
57 void SetOption(const string &option, const string &value);
58 string vk_layer_disables_env_var;
Mark Lobodzinskif5b17152020-06-09 10:16:31 -060059 SettingsFileInfo settings_info{};
Jon Ashburndec60512015-01-13 17:24:01 -070060
Petr Kraus4ed81e32019-09-02 23:41:19 +020061 private:
Petr Krausc53604b2019-09-06 00:31:48 +020062 bool file_is_parsed_;
63 std::map<string, string> value_map_;
Jon Ashburnbe582642014-12-22 12:04:40 -070064
Petr Krausc53604b2019-09-06 00:31:48 +020065 string FindSettings();
66 void ParseFile(const char *filename);
Jon Ashburnbe582642014-12-22 12:04:40 -070067};
68
Petr Krausc53604b2019-09-06 00:31:48 +020069static ConfigFile layer_config;
Jon Ashburndec60512015-01-13 17:24:01 -070070
Jeremy Gebben427d3972022-07-14 13:48:08 -060071VK_LAYER_EXPORT std::string GetEnvironment(const char *variable) {
Lenny Komow807ebf02016-09-30 14:15:25 -060072#if !defined(__ANDROID__) && !defined(_WIN32)
73 const char *output = getenv(variable);
74 return output == NULL ? "" : output;
75#elif defined(_WIN32)
76 int size = GetEnvironmentVariable(variable, NULL, 0);
77 if (size == 0) {
78 return "";
79 }
80 char *buffer = new char[size];
81 GetEnvironmentVariable(variable, buffer, size);
Petr Krausc53604b2019-09-06 00:31:48 +020082 string output = buffer;
Lenny Komow807ebf02016-09-30 14:15:25 -060083 delete[] buffer;
84 return output;
sfricke-samsung98acb882020-11-03 19:16:10 -080085#elif defined(__ANDROID__)
86 string command = "getprop " + string(variable);
87 FILE *pPipe = popen(command.c_str(), "r");
88 if (pPipe != nullptr) {
89 char value[256];
90 fgets(value, 256, pPipe);
91 pclose(pPipe);
92
Nathaniel Cesariof6b4a3d2021-04-22 09:36:14 -060093 // Make sure its not an empty line and does not end in a newline
94 const auto str_len = strcspn(value, "\r\n");
95 if (str_len == 0) {
sfricke-samsung98acb882020-11-03 19:16:10 -080096 return "";
97 } else {
Nathaniel Cesariof6b4a3d2021-04-22 09:36:14 -060098 value[str_len] = '\0';
sfricke-samsung98acb882020-11-03 19:16:10 -080099 return string(value);
100 }
101 } else {
102 return "";
103 }
Lenny Komow807ebf02016-09-30 14:15:25 -0600104#else
105 return "";
106#endif
107}
108
Petr Krausc53604b2019-09-06 00:31:48 +0200109VK_LAYER_EXPORT const char *getLayerOption(const char *option) { return layer_config.GetOption(option); }
110VK_LAYER_EXPORT const char *GetLayerEnvVar(const char *option) {
Jeremy Gebben427d3972022-07-14 13:48:08 -0600111 // NOTE: new code should use GetEnvironment directly. This is a workaround for the problem
112 // described in https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3048
113 static std::string result;
114 result = GetEnvironment(option);
115 return result.c_str();
Mark Lobodzinski2af57ec2019-03-20 09:17:56 -0600116}
Jon Ashburnbe582642014-12-22 12:04:40 -0700117
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600118VK_LAYER_EXPORT const SettingsFileInfo *GetLayerSettingsFileInfo() { return &layer_config.settings_info; }
119
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600120// If option is NULL or stdout, return stdout, otherwise try to open option
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600121// as a filename. If successful, return file handle, otherwise stdout
Petr Krausc53604b2019-09-06 00:31:48 +0200122VK_LAYER_EXPORT FILE *getLayerLogOutput(const char *option, const char *layer_name) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700123 FILE *log_output = NULL;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700124 if (!option || !strcmp("stdout", option)) {
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600125 log_output = stdout;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700126 } else {
Petr Krausc53604b2019-09-06 00:31:48 +0200127 log_output = fopen(option, "w");
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600128 if (log_output == NULL) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700129 if (option) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700130 std::cout << std::endl
Petr Krausc53604b2019-09-06 00:31:48 +0200131 << layer_name << " ERROR: Bad output filename specified: " << option << ". Writing to STDOUT instead"
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700132 << std::endl
133 << std::endl;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700134 }
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600135 log_output = stdout;
136 }
137 }
Cody Northrope3e39ef2015-09-16 08:35:29 -0600138 return log_output;
Tobin Ehlisb1df55e2015-09-15 09:55:54 -0600139}
140
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600141// Map option strings to flag enum values
Jeremy Gebbencbf22862021-03-03 12:01:22 -0700142VK_LAYER_EXPORT VkFlags GetLayerOptionFlags(string option, layer_data::unordered_map<string, VkFlags> const &enum_data,
Mark Lobodzinski07954a52018-02-01 12:14:30 -0700143 uint32_t option_default) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600144 VkDebugReportFlagsEXT flags = option_default;
Petr Krausc53604b2019-09-06 00:31:48 +0200145 string option_list = layer_config.GetOption(option.c_str());
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600146
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600147 while (option_list.length() != 0) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600148 // Find length of option string
149 std::size_t option_length = option_list.find(",");
150 if (option_length == option_list.npos) {
151 option_length = option_list.size();
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600152 }
153
Petr Krausc53604b2019-09-06 00:31:48 +0200154 // Get first option item in list
155 const string option_item = option_list.substr(0, option_length);
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600156
Petr Krausc53604b2019-09-06 00:31:48 +0200157 auto enum_value = enum_data.find(option_item);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600158 if (enum_value != enum_data.end()) {
159 flags |= enum_value->second;
160 }
161
162 // Remove first option from option_list
163 option_list.erase(0, option_length);
164 // Remove possible comma separator
165 std::size_t char_position = option_list.find(",");
166 if (char_position == 0) {
167 option_list.erase(char_position, 1);
168 }
169 // Remove possible space
170 char_position = option_list.find(" ");
171 if (char_position == 0) {
172 option_list.erase(char_position, 1);
173 }
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600174 }
175 return flags;
176}
177
Petr Krausc53604b2019-09-06 00:31:48 +0200178VK_LAYER_EXPORT void setLayerOption(const char *option, const char *value) { layer_config.SetOption(option, value); }
Jon Ashburndec60512015-01-13 17:24:01 -0700179
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600180// Constructor for ConfigFile. Initialize layers to log error messages to stdout by default. If a vk_layer_settings file is present,
181// its settings will override the defaults.
Petr Krausc53604b2019-09-06 00:31:48 +0200182ConfigFile::ConfigFile() : file_is_parsed_(false) {
183 value_map_["khronos_validation.report_flags"] = "error";
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600184
185#ifdef WIN32
186 // For Windows, enable message logging AND OutputDebugString
Petr Krausc53604b2019-09-06 00:31:48 +0200187 value_map_["khronos_validation.debug_action"] =
Mark Lobodzinski13500d32019-03-20 10:06:09 -0600188 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700189#else // WIN32
Petr Krausc53604b2019-09-06 00:31:48 +0200190 value_map_["khronos_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700191#endif // WIN32
Petr Krausc53604b2019-09-06 00:31:48 +0200192 value_map_["khronos_validation.log_filename"] = "stdout";
Jeremy Gebben81d9b132022-05-04 08:54:37 -0600193 value_map_["khronos_validation.fine_grained_locking"] = "true";
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600194}
Jon Ashburnbe582642014-12-22 12:04:40 -0700195
Petr Krausc53604b2019-09-06 00:31:48 +0200196const char *ConfigFile::GetOption(const string &option) {
197 std::map<string, string>::const_iterator it;
198 if (!file_is_parsed_) {
199 string settings_file = FindSettings();
200 ParseFile(settings_file.c_str());
Jon Ashburnbe582642014-12-22 12:04:40 -0700201 }
202
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700203 if ((it = value_map_.find(option)) == value_map_.end()) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600204 return "";
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700205 } else {
Jon Ashburnbe582642014-12-22 12:04:40 -0700206 return it->second.c_str();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700207 }
Jon Ashburnbe582642014-12-22 12:04:40 -0700208}
209
Petr Krausc53604b2019-09-06 00:31:48 +0200210void ConfigFile::SetOption(const string &option, const string &val) {
211 if (!file_is_parsed_) {
212 string settings_file = FindSettings();
213 ParseFile(settings_file.c_str());
Jon Ashburndec60512015-01-13 17:24:01 -0700214 }
215
Petr Krausc53604b2019-09-06 00:31:48 +0200216 value_map_[option] = val;
Jon Ashburndec60512015-01-13 17:24:01 -0700217}
218
Dorian Apanelfcfe5a32020-08-09 11:19:50 +0200219#if defined(WIN32)
220// Check for admin rights
221static inline bool IsHighIntegrity() {
222 HANDLE process_token;
223 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
224 // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
225 uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)];
226 DWORD buffer_size;
227 if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer),
228 &buffer_size) != 0) {
229 const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer;
230 const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
231 const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1);
232
233 CloseHandle(process_token);
234 return integrity_level > SECURITY_MANDATORY_MEDIUM_RID;
235 }
236
237 CloseHandle(process_token);
238 }
239
240 return false;
241}
242#endif
243
Petr Krausc53604b2019-09-06 00:31:48 +0200244string ConfigFile::FindSettings() {
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600245 struct stat info;
246
247#if defined(WIN32)
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600248 // Look for VkConfig-specific settings location specified in the windows registry
Dorian Apanelfcfe5a32020-08-09 11:19:50 +0200249 HKEY key;
250
251 const std::array<HKEY, 2> hives = {DEFAULT_VK_REGISTRY_HIVE, SECONDARY_VK_REGISTRY_HIVE};
252 const size_t hives_to_check_count = IsHighIntegrity() ? 1 : hives.size(); // Admin checks only the default hive
253
254 for (size_t hive_index = 0; hive_index < hives_to_check_count; ++hive_index) {
255 LSTATUS err = RegOpenKeyEx(hives[hive_index], "Software\\Khronos\\Vulkan\\Settings", 0, KEY_READ, &key);
256 if (err == ERROR_SUCCESS) {
257 char name[2048];
258 DWORD i = 0, name_size, type, value, value_size;
259 while (ERROR_SUCCESS == RegEnumValue(key, i++, name, &(name_size = sizeof(name)), nullptr, &type,
260 reinterpret_cast<LPBYTE>(&value), &(value_size = sizeof(value)))) {
261 // Check if the registry entry is a dword with a value of zero
262 if (type != REG_DWORD || value != 0) {
263 continue;
264 }
265
266 // Check if this actually points to a file
267 if ((stat(name, &info) != 0) || !(info.st_mode & S_IFREG)) {
268 continue;
269 }
270
271 // Use this file
272 RegCloseKey(key);
273 settings_info.source = kVkConfig;
274 settings_info.location = name;
275 return name;
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600276 }
277
Dorian Apanelfcfe5a32020-08-09 11:19:50 +0200278 RegCloseKey(key);
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600279 }
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600280 }
Dorian Apanelfcfe5a32020-08-09 11:19:50 +0200281
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600282#else
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600283 // Look for VkConfig-specific settings location specified in a specific spot in the linux settings store
Petr Krausc53604b2019-09-06 00:31:48 +0200284 string search_path = GetEnvironment("XDG_DATA_HOME");
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600285 if (search_path == "") {
Petr Krausc53604b2019-09-06 00:31:48 +0200286 search_path = GetEnvironment("HOME");
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600287 if (search_path != "") {
288 search_path += "/.local/share";
289 }
290 }
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600291 // Use the vk_layer_settings.txt file from here, if it is present
292 if (search_path != "") {
Petr Krausc53604b2019-09-06 00:31:48 +0200293 string home_file = search_path + "/vulkan/settings.d/vk_layer_settings.txt";
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600294 if (stat(home_file.c_str(), &info) == 0) {
295 if (info.st_mode & S_IFREG) {
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600296 settings_info.source = kVkConfig;
297 settings_info.location = home_file;
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600298 return home_file;
299 }
300 }
301 }
302
303#endif
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600304 // Look for an enviornment variable override for the settings file location
Petr Krausc53604b2019-09-06 00:31:48 +0200305 string env_path = GetEnvironment("VK_LAYER_SETTINGS_PATH");
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600306
307 // If the path exists use it, else use vk_layer_settings
308 if (stat(env_path.c_str(), &info) == 0) {
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600309 // If this is a directory, append settings file name
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600310 if (info.st_mode & S_IFDIR) {
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600311 env_path.append("/vk_layer_settings.txt");
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600312 }
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600313 settings_info.source = kEnvVar;
314 settings_info.location = env_path;
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600315 return env_path;
316 }
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600317
318 // Default -- use the current working directory for the settings file location
319 settings_info.source = kLocal;
320 char buff[512];
321 auto buf_ptr = GetCurrentDir(buff, 512);
322 if (buf_ptr) {
323 settings_info.location = buf_ptr;
324 settings_info.location.append("\\vk_layer_settings.txt");
325 }
Lenny Komow5c57fcb2018-10-02 09:18:51 -0600326 return "vk_layer_settings.txt";
327}
328
Petr Krausc53604b2019-09-06 00:31:48 +0200329void ConfigFile::ParseFile(const char *filename) {
Petr Krausc53604b2019-09-06 00:31:48 +0200330 file_is_parsed_ = true;
Jon Ashburnbe582642014-12-22 12:04:40 -0700331
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600332 // Extract option = value pairs from a file
Petr Kraus168417e2019-09-07 16:45:40 +0200333 std::ifstream file(filename);
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600334 if (file.good()) {
335 settings_info.file_found = true;
336 for (string line; std::getline(file, line);) {
337 // discard comments, which start with '#'
338 const auto comments_pos = line.find_first_of('#');
339 if (comments_pos != string::npos) line.erase(comments_pos);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600340
Mark Lobodzinskif5b17152020-06-09 10:16:31 -0600341 const auto value_pos = line.find_first_of('=');
342 if (value_pos != string::npos) {
343 const string option = string_trim(line.substr(0, value_pos));
344 const string value = string_trim(line.substr(value_pos + 1));
345 value_map_[option] = value;
346 }
Ricardo Garcia5efc3922019-11-21 16:43:27 +0100347 }
Jon Ashburnbe582642014-12-22 12:04:40 -0700348 }
349}
350
Mark Young6ba8abe2017-11-09 10:37:04 -0700351VK_LAYER_EXPORT void PrintMessageFlags(VkFlags vk_flags, char *msg_flags) {
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600352 bool separator = false;
353
354 msg_flags[0] = 0;
Mark Young6ba8abe2017-11-09 10:37:04 -0700355 if (vk_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600356 strcat(msg_flags, "DEBUG");
357 separator = true;
358 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700359 if (vk_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700360 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600361 strcat(msg_flags, "INFO");
362 separator = true;
363 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700364 if (vk_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700365 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600366 strcat(msg_flags, "WARN");
367 separator = true;
368 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700369 if (vk_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700370 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600371 strcat(msg_flags, "PERF");
372 separator = true;
373 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700374 if (vk_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700375 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600376 strcat(msg_flags, "ERROR");
377 }
378}
Mark Young6ba8abe2017-11-09 10:37:04 -0700379
380VK_LAYER_EXPORT void PrintMessageSeverity(VkFlags vk_flags, char *msg_flags) {
381 bool separator = false;
382
383 msg_flags[0] = 0;
384 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
385 strcat(msg_flags, "VERBOSE");
386 separator = true;
387 }
388 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
389 if (separator) strcat(msg_flags, ",");
390 strcat(msg_flags, "INFO");
391 separator = true;
392 }
393 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
394 if (separator) strcat(msg_flags, ",");
395 strcat(msg_flags, "WARN");
396 separator = true;
397 }
398 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
399 if (separator) strcat(msg_flags, ",");
400 strcat(msg_flags, "ERROR");
401 }
402}
403
404VK_LAYER_EXPORT void PrintMessageType(VkFlags vk_flags, char *msg_flags) {
405 bool separator = false;
406
407 msg_flags[0] = 0;
408 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
409 strcat(msg_flags, "GEN");
410 separator = true;
411 }
412 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +0200413 if (separator) strcat(msg_flags, ",");
Mark Young6ba8abe2017-11-09 10:37:04 -0700414 strcat(msg_flags, "SPEC");
415 separator = true;
416 }
417 if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) {
418 if (separator) strcat(msg_flags, ",");
419 strcat(msg_flags, "PERF");
Mark Young6ba8abe2017-11-09 10:37:04 -0700420 }
421}
sfricke-samsung98acb882020-11-03 19:16:10 -0800422
423// This catches before dlopen fails if the default Android-26 layers are being used and attempted to be ran on Android 25 or below
424#if defined(__ANDROID__)
425#include "android_ndk_types.h" // get AHB_VALIDATION_SUPPORT macro
426void __attribute__((constructor)) CheckAndroidVersion();
427void CheckAndroidVersion() {
428#ifdef AHB_VALIDATION_SUPPORT
429 string version_env = GetEnvironment("ro.build.version.sdk");
430 int target_version = atoi(version_env.c_str());
431
432 // atoi returns 0 if GetEnvironment fails and don't want false positive errors
433 if ((target_version != 0) && (target_version < 26)) {
434 LOGCONSOLE(
435 "ERROR - Targeted Android version is %d and needs to be 26 or above. Please read "
436 "https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/BUILD.md for how to build the Validation Layers "
437 "for Android 25 and below",
438 target_version);
439 }
440#endif // AHB_VALIDATION_SUPPORT
441}
442#endif // defined(__ANDROID__)