Home | History | Annotate | Download | only in layers
      1 /**************************************************************************
      2  *
      3  * Copyright 2014 Valve Software
      4  * Copyright 2015 Google Inc.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23  * THE SOFTWARE.
     24  *
     25  * Author: Jon Ashburn <jon (at) lunarg.com>
     26  * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com>
     27  * Author: Tobin Ehlis <tobin (at) lunarg.com>
     28  **************************************************************************/
     29 #include <fstream>
     30 #include <string>
     31 #include <map>
     32 #include <string.h>
     33 #include <vulkan/vk_layer.h>
     34 #include <iostream>
     35 #include "vk_layer_config.h"
     36 #include "vulkan/vk_sdk_platform.h"
     37 
     38 #define MAX_CHARS_PER_LINE 4096
     39 
     40 class ConfigFile {
     41   public:
     42     ConfigFile();
     43     ~ConfigFile();
     44 
     45     const char *getOption(const std::string &_option);
     46     void setOption(const std::string &_option, const std::string &_val);
     47 
     48   private:
     49     bool m_fileIsParsed;
     50     std::map<std::string, std::string> m_valueMap;
     51 
     52     void parseFile(const char *filename);
     53 };
     54 
     55 static ConfigFile g_configFileObj;
     56 
     57 static VkLayerDbgAction stringToDbgAction(const char *_enum) {
     58     // only handles single enum values
     59     if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_IGNORE"))
     60         return VK_DBG_LAYER_ACTION_IGNORE;
     61     else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_LOG_MSG"))
     62         return VK_DBG_LAYER_ACTION_LOG_MSG;
     63 #ifdef WIN32
     64     else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"))
     65         return VK_DBG_LAYER_ACTION_DEBUG_OUTPUT;
     66 #endif
     67     else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_BREAK"))
     68         return VK_DBG_LAYER_ACTION_BREAK;
     69     return (VkLayerDbgAction)0;
     70 }
     71 
     72 static VkFlags stringToDbgReportFlags(const char *_enum) {
     73     // only handles single enum values
     74     if (!strcmp(_enum, "VK_DEBUG_REPORT_INFO"))
     75         return VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
     76     else if (!strcmp(_enum, "VK_DEBUG_REPORT_WARN"))
     77         return VK_DEBUG_REPORT_WARNING_BIT_EXT;
     78     else if (!strcmp(_enum, "VK_DEBUG_REPORT_PERF_WARN"))
     79         return VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
     80     else if (!strcmp(_enum, "VK_DEBUG_REPORT_ERROR"))
     81         return VK_DEBUG_REPORT_ERROR_BIT_EXT;
     82     else if (!strcmp(_enum, "VK_DEBUG_REPORT_DEBUG"))
     83         return VK_DEBUG_REPORT_DEBUG_BIT_EXT;
     84     return (VkFlags)0;
     85 }
     86 
     87 static unsigned int convertStringEnumVal(const char *_enum) {
     88     unsigned int ret;
     89 
     90     ret = stringToDbgAction(_enum);
     91     if (ret)
     92         return ret;
     93 
     94     return stringToDbgReportFlags(_enum);
     95 }
     96 
     97 const char *getLayerOption(const char *_option) { return g_configFileObj.getOption(_option); }
     98 
     99 // If option is NULL or stdout, return stdout, otherwise try to open option
    100 //  as a filename. If successful, return file handle, otherwise stdout
    101 FILE *getLayerLogOutput(const char *_option, const char *layerName) {
    102     FILE *log_output = NULL;
    103     if (!_option || !strcmp("stdout", _option))
    104         log_output = stdout;
    105     else {
    106         log_output = fopen(_option, "w");
    107         if (log_output == NULL) {
    108             if (_option)
    109                 std::cout << std::endl
    110                           << layerName << " ERROR: Bad output filename specified: " << _option << ". Writing to STDOUT instead"
    111                           << std::endl
    112                           << std::endl;
    113             log_output = stdout;
    114         }
    115     }
    116     return log_output;
    117 }
    118 
    119 VkDebugReportFlagsEXT getLayerOptionFlags(const char *_option, uint32_t optionDefault) {
    120     VkDebugReportFlagsEXT flags = optionDefault;
    121     const char *option = (g_configFileObj.getOption(_option));
    122 
    123     /* parse comma-separated options */
    124     while (option) {
    125         const char *p = strchr(option, ',');
    126         size_t len;
    127 
    128         if (p)
    129             len = p - option;
    130         else
    131             len = strlen(option);
    132 
    133         if (len > 0) {
    134             if (strncmp(option, "warn", len) == 0) {
    135                 flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
    136             } else if (strncmp(option, "info", len) == 0) {
    137                 flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
    138             } else if (strncmp(option, "perf", len) == 0) {
    139                 flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    140             } else if (strncmp(option, "error", len) == 0) {
    141                 flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
    142             } else if (strncmp(option, "debug", len) == 0) {
    143                 flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
    144             }
    145         }
    146 
    147         if (!p)
    148             break;
    149 
    150         option = p + 1;
    151     }
    152     return flags;
    153 }
    154 
    155 bool getLayerOptionEnum(const char *_option, uint32_t *optionDefault) {
    156     bool res;
    157     const char *option = (g_configFileObj.getOption(_option));
    158     if (option != NULL) {
    159         *optionDefault = convertStringEnumVal(option);
    160         res = false;
    161     } else {
    162         res = true;
    163     }
    164     return res;
    165 }
    166 
    167 void setLayerOptionEnum(const char *_option, const char *_valEnum) {
    168     unsigned int val = convertStringEnumVal(_valEnum);
    169     char strVal[24];
    170     snprintf(strVal, 24, "%u", val);
    171     g_configFileObj.setOption(_option, strVal);
    172 }
    173 
    174 void setLayerOption(const char *_option, const char *_val) { g_configFileObj.setOption(_option, _val); }
    175 
    176 ConfigFile::ConfigFile() : m_fileIsParsed(false) {}
    177 
    178 ConfigFile::~ConfigFile() {}
    179 
    180 const char *ConfigFile::getOption(const std::string &_option) {
    181     std::map<std::string, std::string>::const_iterator it;
    182     if (!m_fileIsParsed) {
    183         parseFile("vk_layer_settings.txt");
    184     }
    185 
    186     if ((it = m_valueMap.find(_option)) == m_valueMap.end())
    187         return NULL;
    188     else
    189         return it->second.c_str();
    190 }
    191 
    192 void ConfigFile::setOption(const std::string &_option, const std::string &_val) {
    193     if (!m_fileIsParsed) {
    194         parseFile("vk_layer_settings.txt");
    195     }
    196 
    197     m_valueMap[_option] = _val;
    198 }
    199 
    200 void ConfigFile::parseFile(const char *filename) {
    201     std::ifstream file;
    202     char buf[MAX_CHARS_PER_LINE];
    203 
    204     m_fileIsParsed = true;
    205     m_valueMap.clear();
    206 
    207     file.open(filename);
    208     if (!file.good())
    209         return;
    210 
    211     // read tokens from the file and form option, value pairs
    212     file.getline(buf, MAX_CHARS_PER_LINE);
    213     while (!file.eof()) {
    214         char option[512];
    215         char value[512];
    216 
    217         char *pComment;
    218 
    219         // discard any comments delimited by '#' in the line
    220         pComment = strchr(buf, '#');
    221         if (pComment)
    222             *pComment = '\0';
    223 
    224         if (sscanf(buf, " %511[^\n\t =] = %511[^\n \t]", option, value) == 2) {
    225             std::string optStr(option);
    226             std::string valStr(value);
    227             m_valueMap[optStr] = valStr;
    228         }
    229         file.getline(buf, MAX_CHARS_PER_LINE);
    230     }
    231 }
    232 
    233 void print_msg_flags(VkFlags msgFlags, char *msg_flags) {
    234     bool separator = false;
    235 
    236     msg_flags[0] = 0;
    237     if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
    238         strcat(msg_flags, "DEBUG");
    239         separator = true;
    240     }
    241     if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
    242         if (separator)
    243             strcat(msg_flags, ",");
    244         strcat(msg_flags, "INFO");
    245         separator = true;
    246     }
    247     if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
    248         if (separator)
    249             strcat(msg_flags, ",");
    250         strcat(msg_flags, "WARN");
    251         separator = true;
    252     }
    253     if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
    254         if (separator)
    255             strcat(msg_flags, ",");
    256         strcat(msg_flags, "PERF");
    257         separator = true;
    258     }
    259     if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
    260         if (separator)
    261             strcat(msg_flags, ",");
    262         strcat(msg_flags, "ERROR");
    263     }
    264 }
    265