blob: 6ac4e60497c3950e311ab2d34628629ada3d7bba [file] [log] [blame]
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06001/*
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -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 *
23 * Authors:
24 * Courtney Goeltzenleuchter <courtney@lunarg.com>
25 */
26
27#ifndef LAYER_LOGGING_H
28#define LAYER_LOGGING_H
29
30#include <stdio.h>
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -060031#include <stdarg.h>
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060032#include <stdbool.h>
33#include <unordered_map>
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -060034#include <inttypes.h>
Tobin Ehlis890adf12015-11-02 15:45:19 -070035#include "vk_loader_platform.h"
Tobin Ehlis0c6f9ee2015-07-03 09:42:57 -060036#include "vk_layer.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060037#include "vk_layer_data.h"
38#include "vk_layer_table.h"
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060039
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060040typedef struct _debug_report_data {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060041 VkLayerDbgFunctionNode *g_pDbgFunctionHead;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -060042 VkFlags active_flags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060043 bool g_DEBUG_REPORT;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060044} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060045
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060046template debug_report_data *get_my_data_ptr<debug_report_data>(
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060047 void *data_key,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060048 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060049
50// Utility function to handle reporting
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060051static inline VkBool32 debug_report_log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060052 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060053 VkFlags msgFlags,
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -060054 VkDbgObjectType objectType,
55 uint64_t srcObject,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060056 size_t location,
57 int32_t msgCode,
58 const char* pLayerPrefix,
59 const char* pMsg)
60{
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060061 VkBool32 bail = false;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060062 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
63 while (pTrav) {
64 if (pTrav->msgFlags & msgFlags) {
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060065 if (pTrav->pfnMsgCallback(msgFlags,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060066 objectType, srcObject,
67 location,
68 msgCode,
69 pLayerPrefix,
70 pMsg,
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060071 (void *) pTrav->pUserData)) {
72 bail = true;
73 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060074 }
75 pTrav = pTrav->pNext;
76 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060077
78 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060079}
80
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060081static inline debug_report_data *debug_report_create_instance(
82 VkLayerInstanceDispatchTable *table,
83 VkInstance inst,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060084 uint32_t extension_count,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060085 const char*const* ppEnabledExtensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060086{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060087 debug_report_data *debug_data;
88 PFN_vkGetInstanceProcAddr gpa = table->GetInstanceProcAddr;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060089
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060090 table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback");
91 table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback");
92
93 debug_data = (debug_report_data *) malloc(sizeof(debug_report_data));
94 if (!debug_data) return NULL;
95
96 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060097 for (uint32_t i = 0; i < extension_count; i++) {
98 /* TODO: Check other property fields */
Courtney Goeltzenleuchter05159a92015-07-30 11:32:46 -060099 if (strcmp(ppEnabledExtensions[i], VK_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600100 debug_data->g_DEBUG_REPORT = true;
101 }
102 }
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600103 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600104}
105
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600106static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600107{
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600108 VkLayerDbgFunctionNode *pTrav;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600109 VkLayerDbgFunctionNode *pTravNext;
110
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600111 if (!debug_data) {
112 return;
113 }
114
115 pTrav = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600116 /* Clear out any leftover callbacks */
117 while (pTrav) {
118 pTravNext = pTrav->pNext;
119
120 debug_report_log_msg(
121 debug_data, VK_DBG_REPORT_WARN_BIT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800122 VK_OBJECT_TYPE_MSG_CALLBACK, (uint64_t) pTrav->msgCallback,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600123 0, DEBUG_REPORT_CALLBACK_REF,
124 "DebugReport",
125 "Debug Report callbacks not removed before DestroyInstance");
126
127 free(pTrav);
128 pTrav = pTravNext;
129 }
130 debug_data->g_pDbgFunctionHead = NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600131
132 free(debug_data);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600133}
134
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600135static inline debug_report_data *layer_debug_report_create_device(
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600136 debug_report_data *instance_debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600137 VkDevice device)
138{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600139 /* DEBUG_REPORT shares data between Instance and Device,
140 * so just return instance's data pointer */
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600141 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600142}
143
144static inline void layer_debug_report_destroy_device(VkDevice device)
145{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600146 /* Nothing to do since we're using instance data record */
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600147}
148
149static inline VkResult layer_create_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600150 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600151 VkFlags msgFlags,
152 const PFN_vkDbgMsgCallback pfnMsgCallback,
153 void *pUserData,
154 VkDbgMsgCallback *pMsgCallback)
155{
156 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode));
157 if (!pNewDbgFuncNode)
158 return VK_ERROR_OUT_OF_HOST_MEMORY;
159
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600160 // Handle of 0 is logging_callback so use allocated Node address as unique handle
161 if (!(*pMsgCallback))
Chia-I Wue2fc5522015-10-26 20:04:44 +0800162 *pMsgCallback = (VkDbgMsgCallback) pNewDbgFuncNode;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600163 pNewDbgFuncNode->msgCallback = *pMsgCallback;
164 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
165 pNewDbgFuncNode->msgFlags = msgFlags;
166 pNewDbgFuncNode->pUserData = pUserData;
167 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600168
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600169 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600170 debug_data->active_flags |= msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600171
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600172 debug_report_log_msg(
173 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800174 VK_OBJECT_TYPE_MSG_CALLBACK, (uint64_t) *pMsgCallback,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600175 0, DEBUG_REPORT_CALLBACK_REF,
176 "DebugReport",
177 "Added callback");
178 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600179}
180
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600181static inline void layer_destroy_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600182 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600183 VkDbgMsgCallback msg_callback)
184{
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600185 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
186 VkLayerDbgFunctionNode *pPrev = pTrav;
Mike Stroyan14a57e72015-07-31 16:20:39 -0600187 bool matched;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600188
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600189 debug_data->active_flags = 0;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600190 while (pTrav) {
191 if (pTrav->msgCallback == msg_callback) {
Mike Stroyan14a57e72015-07-31 16:20:39 -0600192 matched = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600193 pPrev->pNext = pTrav->pNext;
194 if (debug_data->g_pDbgFunctionHead == pTrav) {
195 debug_data->g_pDbgFunctionHead = pTrav->pNext;
196 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600197 debug_report_log_msg(
198 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800199 VK_OBJECT_TYPE_MSG_CALLBACK, (uint64_t) pTrav->msgCallback,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600200 0, DEBUG_REPORT_NONE,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600201 "DebugReport",
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600202 "Destroyed callback");
Mike Stroyan14a57e72015-07-31 16:20:39 -0600203 } else {
204 matched = false;
Mike Stroyan22ff5022015-08-10 16:14:18 -0600205 debug_data->active_flags |= pTrav->msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600206 }
207 pPrev = pTrav;
208 pTrav = pTrav->pNext;
Mike Stroyan14a57e72015-07-31 16:20:39 -0600209 if (matched) {
210 free(pPrev);
211 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600212 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600213}
214
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600215static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600216 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600217 const char *funcName)
218{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600219 if (!debug_data || !debug_data->g_DEBUG_REPORT) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600220 return NULL;
221 }
222
223 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600224 return (PFN_vkVoidFunction) vkDbgCreateMsgCallback;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600225 }
226 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600227 return (PFN_vkVoidFunction) vkDbgDestroyMsgCallback;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600228 }
229
230 return NULL;
231}
232
233/*
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600234 * Checks if the message will get logged.
235 * Allows layer to defer collecting & formating data if the
236 * message will be discarded.
237 */
238static inline VkBool32 will_log_msg(
239 debug_report_data *debug_data,
240 VkFlags msgFlags)
241{
242 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
243 /* message is not wanted */
244 return false;
245 }
246
247 return true;
248}
249
250/*
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600251 * Output log message via DEBUG_REPORT
252 * Takes format and variable arg list so that output string
253 * is only computed if a message needs to be logged
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600254 */
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600255static inline VkBool32 log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600256 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600257 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600258 VkDbgObjectType objectType,
259 uint64_t srcObject,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600260 size_t location,
261 int32_t msgCode,
262 const char* pLayerPrefix,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600263 const char* format,
264 ...)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600265{
Courtney Goeltzenleuchter61cb70a2015-06-26 15:14:50 -0600266 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600267 /* message is not wanted */
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600268 return false;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600269 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600270
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600271 char str[1024];
272 va_list argptr;
273 va_start(argptr, format);
274 vsnprintf(str, 1024, format, argptr);
275 va_end(argptr);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600276 return debug_report_log_msg(
277 debug_data, msgFlags, objectType,
278 srcObject, location, msgCode,
279 pLayerPrefix, str);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600280}
281
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600282static inline VkBool32 VKAPI log_callback(
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600283 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600284 VkDbgObjectType objType,
285 uint64_t srcObject,
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600286 size_t location,
287 int32_t msgCode,
288 const char* pLayerPrefix,
289 const char* pMsg,
290 void* pUserData)
291{
292 char msg_flags[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600293
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600294 print_msg_flags(msgFlags, msg_flags);
295
Mark Lobodzinskia1456492015-10-06 09:57:52 -0600296 fprintf((FILE *) pUserData, "%s(%s): object: %#" PRIx64 " type: %d location: %lu msgCode: %d: %s\n",
297 pLayerPrefix, msg_flags, srcObject, objType, (unsigned long)location, msgCode, pMsg);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600298 fflush((FILE *) pUserData);
299
300 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600301}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600302
303static inline VkBool32 VKAPI win32_debug_output_msg(
304 VkFlags msgFlags,
305 VkDbgObjectType objType,
306 uint64_t srcObject,
307 size_t location,
308 int32_t msgCode,
309 const char* pLayerPrefix,
310 const char* pMsg,
311 void* pUserData)
312{
313#ifdef WIN32
314 char msg_flags[30];
315 char buf[2048];
316
317 print_msg_flags(msgFlags, msg_flags);
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600318 _snprintf(buf, sizeof(buf) - 1, "%s (%s): object: 0x%" PRIxPTR " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msgCode: %d: %s\n",
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600319 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
320
321 OutputDebugString(buf);
322#endif
323
324 return false;
325}
326
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600327#endif // LAYER_LOGGING_H