vk_layer_logging.h revision f8155e48c6ce161cb0e9a2c4e2b8eb0b19cc99b4
1/* 2 * Vulkan 3 * 4 * Copyright (C) 2014 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS 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. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Courtney Goeltzenleuchter <courtney@lunarg.com> 26 */ 27 28#ifndef LAYER_LOGGING_H 29#define LAYER_LOGGING_H 30 31#include <stdio.h> 32#include <stdarg.h> 33#include <stdbool.h> 34#include <unordered_map> 35#include <inttypes.h> 36#include "vk_layer.h" 37#include "vk_layer_data.h" 38#include "vk_layer_table.h" 39 40typedef struct _debug_report_data { 41 VkLayerDbgFunctionNode *g_pDbgFunctionHead; 42 VkFlags active_flags; 43 bool g_DEBUG_REPORT; 44} debug_report_data; 45 46template debug_report_data *get_my_data_ptr<debug_report_data>( 47 void *data_key, 48 std::unordered_map<void *, debug_report_data *> &data_map); 49 50// Utility function to handle reporting 51static inline void debug_report_log_msg( 52 debug_report_data *debug_data, 53 VkFlags msgFlags, 54 VkDbgObjectType objectType, 55 uint64_t srcObject, 56 size_t location, 57 int32_t msgCode, 58 const char* pLayerPrefix, 59 const char* pMsg) 60{ 61 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead; 62 while (pTrav) { 63 if (pTrav->msgFlags & msgFlags) { 64 pTrav->pfnMsgCallback(msgFlags, 65 objectType, srcObject, 66 location, 67 msgCode, 68 pLayerPrefix, 69 pMsg, 70 (void *) pTrav->pUserData); 71 } 72 pTrav = pTrav->pNext; 73 } 74} 75 76static inline debug_report_data *debug_report_create_instance( 77 VkLayerInstanceDispatchTable *table, 78 VkInstance inst, 79 uint32_t extension_count, 80 const char*const* ppEnabledExtensions) // layer or extension name to be enabled 81{ 82 debug_report_data *debug_data; 83 PFN_vkGetInstanceProcAddr gpa = table->GetInstanceProcAddr; 84 85 table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback"); 86 table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback"); 87 88 debug_data = (debug_report_data *) malloc(sizeof(debug_report_data)); 89 if (!debug_data) return NULL; 90 91 memset(debug_data, 0, sizeof(debug_report_data)); 92 for (uint32_t i = 0; i < extension_count; i++) { 93 /* TODO: Check other property fields */ 94 if (strcmp(ppEnabledExtensions[i], VK_DEBUG_REPORT_EXTENSION_NAME) == 0) { 95 debug_data->g_DEBUG_REPORT = true; 96 } 97 } 98 return debug_data; 99} 100 101static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data) 102{ 103 VkLayerDbgFunctionNode *pTrav; 104 VkLayerDbgFunctionNode *pTravNext; 105 106 if (!debug_data) { 107 return; 108 } 109 110 pTrav = debug_data->g_pDbgFunctionHead; 111 /* Clear out any leftover callbacks */ 112 while (pTrav) { 113 pTravNext = pTrav->pNext; 114 115 debug_report_log_msg( 116 debug_data, VK_DBG_REPORT_WARN_BIT, 117 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback.handle, 118 0, DEBUG_REPORT_CALLBACK_REF, 119 "DebugReport", 120 "Debug Report callbacks not removed before DestroyInstance"); 121 122 free(pTrav); 123 pTrav = pTravNext; 124 } 125 debug_data->g_pDbgFunctionHead = NULL; 126 127 free(debug_data); 128} 129 130static inline debug_report_data *layer_debug_report_create_device( 131 debug_report_data *instance_debug_data, 132 VkDevice device) 133{ 134 /* DEBUG_REPORT shares data between Instance and Device, 135 * so just return instance's data pointer */ 136 return instance_debug_data; 137} 138 139static inline void layer_debug_report_destroy_device(VkDevice device) 140{ 141 /* Nothing to do since we're using instance data record */ 142} 143 144static inline VkResult layer_create_msg_callback( 145 debug_report_data *debug_data, 146 VkFlags msgFlags, 147 const PFN_vkDbgMsgCallback pfnMsgCallback, 148 void *pUserData, 149 VkDbgMsgCallback *pMsgCallback) 150{ 151 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode)); 152 if (!pNewDbgFuncNode) 153 return VK_ERROR_OUT_OF_HOST_MEMORY; 154 155 pNewDbgFuncNode->msgCallback = *pMsgCallback; 156 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback; 157 pNewDbgFuncNode->msgFlags = msgFlags; 158 pNewDbgFuncNode->pUserData = pUserData; 159 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead; 160 161 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode; 162 debug_data->active_flags |= msgFlags; 163 164 debug_report_log_msg( 165 debug_data, VK_DBG_REPORT_DEBUG_BIT, 166 VK_OBJECT_TYPE_MSG_CALLBACK, (*pMsgCallback).handle, 167 0, DEBUG_REPORT_CALLBACK_REF, 168 "DebugReport", 169 "Added callback"); 170 return VK_SUCCESS; 171} 172 173static inline void layer_destroy_msg_callback( 174 debug_report_data *debug_data, 175 VkDbgMsgCallback msg_callback) 176{ 177 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead; 178 VkLayerDbgFunctionNode *pPrev = pTrav; 179 bool matched; 180 181 debug_data->active_flags = 0; 182 while (pTrav) { 183 if (pTrav->msgCallback == msg_callback) { 184 matched = true; 185 pPrev->pNext = pTrav->pNext; 186 if (debug_data->g_pDbgFunctionHead == pTrav) { 187 debug_data->g_pDbgFunctionHead = pTrav->pNext; 188 } 189 debug_report_log_msg( 190 debug_data, VK_DBG_REPORT_DEBUG_BIT, 191 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback.handle, 192 0, DEBUG_REPORT_NONE, 193 "DebugReport", 194 "Destroyed callback"); 195 } else { 196 matched = false; 197 debug_data->active_flags |= pTrav->msgFlags; 198 } 199 pPrev = pTrav; 200 pTrav = pTrav->pNext; 201 if (matched) { 202 free(pPrev); 203 } 204 } 205} 206 207static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr( 208 debug_report_data *debug_data, 209 const char *funcName) 210{ 211 if (!debug_data || !debug_data->g_DEBUG_REPORT) { 212 return NULL; 213 } 214 215 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) { 216 return (PFN_vkVoidFunction) vkDbgCreateMsgCallback; 217 } 218 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) { 219 return (PFN_vkVoidFunction) vkDbgDestroyMsgCallback; 220 } 221 222 return NULL; 223} 224 225/* 226 * Output log message via DEBUG_REPORT 227 * Takes format and variable arg list so that output string 228 * is only computed if a message needs to be logged 229 */ 230static inline void log_msg( 231 debug_report_data *debug_data, 232 VkFlags msgFlags, 233 VkDbgObjectType objectType, 234 uint64_t srcObject, 235 size_t location, 236 int32_t msgCode, 237 const char* pLayerPrefix, 238 const char* format, 239 ...) 240{ 241 if (!debug_data || !(debug_data->active_flags & msgFlags)) { 242 /* message is not wanted */ 243 return; 244 } 245 246 char str[1024]; 247 va_list argptr; 248 va_start(argptr, format); 249 vsnprintf(str, 1024, format, argptr); 250 va_end(argptr); 251 debug_report_log_msg(debug_data, msgFlags, objectType, 252 srcObject, location, msgCode, 253 pLayerPrefix, str); 254} 255 256static inline void VKAPI log_callback( 257 VkFlags msgFlags, 258 VkDbgObjectType objType, 259 uint64_t srcObject, 260 size_t location, 261 int32_t msgCode, 262 const char* pLayerPrefix, 263 const char* pMsg, 264 void* pUserData) 265{ 266 char msg_flags[30]; 267 268 print_msg_flags(msgFlags, msg_flags); 269 270 fprintf((FILE *) pUserData, "%s(%s): object: %#" PRIx64 " type: %d location: %zu msgCode: %d: %s\n", 271 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg); 272} 273#endif // LAYER_LOGGING_H 274