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
31 struct 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
VK_DEFINE_NONDISP_HANDLE_CASTS(vk_debug_report_callback,base,VkDebugReportCallbackEXT,VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT)41 VK_DEFINE_NONDISP_HANDLE_CASTS(vk_debug_report_callback, base,
42 VkDebugReportCallbackEXT,
43 VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT)
44
45 VKAPI_ATTR VkResult VKAPI_CALL
46 vk_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
77 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyDebugReportCallbackEXT(VkInstance _instance,VkDebugReportCallbackEXT _callback,const VkAllocationCallbacks * pAllocator)78 vk_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
96 static void
debug_report(struct vk_instance * instance,VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT object_type,uint64_t handle,size_t location,int32_t messageCode,const char * pLayerPrefix,const char * pMessage)97 debug_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
129 VKAPI_ATTR void VKAPI_CALL
vk_common_DebugReportMessageEXT(VkInstance _instance,VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objectType,uint64_t object,size_t location,int32_t messageCode,const char * pLayerPrefix,const char * pMessage)130 vk_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
144 void
vk_debug_report(struct vk_instance * instance,VkDebugReportFlagsEXT flags,const struct vk_object_base * object,size_t location,int32_t messageCode,const char * pLayerPrefix,const char * pMessage)145 vk_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 VkObjectType object_type =
154 object ? object->type : VK_OBJECT_TYPE_UNKNOWN;
155 debug_report(instance, flags, (VkDebugReportObjectTypeEXT)object_type,
156 (uint64_t)(uintptr_t)object, location, messageCode,
157 pLayerPrefix, pMessage);
158 }
159