debug_report.c revision b40f2568bff91895d66848767fdaa540793b5162
1/* 2 * Vulkan 3 * 4 * Copyright (C) 2015 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 * Jon Ashburn <jon@lunarg.com> 26 * Courtney Goeltzenleuchter <courtney@lunarg.com> 27 */ 28 29#include <string.h> 30#include <stdlib.h> 31#include "debug_report.h" 32#include "vkLayer.h" 33 34static const struct loader_extension_property debug_report_extension_info = { 35 .info = { 36 .sType = VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES, 37 .name = DEBUG_REPORT_EXTENSION_NAME, 38 .version = VK_DEBUG_REPORT_EXTENSION_VERSION, 39 .description = "loader: debug report extension", 40 }, 41 .origin = VK_EXTENSION_ORIGIN_LOADER, 42 .hosted = true, 43}; 44 45void debug_report_add_instance_extensions( 46 struct loader_extension_list *ext_list) 47{ 48 loader_add_to_ext_list(ext_list, 1, &debug_report_extension_info); 49} 50 51void debug_report_create_instance( 52 struct loader_instance *ptr_instance) 53{ 54 ptr_instance->debug_report_enabled = has_vk_extension_property( 55 &debug_report_extension_info.info, 56 &ptr_instance->enabled_instance_extensions); 57} 58 59static VkResult debug_report_DbgCreateMsgCallback( 60 VkInstance instance, 61 VkFlags msgFlags, 62 const PFN_vkDbgMsgCallback pfnMsgCallback, 63 void* pUserData, 64 VkDbgMsgCallback* pMsgCallback) 65{ 66 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *) malloc(sizeof(VkLayerDbgFunctionNode)); 67 if (!pNewDbgFuncNode) 68 return VK_ERROR_OUT_OF_HOST_MEMORY; 69 70 struct loader_instance *inst = loader_instance(instance); 71 loader_platform_thread_lock_mutex(&loader_lock); 72 VkResult result = inst->disp->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback); 73 if (result == VK_SUCCESS) { 74 pNewDbgFuncNode->msgCallback = *pMsgCallback; 75 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback; 76 pNewDbgFuncNode->msgFlags = msgFlags; 77 pNewDbgFuncNode->pUserData = pUserData; 78 pNewDbgFuncNode->pNext = inst->DbgFunctionHead; 79 inst->DbgFunctionHead = pNewDbgFuncNode; 80 } else { 81 free(pNewDbgFuncNode); 82 } 83 loader_platform_thread_unlock_mutex(&loader_lock); 84 return result; 85} 86 87static VkResult debug_report_DbgDestroyMsgCallback( 88 VkInstance instance, 89 VkDbgMsgCallback msg_callback) 90{ 91 struct loader_instance *inst = loader_instance(instance); 92 loader_platform_thread_lock_mutex(&loader_lock); 93 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead; 94 VkLayerDbgFunctionNode *pPrev = pTrav; 95 96 VkResult result = inst->disp->DbgDestroyMsgCallback(instance, msg_callback); 97 98 while (pTrav) { 99 if (pTrav->msgCallback == msg_callback) { 100 pPrev->pNext = pTrav->pNext; 101 if (inst->DbgFunctionHead == pTrav) 102 inst->DbgFunctionHead = pTrav->pNext; 103 free(pTrav); 104 break; 105 } 106 pPrev = pTrav; 107 pTrav = pTrav->pNext; 108 } 109 110 loader_platform_thread_unlock_mutex(&loader_lock); 111 return result; 112} 113 114 115/* 116 * This is the instance chain terminator function 117 * for DbgCreateMsgCallback 118 */ 119VkResult loader_DbgCreateMsgCallback( 120 VkInstance instance, 121 VkFlags msgFlags, 122 const PFN_vkDbgMsgCallback pfnMsgCallback, 123 const void* pUserData, 124 VkDbgMsgCallback* pMsgCallback) 125{ 126 VkDbgMsgCallback *icd_info; 127 const struct loader_icd *icd; 128 struct loader_instance *inst; 129 VkResult res; 130 uint32_t storage_idx; 131 132 if (instance == VK_NULL_HANDLE) 133 return VK_ERROR_INVALID_HANDLE; 134 135 assert(loader.icds_scanned); 136 137 for (inst = loader.instances; inst; inst = inst->next) { 138 if ((VkInstance) inst == instance) 139 break; 140 } 141 142 if (inst == VK_NULL_HANDLE) 143 return VK_ERROR_INVALID_HANDLE; 144 145 icd_info = calloc(sizeof(VkDbgMsgCallback), inst->total_icd_count); 146 if (!icd_info) { 147 return VK_ERROR_OUT_OF_HOST_MEMORY; 148 } 149 150 storage_idx = 0; 151 for (icd = inst->icds; icd; icd = icd->next) { 152 if (!icd->DbgCreateMsgCallback) { 153 continue; 154 } 155 156 res = icd->DbgCreateMsgCallback( 157 icd->instance, 158 msgFlags, 159 pfnMsgCallback, 160 pUserData, 161 &icd_info[storage_idx]); 162 163 if (res != VK_SUCCESS) { 164 break; 165 } 166 storage_idx++; 167 } 168 169 /* roll back on errors */ 170 if (icd) { 171 storage_idx = 0; 172 for (icd = inst->icds; icd; icd = icd->next) { 173 if (icd_info[storage_idx]) { 174 icd->DbgDestroyMsgCallback( 175 icd->instance, 176 icd_info[storage_idx]); 177 } 178 storage_idx++; 179 } 180 181 return res; 182 } 183 184 *pMsgCallback = (VkDbgMsgCallback) icd_info; 185 186 return VK_SUCCESS; 187} 188 189/* 190 * This is the instance chain terminator function 191 * for DbgDestroyMsgCallback 192 */ 193VkResult loader_DbgDestroyMsgCallback( 194 VkInstance instance, 195 VkDbgMsgCallback msgCallback) 196{ 197 uint32_t storage_idx; 198 VkDbgMsgCallback *icd_info; 199 const struct loader_icd *icd; 200 VkResult res = VK_SUCCESS; 201 struct loader_instance *inst; 202 203 if (instance == VK_NULL_HANDLE) 204 return VK_ERROR_INVALID_HANDLE; 205 206 assert(loader.icds_scanned); 207 208 for (inst = loader.instances; inst; inst = inst->next) { 209 if ((VkInstance) inst == instance) 210 break; 211 } 212 213 if (inst == VK_NULL_HANDLE) 214 return VK_ERROR_INVALID_HANDLE; 215 216 icd_info = (VkDbgMsgCallback *) msgCallback; 217 storage_idx = 0; 218 for (icd = inst->icds; icd; icd = icd->next) { 219 if (icd_info[storage_idx]) { 220 icd->DbgDestroyMsgCallback( 221 icd->instance, 222 icd_info[storage_idx]); 223 } 224 storage_idx++; 225 } 226 return res; 227} 228 229// DebugReport utility callback functions 230static void VKAPI StringCallback( 231 VkFlags msgFlags, 232 VkObjectType objType, 233 VkObject srcObject, 234 size_t location, 235 int32_t msgCode, 236 const char* pLayerPrefix, 237 const char* pMsg, 238 void* pUserData) 239{ 240 241} 242 243static void VKAPI StdioCallback( 244 VkFlags msgFlags, 245 VkObjectType objType, 246 VkObject srcObject, 247 size_t location, 248 int32_t msgCode, 249 const char* pLayerPrefix, 250 const char* pMsg, 251 void* pUserData) 252{ 253 254} 255 256static void VKAPI BreakCallback( 257 VkFlags msgFlags, 258 VkObjectType objType, 259 VkObject srcObject, 260 size_t location, 261 int32_t msgCode, 262 const char* pLayerPrefix, 263 const char* pMsg, 264 void* pUserData) 265{ 266 267} 268 269void *debug_report_instance_gpa( 270 struct loader_instance *ptr_instance, 271 const char* name) 272{ 273 if (ptr_instance == VK_NULL_HANDLE || !ptr_instance->debug_report_enabled) 274 return NULL; 275 276 if (!strcmp("vkDbgCreateMsgCallback", name)) 277 return (void *) debug_report_DbgCreateMsgCallback; 278 else if (!strcmp("vkDbgDestroyMsgCallback", name)) 279 return (void *) debug_report_DbgDestroyMsgCallback; 280 else if (!strcmp("vkDbgStringCallback", name)) 281 return (void *) StringCallback; 282 else if (!strcmp("vkDbgStdioCallback", name)) 283 return (void *) StdioCallback; 284 else if (!strcmp("vkDbgBreakCallback", name)) 285 return (void *) BreakCallback; 286 287 return NULL; 288} 289