1/* 2 * Copyright © 2017 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "vk_debug_report.h" 25 26#include "vk_alloc.h" 27#include "vk_common_entrypoints.h" 28#include "vk_instance.h" 29#include "vk_util.h" 30 31struct vk_debug_report_callback { 32 struct vk_object_base base; 33 34 /* Link in the 'callbacks' list in anv_instance struct. */ 35 struct list_head link; 36 VkDebugReportFlagsEXT flags; 37 PFN_vkDebugReportCallbackEXT callback; 38 void * data; 39}; 40 41VK_DEFINE_NONDISP_HANDLE_CASTS(vk_debug_report_callback, base, 42 VkDebugReportCallbackEXT, 43 VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT) 44 45VKAPI_ATTR VkResult VKAPI_CALL 46vk_common_CreateDebugReportCallbackEXT(VkInstance _instance, 47 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 48 const VkAllocationCallbacks *pAllocator, 49 VkDebugReportCallbackEXT *pCallback) 50{ 51 VK_FROM_HANDLE(vk_instance, instance, _instance); 52 53 struct vk_debug_report_callback *cb = 54 vk_alloc2(&instance->alloc, pAllocator, 55 sizeof(struct vk_debug_report_callback), 8, 56 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 57 58 if (!cb) 59 return VK_ERROR_OUT_OF_HOST_MEMORY; 60 61 vk_object_base_init(NULL, &cb->base, 62 VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT); 63 64 cb->flags = pCreateInfo->flags; 65 cb->callback = pCreateInfo->pfnCallback; 66 cb->data = pCreateInfo->pUserData; 67 68 mtx_lock(&instance->debug_report.callbacks_mutex); 69 list_addtail(&cb->link, &instance->debug_report.callbacks); 70 mtx_unlock(&instance->debug_report.callbacks_mutex); 71 72 *pCallback = vk_debug_report_callback_to_handle(cb); 73 74 return VK_SUCCESS; 75} 76 77VKAPI_ATTR void VKAPI_CALL 78vk_common_DestroyDebugReportCallbackEXT(VkInstance _instance, 79 VkDebugReportCallbackEXT _callback, 80 const VkAllocationCallbacks *pAllocator) 81{ 82 VK_FROM_HANDLE(vk_instance, instance, _instance); 83 VK_FROM_HANDLE(vk_debug_report_callback, callback, _callback); 84 85 if (callback == NULL) 86 return; 87 88 /* Remove from list and destroy given callback. */ 89 mtx_lock(&instance->debug_report.callbacks_mutex); 90 list_del(&callback->link); 91 vk_object_base_finish(&callback->base); 92 vk_free2(&instance->alloc, pAllocator, callback); 93 mtx_unlock(&instance->debug_report.callbacks_mutex); 94} 95 96static void 97debug_report(struct vk_instance *instance, 98 VkDebugReportFlagsEXT flags, 99 VkDebugReportObjectTypeEXT object_type, 100 uint64_t handle, 101 size_t location, 102 int32_t messageCode, 103 const char* pLayerPrefix, 104 const char *pMessage) 105{ 106 /* Allow NULL for convinience, return if no callbacks registered. */ 107 if (!instance || list_is_empty(&instance->debug_report.callbacks)) 108 return; 109 110 mtx_lock(&instance->debug_report.callbacks_mutex); 111 112 /* Section 33.2 of the Vulkan 1.0.59 spec says: 113 * 114 * "callback is an externally synchronized object and must not be 115 * used on more than one thread at a time. This means that 116 * vkDestroyDebugReportCallbackEXT must not be called when a callback 117 * is active." 118 */ 119 list_for_each_entry(struct vk_debug_report_callback, cb, 120 &instance->debug_report.callbacks, link) { 121 if (cb->flags & flags) 122 cb->callback(flags, object_type, handle, location, messageCode, 123 pLayerPrefix, pMessage, cb->data); 124 } 125 126 mtx_unlock(&instance->debug_report.callbacks_mutex); 127} 128 129VKAPI_ATTR void VKAPI_CALL 130vk_common_DebugReportMessageEXT(VkInstance _instance, 131 VkDebugReportFlagsEXT flags, 132 VkDebugReportObjectTypeEXT objectType, 133 uint64_t object, 134 size_t location, 135 int32_t messageCode, 136 const char* pLayerPrefix, 137 const char* pMessage) 138{ 139 VK_FROM_HANDLE(vk_instance, instance, _instance); 140 debug_report(instance, flags, objectType, 141 object, location, messageCode, pLayerPrefix, pMessage); 142} 143 144void 145vk_debug_report(struct vk_instance *instance, 146 VkDebugReportFlagsEXT flags, 147 const struct vk_object_base *object, 148 size_t location, 149 int32_t messageCode, 150 const char* pLayerPrefix, 151 const char *pMessage) 152{ 153 VkDebugReportObjectTypeEXT object_type = 154 object ? object->type : VK_OBJECT_TYPE_UNKNOWN; 155 debug_report(instance, flags, object_type, (uint64_t)(uintptr_t)object, 156 location, messageCode, pLayerPrefix, pMessage); 157} 158