1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
/* Copyright (c) 2015-2016, 2020-2023 The Khronos Group Inc.
* Copyright (c) 2015-2016, 2020-2023 Valve Corporation
* Copyright (c) 2015-2016, 2020-2023 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Mark Lobodzinski <mark@lunarg.com>
* Author: Dave Houlton <daveh@lunarg.com>
*
*/
#include "vk_layer_utils.h"
#include <string.h>
#include <string>
#include <vector>
#include "vulkan/vulkan.h"
#include "vk_layer_config.h"
// Include new / delete overrides if using mimalloc. This needs to be include exactly once in a file that is
// part of the layer utils library.
#if defined(USE_MIMALLOC) && defined(_WIN64)
#include "mimalloc-new-delete.h"
#endif
static const uint8_t kUtF8OneByteCode = 0xC0;
static const uint8_t kUtF8OneByteMask = 0xE0;
static const uint8_t kUtF8TwoByteCode = 0xE0;
static const uint8_t kUtF8TwoByteMask = 0xF0;
static const uint8_t kUtF8ThreeByteCode = 0xF0;
static const uint8_t kUtF8ThreeByteMask = 0xF8;
static const uint8_t kUtF8DataByteCode = 0x80;
static const uint8_t kUtF8DataByteMask = 0xC0;
VK_LAYER_EXPORT VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
VkStringErrorFlags result = VK_STRING_ERROR_NONE;
int num_char_bytes = 0;
int i, j;
for (i = 0; i <= max_length; i++) {
if (utf8[i] == 0) {
break;
} else if (i == max_length) {
result |= VK_STRING_ERROR_LENGTH;
break;
} else if ((utf8[i] >= 0xa) && (utf8[i] < 0x7f)) {
num_char_bytes = 0;
} else if ((utf8[i] & kUtF8OneByteMask) == kUtF8OneByteCode) {
num_char_bytes = 1;
} else if ((utf8[i] & kUtF8TwoByteMask) == kUtF8TwoByteCode) {
num_char_bytes = 2;
} else if ((utf8[i] & kUtF8ThreeByteMask) == kUtF8ThreeByteCode) {
num_char_bytes = 3;
} else {
result |= VK_STRING_ERROR_BAD_DATA;
break;
}
// Validate the following num_char_bytes of data
for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
if (++i == max_length) {
result |= VK_STRING_ERROR_LENGTH;
break;
}
if ((utf8[i] & kUtF8DataByteMask) != kUtF8DataByteCode) {
result |= VK_STRING_ERROR_BAD_DATA;
break;
}
}
if (result != VK_STRING_ERROR_NONE) break;
}
return result;
}
// Utility function for determining if a string is in a set of strings
VK_LAYER_EXPORT bool white_list(const char *item, const std::set<std::string> &list) { return (list.find(item) != list.end()); }
// Debug callbacks get created in three ways:
// o Application-defined debug callbacks
// o Through settings in a vk_layer_settings.txt file
// o By default, if neither an app-defined debug callback nor a vk_layer_settings.txt file is present
//
// At layer initialization time, default logging callbacks are created to output layer error messages.
// If a vk_layer_settings.txt file is present its settings will override any default settings.
//
// If a vk_layer_settings.txt file is present and an application defines a debug callback, both callbacks
// will be active. If no vk_layer_settings.txt file is present, creating an application-defined debug
// callback will cause the default callbacks to be unregisterd and removed.
VK_LAYER_EXPORT void layer_debug_messenger_actions(debug_report_data *report_data, const VkAllocationCallbacks *pAllocator,
const char *layer_identifier) {
VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
std::string report_flags_key = layer_identifier;
std::string debug_action_key = layer_identifier;
std::string log_filename_key = layer_identifier;
report_flags_key.append(".report_flags");
debug_action_key.append(".debug_action");
log_filename_key.append(".log_filename");
// Initialize layer options
LogMessageTypeFlags report_flags = GetLayerOptionFlags(report_flags_key, log_msg_type_option_definitions, 0);
VkLayerDbgActionFlags debug_action = GetLayerOptionFlags(debug_action_key, debug_actions_option_definitions, 0);
// Flag as default if these settings are not from a vk_layer_settings.txt file
const bool default_layer_callback = (debug_action & VK_DBG_LAYER_ACTION_DEFAULT) ? true : false;
auto dbg_create_info = LvlInitStruct<VkDebugUtilsMessengerCreateInfoEXT>();
dbg_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
if (report_flags & kErrorBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
}
if (report_flags & kWarningBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
}
if (report_flags & kPerformanceWarningBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
dbg_create_info.messageType |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
}
if (report_flags & kInformationBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
}
if (report_flags & kDebugBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
}
if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) {
const char *log_filename = getLayerOption(log_filename_key.c_str());
FILE *log_output = getLayerLogOutput(log_filename, layer_identifier);
dbg_create_info.pfnUserCallback = MessengerLogCallback;
dbg_create_info.pUserData = (void *)log_output;
LayerCreateMessengerCallback(report_data, default_layer_callback, &dbg_create_info, pAllocator, &messenger);
}
messenger = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
dbg_create_info.pfnUserCallback = MessengerWin32DebugOutputMsg;
dbg_create_info.pUserData = NULL;
LayerCreateMessengerCallback(report_data, default_layer_callback, &dbg_create_info, pAllocator, &messenger);
}
messenger = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_BREAK) {
dbg_create_info.pfnUserCallback = MessengerBreakCallback;
dbg_create_info.pUserData = NULL;
LayerCreateMessengerCallback(report_data, default_layer_callback, &dbg_create_info, pAllocator, &messenger);
}
}
// NOTE: This function has been deprecated, and the above function (layer_debug_messenger_actions) should be
// used in its place.
VK_LAYER_EXPORT void layer_debug_report_actions(debug_report_data *report_data, const VkAllocationCallbacks *pAllocator,
const char *layer_identifier) {
VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
std::string report_flags_key = layer_identifier;
std::string debug_action_key = layer_identifier;
std::string log_filename_key = layer_identifier;
report_flags_key.append(".report_flags");
debug_action_key.append(".debug_action");
log_filename_key.append(".log_filename");
// Initialize layer options
VkDebugReportFlagsEXT report_flags = GetLayerOptionFlags(report_flags_key, report_flags_option_definitions, 0);
VkLayerDbgActionFlags debug_action = GetLayerOptionFlags(debug_action_key, debug_actions_option_definitions, 0);
// Flag as default if these settings are not from a vk_layer_settings.txt file
const bool default_layer_callback = (debug_action & VK_DBG_LAYER_ACTION_DEFAULT) ? true : false;
if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) {
const char *log_filename = getLayerOption(log_filename_key.c_str());
FILE *log_output = getLayerLogOutput(log_filename, layer_identifier);
auto dbg_create_info = LvlInitStruct<VkDebugReportCallbackCreateInfoEXT>();
dbg_create_info.flags = report_flags;
dbg_create_info.pfnCallback = ReportLogCallback;
dbg_create_info.pUserData = (void *)log_output;
LayerCreateReportCallback(report_data, default_layer_callback, &dbg_create_info, pAllocator, &callback);
}
callback = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
auto dbg_create_info = LvlInitStruct<VkDebugReportCallbackCreateInfoEXT>();
dbg_create_info.flags = report_flags;
dbg_create_info.pfnCallback = ReportWin32DebugOutputMsg;
dbg_create_info.pUserData = NULL;
LayerCreateReportCallback(report_data, default_layer_callback, &dbg_create_info, pAllocator, &callback);
}
callback = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_BREAK) {
auto dbg_create_info = LvlInitStruct<VkDebugReportCallbackCreateInfoEXT>();
dbg_create_info.flags = report_flags;
dbg_create_info.pfnCallback = DebugBreakCallback;
dbg_create_info.pUserData = NULL;
LayerCreateReportCallback(report_data, default_layer_callback, &dbg_create_info, pAllocator, &callback);
}
}
VK_LAYER_EXPORT VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
}
assert(chain_info != NULL);
return chain_info;
}
VK_LAYER_EXPORT VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
}
assert(chain_info != NULL);
return chain_info;
}
|