blob: ffefbcd6b690f30b5a54eefd22294b7f80142b80 [file] [log] [blame]
Jon Ashburnbe582642014-12-22 12:04:40 -07001/**************************************************************************
2 *
Jon Ashburne922f712015-11-03 13:41:23 -07003 * Copyright 2014 Valve Software
Michael Lentine695f2c22015-09-09 12:39:13 -07004 * Copyright 2015 Google Inc.
Jon Ashburnbe582642014-12-22 12:04:40 -07005 * All Rights Reserved.
6 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06007 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
Jon Ashburnbe582642014-12-22 12:04:40 -070010 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011 * http://www.apache.org/licenses/LICENSE-2.0
Jon Ashburnbe582642014-12-22 12:04:40 -070012 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060013 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jon Ashburnbe582642014-12-22 12:04:40 -070018 *
Jon Ashburne922f712015-11-03 13:41:23 -070019 * Author: Jon Ashburn <jon@lunarg.com>
20 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
21 * Author: Tobin Ehlis <tobin@lunarg.com>
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060022 * Author: Mark Lobodzinski <mark@lunarg.com>
Jon Ashburnbe582642014-12-22 12:04:40 -070023 **************************************************************************/
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060024#include "vk_layer_config.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070025#include "vulkan/vk_sdk_platform.h"
Lenny Komow807ebf02016-09-30 14:15:25 -060026#include <fstream>
27#include <iostream>
28#include <map>
29#include <string.h>
30#include <string>
31#include <sys/stat.h>
32#include <vulkan/vk_layer.h>
Jon Ashburnbe582642014-12-22 12:04:40 -070033
34#define MAX_CHARS_PER_LINE 4096
35
Jon Ashburn5484e0c2016-03-08 17:48:44 -070036class ConfigFile {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070037 public:
Jon Ashburnbe582642014-12-22 12:04:40 -070038 ConfigFile();
39 ~ConfigFile();
40
41 const char *getOption(const std::string &_option);
Jon Ashburndec60512015-01-13 17:24:01 -070042 void setOption(const std::string &_option, const std::string &_val);
43
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070044 private:
Jon Ashburnbe582642014-12-22 12:04:40 -070045 bool m_fileIsParsed;
46 std::map<std::string, std::string> m_valueMap;
47
48 void parseFile(const char *filename);
49};
50
51static ConfigFile g_configFileObj;
Jon Ashburndec60512015-01-13 17:24:01 -070052
Lenny Komow807ebf02016-09-30 14:15:25 -060053std::string getEnvironment(const char *variable) {
54#if !defined(__ANDROID__) && !defined(_WIN32)
55 const char *output = getenv(variable);
56 return output == NULL ? "" : output;
57#elif defined(_WIN32)
58 int size = GetEnvironmentVariable(variable, NULL, 0);
59 if (size == 0) {
60 return "";
61 }
62 char *buffer = new char[size];
63 GetEnvironmentVariable(variable, buffer, size);
64 std::string output = buffer;
65 delete[] buffer;
66 return output;
67#else
68 return "";
69#endif
70}
71
Jon Ashburn5484e0c2016-03-08 17:48:44 -070072const char *getLayerOption(const char *_option) { return g_configFileObj.getOption(_option); }
Jon Ashburnbe582642014-12-22 12:04:40 -070073
Tobin Ehlisb1df55e2015-09-15 09:55:54 -060074// If option is NULL or stdout, return stdout, otherwise try to open option
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060075// as a filename. If successful, return file handle, otherwise stdout
Jon Ashburn5484e0c2016-03-08 17:48:44 -070076FILE *getLayerLogOutput(const char *_option, const char *layerName) {
77 FILE *log_output = NULL;
Tobin Ehlisb1df55e2015-09-15 09:55:54 -060078 if (!_option || !strcmp("stdout", _option))
79 log_output = stdout;
80 else {
81 log_output = fopen(_option, "w");
82 if (log_output == NULL) {
83 if (_option)
Jon Ashburn5484e0c2016-03-08 17:48:44 -070084 std::cout << std::endl
85 << layerName << " ERROR: Bad output filename specified: " << _option << ". Writing to STDOUT instead"
86 << std::endl
87 << std::endl;
Tobin Ehlisb1df55e2015-09-15 09:55:54 -060088 log_output = stdout;
89 }
90 }
Cody Northrope3e39ef2015-09-16 08:35:29 -060091 return log_output;
Tobin Ehlisb1df55e2015-09-15 09:55:54 -060092}
93
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060094// Map option strings to flag enum values
95VkFlags GetLayerOptionFlags(std::string _option, std::unordered_map<std::string, VkFlags> const &enum_data,
96 uint32_t option_default) {
97 VkDebugReportFlagsEXT flags = option_default;
98 std::string option_list = g_configFileObj.getOption(_option.c_str());
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -060099
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600100 while (option_list.length() != 0) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600101 // Find length of option string
102 std::size_t option_length = option_list.find(",");
103 if (option_length == option_list.npos) {
104 option_length = option_list.size();
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600105 }
106
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600107 // Get first option in list
108 const std::string option = option_list.substr(0, option_length);
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600109
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600110 auto enum_value = enum_data.find(option);
111 if (enum_value != enum_data.end()) {
112 flags |= enum_value->second;
113 }
114
115 // Remove first option from option_list
116 option_list.erase(0, option_length);
117 // Remove possible comma separator
118 std::size_t char_position = option_list.find(",");
119 if (char_position == 0) {
120 option_list.erase(char_position, 1);
121 }
122 // Remove possible space
123 char_position = option_list.find(" ");
124 if (char_position == 0) {
125 option_list.erase(char_position, 1);
126 }
Courtney Goeltzenleuchterb874b8c2015-06-14 11:34:49 -0600127 }
128 return flags;
129}
130
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700131void setLayerOption(const char *_option, const char *_val) { g_configFileObj.setOption(_option, _val); }
Jon Ashburndec60512015-01-13 17:24:01 -0700132
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600133// Constructor for ConfigFile. Initialize layers to log error messages to stdout by default. If a vk_layer_settings file is present,
134// its settings will override the defaults.
135ConfigFile::ConfigFile() : m_fileIsParsed(false) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600136 m_valueMap["lunarg_core_validation.report_flags"] = "error";
137 m_valueMap["lunarg_image.report_flags"] = "error";
138 m_valueMap["lunarg_object_tracker.report_flags"] = "error";
139 m_valueMap["lunarg_parameter_validation.report_flags"] = "error";
140 m_valueMap["lunarg_swapchain.report_flags"] = "error";
141 m_valueMap["google_threading.report_flags"] = "error";
Mark Lobodzinskiad8448e2016-08-26 08:35:19 -0600142 m_valueMap["google_unique_objects.report_flags"] = "error";
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600143
144#ifdef WIN32
145 // For Windows, enable message logging AND OutputDebugString
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700146 m_valueMap["lunarg_core_validation.debug_action"] =
147 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
148 m_valueMap["lunarg_image.debug_action"] =
149 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
150 m_valueMap["lunarg_object_tracker.debug_action"] =
151 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
152 m_valueMap["lunarg_parameter_validation.debug_action"] =
153 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
154 m_valueMap["lunarg_swapchain.debug_action"] =
155 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
156 m_valueMap["google_threading.debug_action"] =
157 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
158 m_valueMap["google_unique_objects.debug_action"] =
159 "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700160#else // WIN32
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600161 m_valueMap["lunarg_core_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
162 m_valueMap["lunarg_image.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
163 m_valueMap["lunarg_object_tracker.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
164 m_valueMap["lunarg_parameter_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
165 m_valueMap["lunarg_swapchain.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
166 m_valueMap["google_threading.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
Mark Lobodzinskiad8448e2016-08-26 08:35:19 -0600167 m_valueMap["google_unique_objects.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700168#endif // WIN32
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600169
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600170 m_valueMap["lunarg_core_validation.log_filename"] = "stdout";
171 m_valueMap["lunarg_image.log_filename"] = "stdout";
172 m_valueMap["lunarg_object_tracker.log_filename"] = "stdout";
173 m_valueMap["lunarg_parameter_validation.log_filename"] = "stdout";
174 m_valueMap["lunarg_swapchain.log_filename"] = "stdout";
175 m_valueMap["google_threading.log_filename"] = "stdout";
Mark Lobodzinskiad8448e2016-08-26 08:35:19 -0600176 m_valueMap["google_unique_objects.log_filename"] = "stdout";
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600177}
Jon Ashburnbe582642014-12-22 12:04:40 -0700178
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700179ConfigFile::~ConfigFile() {}
Jon Ashburnbe582642014-12-22 12:04:40 -0700180
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700181const char *ConfigFile::getOption(const std::string &_option) {
Jon Ashburnbe582642014-12-22 12:04:40 -0700182 std::map<std::string, std::string>::const_iterator it;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700183 if (!m_fileIsParsed) {
Lenny Komow807ebf02016-09-30 14:15:25 -0600184 std::string envPath = getEnvironment("VK_LAYER_SETTINGS_PATH");
185
186 // If the path exists use it, else use vk_layer_settings
187 struct stat info;
188 if (stat(envPath.c_str(), &info) == 0) {
189 // If this is a directory, look for vk_layer_settings within the directory
190 if (info.st_mode & S_IFDIR) {
191 envPath += "/vk_layer_settings.txt";
192 }
193 parseFile(envPath.c_str());
194 } else {
Cody Northrop885e82e2017-05-04 10:16:46 -0600195 parseFile("vk_layer_settings.txt");
Lenny Komow807ebf02016-09-30 14:15:25 -0600196 }
Jon Ashburnbe582642014-12-22 12:04:40 -0700197 }
198
199 if ((it = m_valueMap.find(_option)) == m_valueMap.end())
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600200 return "";
Jon Ashburnbe582642014-12-22 12:04:40 -0700201 else
202 return it->second.c_str();
203}
204
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700205void ConfigFile::setOption(const std::string &_option, const std::string &_val) {
206 if (!m_fileIsParsed) {
Lenny Komow807ebf02016-09-30 14:15:25 -0600207 std::string envPath = getEnvironment("VK_LAYER_SETTINGS_PATH");
208
209 // If the path exists use it, else use vk_layer_settings
210 struct stat info;
211 if (stat(envPath.c_str(), &info) == 0) {
212 // If this is a directory, look for vk_layer_settings within the directory
213 if (info.st_mode & S_IFDIR) {
214 envPath += "/vk_layer_settings.txt";
215 }
216 parseFile(envPath.c_str());
217 } else {
Cody Northrop885e82e2017-05-04 10:16:46 -0600218 parseFile("vk_layer_settings.txt");
Lenny Komow807ebf02016-09-30 14:15:25 -0600219 }
Jon Ashburndec60512015-01-13 17:24:01 -0700220 }
221
222 m_valueMap[_option] = _val;
223}
224
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700225void ConfigFile::parseFile(const char *filename) {
Jon Ashburnbe582642014-12-22 12:04:40 -0700226 std::ifstream file;
227 char buf[MAX_CHARS_PER_LINE];
228
229 m_fileIsParsed = true;
Jon Ashburnbe582642014-12-22 12:04:40 -0700230
231 file.open(filename);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600232 if (!file.good()) {
Jon Ashburnbe582642014-12-22 12:04:40 -0700233 return;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600234 }
235
Jon Ashburnbe582642014-12-22 12:04:40 -0700236 // read tokens from the file and form option, value pairs
237 file.getline(buf, MAX_CHARS_PER_LINE);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700238 while (!file.eof()) {
Jon Ashburnbe582642014-12-22 12:04:40 -0700239 char option[512];
240 char value[512];
241
242 char *pComment;
243
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700244 // discard any comments delimited by '#' in the line
Jon Ashburnbe582642014-12-22 12:04:40 -0700245 pComment = strchr(buf, '#');
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700246 if (pComment) *pComment = '\0';
Jon Ashburnbe582642014-12-22 12:04:40 -0700247
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700248 if (sscanf(buf, " %511[^\n\t =] = %511[^\n \t]", option, value) == 2) {
Jon Ashburnbe582642014-12-22 12:04:40 -0700249 std::string optStr(option);
250 std::string valStr(value);
251 m_valueMap[optStr] = valStr;
252 }
253 file.getline(buf, MAX_CHARS_PER_LINE);
254 }
255}
256
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700257void print_msg_flags(VkFlags msgFlags, char *msg_flags) {
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600258 bool separator = false;
259
260 msg_flags[0] = 0;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700261 if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600262 strcat(msg_flags, "DEBUG");
263 separator = true;
264 }
Mark Lobodzinski510e20d2016-02-11 09:26:16 -0700265 if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700266 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600267 strcat(msg_flags, "INFO");
268 separator = true;
269 }
Mark Lobodzinski510e20d2016-02-11 09:26:16 -0700270 if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700271 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600272 strcat(msg_flags, "WARN");
273 separator = true;
274 }
Mark Lobodzinski510e20d2016-02-11 09:26:16 -0700275 if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700276 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600277 strcat(msg_flags, "PERF");
278 separator = true;
279 }
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700280 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700281 if (separator) strcat(msg_flags, ",");
Courtney Goeltzenleuchterf85e3612015-06-14 11:33:06 -0600282 strcat(msg_flags, "ERROR");
283 }
284}