blob: 9a0396b049355e226222b9f9e12cc09a6add2e39 [file] [log] [blame]
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001/*
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
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -060029#include <stdio.h>
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060030#include <string.h>
31#include <stdlib.h>
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -060032#include <inttypes.h>
Tony Barbour69698512015-06-18 16:29:32 -060033#ifndef WIN32
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -060034#include <alloca.h>
Tony Barbour69698512015-06-18 16:29:32 -060035#endif
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060036#include "debug_report.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060037#include "vk_layer.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060038
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -060039typedef void (VKAPI *PFN_stringCallback)(char *message);
40
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060041static const struct loader_extension_property debug_report_extension_info = {
42 .info = {
43 .sType = VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
44 .name = DEBUG_REPORT_EXTENSION_NAME,
45 .version = VK_DEBUG_REPORT_EXTENSION_VERSION,
46 .description = "loader: debug report extension",
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060047 },
48 .origin = VK_EXTENSION_ORIGIN_LOADER,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060049};
50
51void debug_report_add_instance_extensions(
52 struct loader_extension_list *ext_list)
53{
54 loader_add_to_ext_list(ext_list, 1, &debug_report_extension_info);
55}
56
57void debug_report_create_instance(
58 struct loader_instance *ptr_instance)
59{
60 ptr_instance->debug_report_enabled = has_vk_extension_property(
61 &debug_report_extension_info.info,
62 &ptr_instance->enabled_instance_extensions);
63}
64
65static VkResult debug_report_DbgCreateMsgCallback(
66 VkInstance instance,
67 VkFlags msgFlags,
68 const PFN_vkDbgMsgCallback pfnMsgCallback,
69 void* pUserData,
70 VkDbgMsgCallback* pMsgCallback)
71{
72 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *) malloc(sizeof(VkLayerDbgFunctionNode));
73 if (!pNewDbgFuncNode)
74 return VK_ERROR_OUT_OF_HOST_MEMORY;
75
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -060076 struct loader_instance *inst = loader_instance(instance);
Jon Ashburnb40f2562015-05-29 13:15:39 -060077 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060078 VkResult result = inst->disp->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
79 if (result == VK_SUCCESS) {
80 pNewDbgFuncNode->msgCallback = *pMsgCallback;
81 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
82 pNewDbgFuncNode->msgFlags = msgFlags;
83 pNewDbgFuncNode->pUserData = pUserData;
84 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
85 inst->DbgFunctionHead = pNewDbgFuncNode;
86 } else {
87 free(pNewDbgFuncNode);
88 }
Jon Ashburnb40f2562015-05-29 13:15:39 -060089 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060090 return result;
91}
92
93static VkResult debug_report_DbgDestroyMsgCallback(
94 VkInstance instance,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060095 VkDbgMsgCallback msg_callback)
96{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -060097 struct loader_instance *inst = loader_instance(instance);
Jon Ashburnb40f2562015-05-29 13:15:39 -060098 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060099 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
100 VkLayerDbgFunctionNode *pPrev = pTrav;
101
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -0600102 VkResult result = inst->disp->DbgDestroyMsgCallback(instance, msg_callback);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600103
104 while (pTrav) {
105 if (pTrav->msgCallback == msg_callback) {
106 pPrev->pNext = pTrav->pNext;
107 if (inst->DbgFunctionHead == pTrav)
108 inst->DbgFunctionHead = pTrav->pNext;
109 free(pTrav);
110 break;
111 }
112 pPrev = pTrav;
113 pTrav = pTrav->pNext;
114 }
115
Jon Ashburnb40f2562015-05-29 13:15:39 -0600116 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600117 return result;
118}
119
120
121/*
122 * This is the instance chain terminator function
123 * for DbgCreateMsgCallback
124 */
125VkResult loader_DbgCreateMsgCallback(
126 VkInstance instance,
127 VkFlags msgFlags,
128 const PFN_vkDbgMsgCallback pfnMsgCallback,
129 const void* pUserData,
130 VkDbgMsgCallback* pMsgCallback)
131{
132 VkDbgMsgCallback *icd_info;
133 const struct loader_icd *icd;
134 struct loader_instance *inst;
135 VkResult res;
136 uint32_t storage_idx;
137
138 if (instance == VK_NULL_HANDLE)
139 return VK_ERROR_INVALID_HANDLE;
140
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600141 for (inst = loader.instances; inst; inst = inst->next) {
142 if ((VkInstance) inst == instance)
143 break;
144 }
145
146 if (inst == VK_NULL_HANDLE)
147 return VK_ERROR_INVALID_HANDLE;
148
149 icd_info = calloc(sizeof(VkDbgMsgCallback), inst->total_icd_count);
150 if (!icd_info) {
151 return VK_ERROR_OUT_OF_HOST_MEMORY;
152 }
153
154 storage_idx = 0;
155 for (icd = inst->icds; icd; icd = icd->next) {
156 if (!icd->DbgCreateMsgCallback) {
157 continue;
158 }
159
160 res = icd->DbgCreateMsgCallback(
161 icd->instance,
162 msgFlags,
163 pfnMsgCallback,
164 pUserData,
165 &icd_info[storage_idx]);
166
167 if (res != VK_SUCCESS) {
168 break;
169 }
170 storage_idx++;
171 }
172
173 /* roll back on errors */
174 if (icd) {
175 storage_idx = 0;
176 for (icd = inst->icds; icd; icd = icd->next) {
177 if (icd_info[storage_idx]) {
178 icd->DbgDestroyMsgCallback(
179 icd->instance,
180 icd_info[storage_idx]);
181 }
182 storage_idx++;
183 }
184
185 return res;
186 }
187
188 *pMsgCallback = (VkDbgMsgCallback) icd_info;
189
190 return VK_SUCCESS;
191}
192
193/*
194 * This is the instance chain terminator function
195 * for DbgDestroyMsgCallback
196 */
197VkResult loader_DbgDestroyMsgCallback(
198 VkInstance instance,
199 VkDbgMsgCallback msgCallback)
200{
201 uint32_t storage_idx;
202 VkDbgMsgCallback *icd_info;
203 const struct loader_icd *icd;
204 VkResult res = VK_SUCCESS;
205 struct loader_instance *inst;
206
207 if (instance == VK_NULL_HANDLE)
208 return VK_ERROR_INVALID_HANDLE;
209
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600210 for (inst = loader.instances; inst; inst = inst->next) {
211 if ((VkInstance) inst == instance)
212 break;
213 }
214
215 if (inst == VK_NULL_HANDLE)
216 return VK_ERROR_INVALID_HANDLE;
217
218 icd_info = (VkDbgMsgCallback *) msgCallback;
219 storage_idx = 0;
220 for (icd = inst->icds; icd; icd = icd->next) {
221 if (icd_info[storage_idx]) {
222 icd->DbgDestroyMsgCallback(
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -0600223 icd->instance,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600224 icd_info[storage_idx]);
225 }
226 storage_idx++;
227 }
228 return res;
229}
230
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600231static void print_msg_flags(VkFlags msgFlags, char *msg_flags)
232{
233 bool separator = false;
234
235 msg_flags[0] = 0;
236 if (msgFlags & VK_DBG_REPORT_DEBUG_BIT) {
237 strcat(msg_flags, "DEBUG");
238 separator = true;
239 }
240 if (msgFlags & VK_DBG_REPORT_INFO_BIT) {
241 if (separator) strcat(msg_flags, ",");
242 strcat(msg_flags, "INFO");
243 separator = true;
244 }
245 if (msgFlags & VK_DBG_REPORT_WARN_BIT) {
246 if (separator) strcat(msg_flags, ",");
247 strcat(msg_flags, "WARN");
248 separator = true;
249 }
250 if (msgFlags & VK_DBG_REPORT_PERF_WARN_BIT) {
251 if (separator) strcat(msg_flags, ",");
252 strcat(msg_flags, "PERF");
253 separator = true;
254 }
255 if (msgFlags & VK_DBG_REPORT_ERROR_BIT) {
256 if (separator) strcat(msg_flags, ",");
257 strcat(msg_flags, "ERROR");
258 }
259}
260
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600261// DebugReport utility callback functions
262static void VKAPI StringCallback(
263 VkFlags msgFlags,
264 VkObjectType objType,
265 VkObject srcObject,
266 size_t location,
267 int32_t msgCode,
268 const char* pLayerPrefix,
269 const char* pMsg,
270 void* pUserData)
271{
Jon Ashburncab27b32015-06-30 14:44:13 -0700272 size_t buf_size;
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600273 char *buf;
274 char msg_flags[30];
275 PFN_stringCallback callback = (PFN_stringCallback) pUserData;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600276
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600277 print_msg_flags(msgFlags, msg_flags);
278
279 buf_size = strlen(msg_flags) + /* ReportFlags: i.e. (DEBUG,INFO,WARN,PERF,ERROR) */
280 20 + /* objType */
281 20 + /* srcObject */
282 20 + /* location */
283 20 + /* msgCode */
284 strlen(pLayerPrefix) +
285 strlen(pMsg) +
286 50 /* other / whitespace */;
Tony Barbour69698512015-06-18 16:29:32 -0600287#ifdef WIN32
288 buf = _alloca(buf_size);
289#else
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600290 buf = alloca(buf_size);
Tony Barbour69698512015-06-18 16:29:32 -0600291#endif
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600292 snprintf(buf, buf_size, "%s (%s): object: 0x%" PRIxLEAST64 " type: %d location: %zu msgCode: %d: %s",
293 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
294 callback(buf);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600295}
296
297static void VKAPI StdioCallback(
298 VkFlags msgFlags,
299 VkObjectType objType,
300 VkObject srcObject,
301 size_t location,
302 int32_t msgCode,
303 const char* pLayerPrefix,
304 const char* pMsg,
305 void* pUserData)
306{
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600307 char msg_flags[30];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600308
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -0600309 print_msg_flags(msgFlags, msg_flags);
310
311 fprintf((FILE *) pUserData, "%s(%s): object: 0x%" PRIxLEAST64 " type: %d location: %zu msgCode: %d: %s",
312 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600313}
314
315static void VKAPI BreakCallback(
316 VkFlags msgFlags,
317 VkObjectType objType,
318 VkObject srcObject,
319 size_t location,
320 int32_t msgCode,
321 const char* pLayerPrefix,
322 const char* pMsg,
323 void* pUserData)
324{
325
326}
327
328void *debug_report_instance_gpa(
329 struct loader_instance *ptr_instance,
330 const char* name)
331{
332 if (ptr_instance == VK_NULL_HANDLE || !ptr_instance->debug_report_enabled)
333 return NULL;
334
335 if (!strcmp("vkDbgCreateMsgCallback", name))
336 return (void *) debug_report_DbgCreateMsgCallback;
337 else if (!strcmp("vkDbgDestroyMsgCallback", name))
338 return (void *) debug_report_DbgDestroyMsgCallback;
Jon Ashburnb843f0b2015-05-26 13:56:43 -0600339 else if (!strcmp("vkDbgStringCallback", name))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600340 return (void *) StringCallback;
Jon Ashburnb843f0b2015-05-26 13:56:43 -0600341 else if (!strcmp("vkDbgStdioCallback", name))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600342 return (void *) StdioCallback;
Jon Ashburnb843f0b2015-05-26 13:56:43 -0600343 else if (!strcmp("vkDbgBreakCallback", name))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600344 return (void *) BreakCallback;
345
346 return NULL;
347}