blob: 98fd3b46d90d7764653564e4b21e52618a456957 [file] [log] [blame]
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001/*
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06004 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the 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
21 * DEALINGS IN THE SOFTWARE.
22 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060023 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
24 *
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060025 */
26
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -060027#define _GNU_SOURCE
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060028#include <stdio.h>
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060029#include <string.h>
30#include <stdlib.h>
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060031#include <inttypes.h>
Tony Barbour1d825c72015-06-18 16:29:32 -060032#ifndef WIN32
Courtney Goeltzenleuchter03663d02015-07-22 11:01:53 -060033#include <signal.h>
34#else
Tony Barbour1d825c72015-06-18 16:29:32 -060035#endif
Jon Ashburn480a50a2015-08-28 14:58:46 -070036#include "vk_loader_platform.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060037#include "debug_report.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070038#include "vulkan/vk_layer.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060039
Chia-I Wu9ab61502015-11-06 06:42:02 +080040typedef void (VKAPI_PTR *PFN_stringCallback)(char *message);
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060041
Jon Ashburn5c042ea2015-08-04 11:14:18 -060042static const VkExtensionProperties debug_report_extension_info = {
Chia-I Wu3432a0c2015-10-27 18:04:07 +080043 .extensionName = VK_DEBUG_REPORT_EXTENSION_NAME,
Ian Elliott464e0b52015-09-04 14:14:35 -060044 .specVersion = VK_DEBUG_REPORT_EXTENSION_REVISION,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060045};
46
47void debug_report_add_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -060048 const struct loader_instance *inst,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060049 struct loader_extension_list *ext_list)
50{
Jon Ashburne39a4f82015-08-28 13:38:21 -060051 loader_add_to_ext_list(inst, ext_list, 1, &debug_report_extension_info);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060052}
53
54void debug_report_create_instance(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060055 struct loader_instance *ptr_instance,
56 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060057{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060058 ptr_instance->debug_report_enabled = false;
59
Chia-I Wud50a7d72015-10-26 20:48:51 +080060 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter05159a92015-07-30 11:32:46 -060061 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060062 ptr_instance->debug_report_enabled = true;
63 return;
64 }
65 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060066}
67
Jon Ashburn4f232582015-11-06 15:31:44 -070068static VKAPI_ATTR VkResult VKAPI_CALL debug_report_DbgCreateMsgCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060069 VkInstance instance,
70 VkFlags msgFlags,
71 const PFN_vkDbgMsgCallback pfnMsgCallback,
72 void* pUserData,
73 VkDbgMsgCallback* pMsgCallback)
74{
Chia-I Wu3432a0c2015-10-27 18:04:07 +080075 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *) loader_heap_alloc((struct loader_instance *)instance, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060076 if (!pNewDbgFuncNode)
77 return VK_ERROR_OUT_OF_HOST_MEMORY;
78
Jon Ashburne0e64572015-09-30 12:56:42 -060079 struct loader_instance *inst = loader_get_instance(instance);
Jon Ashburn6301a0f2015-05-29 13:15:39 -060080 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060081 VkResult result = inst->disp->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
82 if (result == VK_SUCCESS) {
83 pNewDbgFuncNode->msgCallback = *pMsgCallback;
84 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
85 pNewDbgFuncNode->msgFlags = msgFlags;
86 pNewDbgFuncNode->pUserData = pUserData;
87 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
88 inst->DbgFunctionHead = pNewDbgFuncNode;
89 } else {
Jon Ashburne39a4f82015-08-28 13:38:21 -060090 loader_heap_free((struct loader_instance *) instance, pNewDbgFuncNode);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060091 }
Jon Ashburn6301a0f2015-05-29 13:15:39 -060092 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060093 return result;
94}
95
Jon Ashburn4f232582015-11-06 15:31:44 -070096static VKAPI_ATTR VkResult VKAPI_CALL debug_report_DbgDestroyMsgCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060097 VkInstance instance,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060098 VkDbgMsgCallback msg_callback)
99{
Jon Ashburne0e64572015-09-30 12:56:42 -0600100 struct loader_instance *inst = loader_get_instance(instance);
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600101 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600102 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
103 VkLayerDbgFunctionNode *pPrev = pTrav;
104
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -0600105 VkResult result = inst->disp->DbgDestroyMsgCallback(instance, msg_callback);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600106
107 while (pTrav) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800108 if (pTrav->msgCallback == msg_callback) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600109 pPrev->pNext = pTrav->pNext;
110 if (inst->DbgFunctionHead == pTrav)
111 inst->DbgFunctionHead = pTrav->pNext;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600112 loader_heap_free((struct loader_instance *) instance, pTrav);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600113 break;
114 }
115 pPrev = pTrav;
116 pTrav = pTrav->pNext;
117 }
118
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600119 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600120 return result;
121}
122
123
124/*
125 * This is the instance chain terminator function
126 * for DbgCreateMsgCallback
127 */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600128
Chia-I Wu9ab61502015-11-06 06:42:02 +0800129VKAPI_ATTR VkResult VKAPI_CALL loader_DbgCreateMsgCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600130 VkInstance instance,
131 VkFlags msgFlags,
132 const PFN_vkDbgMsgCallback pfnMsgCallback,
Jon Ashburne67741a2015-08-06 13:56:43 -0600133 void* pUserData,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600134 VkDbgMsgCallback* pMsgCallback)
135{
136 VkDbgMsgCallback *icd_info;
137 const struct loader_icd *icd;
138 struct loader_instance *inst;
139 VkResult res;
140 uint32_t storage_idx;
141
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600142 for (inst = loader.instances; inst; inst = inst->next) {
143 if ((VkInstance) inst == instance)
144 break;
145 }
146
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600147 icd_info = calloc(sizeof(VkDbgMsgCallback), inst->total_icd_count);
148 if (!icd_info) {
149 return VK_ERROR_OUT_OF_HOST_MEMORY;
150 }
151
152 storage_idx = 0;
153 for (icd = inst->icds; icd; icd = icd->next) {
154 if (!icd->DbgCreateMsgCallback) {
155 continue;
156 }
157
158 res = icd->DbgCreateMsgCallback(
159 icd->instance,
160 msgFlags,
161 pfnMsgCallback,
162 pUserData,
163 &icd_info[storage_idx]);
164
165 if (res != VK_SUCCESS) {
166 break;
167 }
168 storage_idx++;
169 }
170
171 /* roll back on errors */
172 if (icd) {
173 storage_idx = 0;
174 for (icd = inst->icds; icd; icd = icd->next) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800175 if (icd_info[storage_idx]) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600176 icd->DbgDestroyMsgCallback(
177 icd->instance,
178 icd_info[storage_idx]);
179 }
180 storage_idx++;
181 }
182
183 return res;
184 }
185
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600186 *(VkDbgMsgCallback **)pMsgCallback = icd_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600187
188 return VK_SUCCESS;
189}
190
191/*
192 * This is the instance chain terminator function
193 * for DbgDestroyMsgCallback
194 */
Chia-I Wu9ab61502015-11-06 06:42:02 +0800195VKAPI_ATTR VkResult VKAPI_CALL loader_DbgDestroyMsgCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600196 VkInstance instance,
197 VkDbgMsgCallback msgCallback)
198{
199 uint32_t storage_idx;
200 VkDbgMsgCallback *icd_info;
201 const struct loader_icd *icd;
202 VkResult res = VK_SUCCESS;
203 struct loader_instance *inst;
204
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600205 for (inst = loader.instances; inst; inst = inst->next) {
206 if ((VkInstance) inst == instance)
207 break;
208 }
209
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600210 icd_info = *(VkDbgMsgCallback **) &msgCallback;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600211 storage_idx = 0;
212 for (icd = inst->icds; icd; icd = icd->next) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800213 if (icd_info[storage_idx]) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600214 icd->DbgDestroyMsgCallback(
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -0600215 icd->instance,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600216 icd_info[storage_idx]);
217 }
218 storage_idx++;
219 }
220 return res;
221}
222
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600223static void print_msg_flags(VkFlags msgFlags, char *msg_flags)
224{
225 bool separator = false;
226
227 msg_flags[0] = 0;
228 if (msgFlags & VK_DBG_REPORT_DEBUG_BIT) {
229 strcat(msg_flags, "DEBUG");
230 separator = true;
231 }
232 if (msgFlags & VK_DBG_REPORT_INFO_BIT) {
233 if (separator) strcat(msg_flags, ",");
234 strcat(msg_flags, "INFO");
235 separator = true;
236 }
237 if (msgFlags & VK_DBG_REPORT_WARN_BIT) {
238 if (separator) strcat(msg_flags, ",");
239 strcat(msg_flags, "WARN");
240 separator = true;
241 }
242 if (msgFlags & VK_DBG_REPORT_PERF_WARN_BIT) {
243 if (separator) strcat(msg_flags, ",");
244 strcat(msg_flags, "PERF");
245 separator = true;
246 }
247 if (msgFlags & VK_DBG_REPORT_ERROR_BIT) {
248 if (separator) strcat(msg_flags, ",");
249 strcat(msg_flags, "ERROR");
250 }
251}
252
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600253// DebugReport utility callback functions
Chia-I Wu9ab61502015-11-06 06:42:02 +0800254static VKAPI_ATTR void VKAPI_CALL StringCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600255 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600256 VkDbgObjectType objType,
257 uint64_t srcObject,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600258 size_t location,
259 int32_t msgCode,
260 const char* pLayerPrefix,
261 const char* pMsg,
262 void* pUserData)
263{
Jon Ashburn7242c672015-06-30 14:44:13 -0700264 size_t buf_size;
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600265 char *buf;
266 char msg_flags[30];
267 PFN_stringCallback callback = (PFN_stringCallback) pUserData;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600268
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600269 print_msg_flags(msgFlags, msg_flags);
270
271 buf_size = strlen(msg_flags) + /* ReportFlags: i.e. (DEBUG,INFO,WARN,PERF,ERROR) */
272 20 + /* objType */
273 20 + /* srcObject */
274 20 + /* location */
275 20 + /* msgCode */
276 strlen(pLayerPrefix) +
277 strlen(pMsg) +
278 50 /* other / whitespace */;
Jon Ashburn48091a32015-08-27 13:06:58 -0600279 buf = loader_stack_alloc(buf_size);
280
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600281 snprintf(buf, buf_size, "%s (%s): object: 0x%" PRIxLEAST64 " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msgCode : %d : %s",
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600282 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
283 callback(buf);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600284}
285
Chia-I Wu9ab61502015-11-06 06:42:02 +0800286static VKAPI_ATTR void VKAPI_CALL StdioCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600287 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600288 VkDbgObjectType objType,
289 uint64_t srcObject,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600290 size_t location,
291 int32_t msgCode,
292 const char* pLayerPrefix,
293 const char* pMsg,
294 void* pUserData)
295{
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600296 char msg_flags[30];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600297
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600298 print_msg_flags(msgFlags, msg_flags);
299
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600300 fprintf((FILE *)pUserData, "%s(%s): object: 0x%" PRIxLEAST64 " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msgCode : %d : %s",
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -0600301 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600302}
303
Chia-I Wu9ab61502015-11-06 06:42:02 +0800304static VKAPI_ATTR void VKAPI_CALL BreakCallback(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600305 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600306 VkDbgObjectType objType,
307 uint64_t srcObject,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600308 size_t location,
309 int32_t msgCode,
310 const char* pLayerPrefix,
311 const char* pMsg,
312 void* pUserData)
313{
Courtney Goeltzenleuchter03663d02015-07-22 11:01:53 -0600314#ifndef WIN32
315 raise(SIGTRAP);
316#else
317 DebugBreak();
318#endif
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600319}
320
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600321bool debug_report_instance_gpa(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600322 struct loader_instance *ptr_instance,
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600323 const char* name,
324 void **addr)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600325{
Jon Ashburn8a39efc2015-11-06 11:02:40 -0700326 // debug_report is currently advertised to be supported by the loader,
327 // so always return the entry points if name matches and it's enabled
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600328 *addr = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600329
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600330 if (!strcmp("vkDbgCreateMsgCallback", name)) {
331 *addr = ptr_instance->debug_report_enabled ? (void *) debug_report_DbgCreateMsgCallback : NULL;
332 return true;
333 }
334 if (!strcmp("vkDbgDestroyMsgCallback", name)) {
335 *addr = ptr_instance->debug_report_enabled ? (void *) debug_report_DbgDestroyMsgCallback : NULL;
336 return true;
337 }
338 if (!strcmp("vkDbgStringCallback", name)) {
339 *addr = ptr_instance->debug_report_enabled ? (void *) StringCallback : NULL;
340 return true;
341 }
342 if (!strcmp("vkDbgStdioCallback", name)) {
343 *addr = ptr_instance->debug_report_enabled ? (void *) StdioCallback : NULL;
344 return true;
345 }
346 if (!strcmp("vkDbgBreakCallback", name)) {
347 *addr = ptr_instance->debug_report_enabled ? (void *) BreakCallback : NULL;
348 return true;
349 }
350 return false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600351}