blob: a7cc6bbe24e33487448b5ce1530fcdefe1cbf6af [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 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060023 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
24 * Author: Tobin Ehlis <tobin@lunarg.com>
25 *
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060026 */
27
28#ifndef LAYER_LOGGING_H
29#define LAYER_LOGGING_H
30
31#include <stdio.h>
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -060032#include <stdarg.h>
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060033#include <stdbool.h>
34#include <unordered_map>
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -060035#include <inttypes.h>
Tobin Ehlis890adf12015-11-02 15:45:19 -070036#include "vk_loader_platform.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070037#include "vulkan/vk_layer.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060038#include "vk_layer_data.h"
39#include "vk_layer_table.h"
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060040
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060041typedef struct _debug_report_data {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060042 VkLayerDbgFunctionNode *g_pDbgFunctionHead;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -060043 VkFlags active_flags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060044 bool g_DEBUG_REPORT;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060045} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060046
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060047template debug_report_data *get_my_data_ptr<debug_report_data>(
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060048 void *data_key,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060049 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060050
51// Utility function to handle reporting
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060052static inline VkBool32 debug_report_log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060053 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060054 VkFlags msgFlags,
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -060055 VkDbgObjectType objectType,
56 uint64_t srcObject,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060057 size_t location,
58 int32_t msgCode,
59 const char* pLayerPrefix,
60 const char* pMsg)
61{
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060062 VkBool32 bail = false;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060063 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
64 while (pTrav) {
65 if (pTrav->msgFlags & msgFlags) {
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060066 if (pTrav->pfnMsgCallback(msgFlags,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060067 objectType, srcObject,
68 location,
69 msgCode,
70 pLayerPrefix,
71 pMsg,
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060072 (void *) pTrav->pUserData)) {
73 bail = true;
74 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060075 }
76 pTrav = pTrav->pNext;
77 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -060078
79 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060080}
81
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060082static inline debug_report_data *debug_report_create_instance(
83 VkLayerInstanceDispatchTable *table,
84 VkInstance inst,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060085 uint32_t extension_count,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060086 const char*const* ppEnabledExtensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060087{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060088 debug_report_data *debug_data;
89 PFN_vkGetInstanceProcAddr gpa = table->GetInstanceProcAddr;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060090
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060091 table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback");
92 table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback");
93
94 debug_data = (debug_report_data *) malloc(sizeof(debug_report_data));
95 if (!debug_data) return NULL;
96
97 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060098 for (uint32_t i = 0; i < extension_count; i++) {
99 /* TODO: Check other property fields */
Courtney Goeltzenleuchter05159a92015-07-30 11:32:46 -0600100 if (strcmp(ppEnabledExtensions[i], VK_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600101 debug_data->g_DEBUG_REPORT = true;
102 }
103 }
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600104 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600105}
106
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600107static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600108{
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600109 VkLayerDbgFunctionNode *pTrav;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600110 VkLayerDbgFunctionNode *pTravNext;
111
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600112 if (!debug_data) {
113 return;
114 }
115
116 pTrav = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600117 /* Clear out any leftover callbacks */
118 while (pTrav) {
119 pTravNext = pTrav->pNext;
120
121 debug_report_log_msg(
122 debug_data, VK_DBG_REPORT_WARN_BIT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800123 VK_OBJECT_TYPE_MSG_CALLBACK, (uint64_t) pTrav->msgCallback,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600124 0, DEBUG_REPORT_CALLBACK_REF,
125 "DebugReport",
126 "Debug Report callbacks not removed before DestroyInstance");
127
128 free(pTrav);
129 pTrav = pTravNext;
130 }
131 debug_data->g_pDbgFunctionHead = NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600132
133 free(debug_data);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600134}
135
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600136static inline debug_report_data *layer_debug_report_create_device(
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600137 debug_report_data *instance_debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600138 VkDevice device)
139{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600140 /* DEBUG_REPORT shares data between Instance and Device,
141 * so just return instance's data pointer */
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600142 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600143}
144
145static inline void layer_debug_report_destroy_device(VkDevice device)
146{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600147 /* Nothing to do since we're using instance data record */
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600148}
149
150static inline VkResult layer_create_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600151 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600152 VkFlags msgFlags,
153 const PFN_vkDbgMsgCallback pfnMsgCallback,
154 void *pUserData,
155 VkDbgMsgCallback *pMsgCallback)
156{
157 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode));
158 if (!pNewDbgFuncNode)
159 return VK_ERROR_OUT_OF_HOST_MEMORY;
160
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600161 // Handle of 0 is logging_callback so use allocated Node address as unique handle
162 if (!(*pMsgCallback))
Chia-I Wue2fc5522015-10-26 20:04:44 +0800163 *pMsgCallback = (VkDbgMsgCallback) pNewDbgFuncNode;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600164 pNewDbgFuncNode->msgCallback = *pMsgCallback;
165 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
166 pNewDbgFuncNode->msgFlags = msgFlags;
167 pNewDbgFuncNode->pUserData = pUserData;
168 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600169
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600170 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600171 debug_data->active_flags |= msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600172
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600173 debug_report_log_msg(
174 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800175 VK_OBJECT_TYPE_MSG_CALLBACK, (uint64_t) *pMsgCallback,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600176 0, DEBUG_REPORT_CALLBACK_REF,
177 "DebugReport",
178 "Added callback");
179 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600180}
181
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600182static inline void layer_destroy_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600183 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600184 VkDbgMsgCallback msg_callback)
185{
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600186 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
187 VkLayerDbgFunctionNode *pPrev = pTrav;
Mike Stroyan14a57e72015-07-31 16:20:39 -0600188 bool matched;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600189
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600190 debug_data->active_flags = 0;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600191 while (pTrav) {
192 if (pTrav->msgCallback == msg_callback) {
Mike Stroyan14a57e72015-07-31 16:20:39 -0600193 matched = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600194 pPrev->pNext = pTrav->pNext;
195 if (debug_data->g_pDbgFunctionHead == pTrav) {
196 debug_data->g_pDbgFunctionHead = pTrav->pNext;
197 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600198 debug_report_log_msg(
199 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800200 VK_OBJECT_TYPE_MSG_CALLBACK, (uint64_t) pTrav->msgCallback,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600201 0, DEBUG_REPORT_NONE,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600202 "DebugReport",
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600203 "Destroyed callback");
Mike Stroyan14a57e72015-07-31 16:20:39 -0600204 } else {
205 matched = false;
Mike Stroyan22ff5022015-08-10 16:14:18 -0600206 debug_data->active_flags |= pTrav->msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600207 }
208 pPrev = pTrav;
209 pTrav = pTrav->pNext;
Mike Stroyan14a57e72015-07-31 16:20:39 -0600210 if (matched) {
211 free(pPrev);
212 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600213 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600214}
215
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600216static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600217 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600218 const char *funcName)
219{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600220 if (!debug_data || !debug_data->g_DEBUG_REPORT) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600221 return NULL;
222 }
223
224 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600225 return (PFN_vkVoidFunction) vkDbgCreateMsgCallback;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600226 }
227 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -0600228 return (PFN_vkVoidFunction) vkDbgDestroyMsgCallback;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600229 }
230
231 return NULL;
232}
233
234/*
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600235 * Checks if the message will get logged.
236 * Allows layer to defer collecting & formating data if the
237 * message will be discarded.
238 */
239static inline VkBool32 will_log_msg(
240 debug_report_data *debug_data,
241 VkFlags msgFlags)
242{
243 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
244 /* message is not wanted */
245 return false;
246 }
247
248 return true;
249}
250
251/*
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600252 * Output log message via DEBUG_REPORT
253 * Takes format and variable arg list so that output string
254 * is only computed if a message needs to be logged
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600255 */
Michael Lentine010f4692015-11-03 16:19:46 -0800256#ifndef WIN32
257static inline VkBool32 log_msg(
258 debug_report_data *debug_data,
259 VkFlags msgFlags,
260 VkDbgObjectType objectType,
261 uint64_t srcObject,
262 size_t location,
263 int32_t msgCode,
264 const char* pLayerPrefix,
265 const char* format,
266 ...) __attribute__ ((format (printf, 8, 9)));
267#endif
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600268static inline VkBool32 log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600269 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600270 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600271 VkDbgObjectType objectType,
272 uint64_t srcObject,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600273 size_t location,
274 int32_t msgCode,
275 const char* pLayerPrefix,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600276 const char* format,
277 ...)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600278{
Courtney Goeltzenleuchter61cb70a2015-06-26 15:14:50 -0600279 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600280 /* message is not wanted */
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600281 return false;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600282 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600283
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600284 char str[1024];
285 va_list argptr;
286 va_start(argptr, format);
287 vsnprintf(str, 1024, format, argptr);
288 va_end(argptr);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600289 return debug_report_log_msg(
290 debug_data, msgFlags, objectType,
291 srcObject, location, msgCode,
292 pLayerPrefix, str);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600293}
294
Chia-I Wu9ab61502015-11-06 06:42:02 +0800295static inline VKAPI_ATTR VkBool32 VKAPI_CALL log_callback(
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600296 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600297 VkDbgObjectType objType,
298 uint64_t srcObject,
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600299 size_t location,
300 int32_t msgCode,
301 const char* pLayerPrefix,
302 const char* pMsg,
303 void* pUserData)
304{
305 char msg_flags[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600306
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600307 print_msg_flags(msgFlags, msg_flags);
308
Mark Lobodzinskia1456492015-10-06 09:57:52 -0600309 fprintf((FILE *) pUserData, "%s(%s): object: %#" PRIx64 " type: %d location: %lu msgCode: %d: %s\n",
310 pLayerPrefix, msg_flags, srcObject, objType, (unsigned long)location, msgCode, pMsg);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600311 fflush((FILE *) pUserData);
312
313 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600314}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600315
Chia-I Wu9ab61502015-11-06 06:42:02 +0800316static inline VKAPI_ATTR VkBool32 VKAPI_CALL win32_debug_output_msg(
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600317 VkFlags msgFlags,
318 VkDbgObjectType objType,
319 uint64_t srcObject,
320 size_t location,
321 int32_t msgCode,
322 const char* pLayerPrefix,
323 const char* pMsg,
324 void* pUserData)
325{
326#ifdef WIN32
327 char msg_flags[30];
328 char buf[2048];
329
330 print_msg_flags(msgFlags, msg_flags);
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600331 _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 -0600332 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
333
334 OutputDebugString(buf);
335#endif
336
337 return false;
338}
339
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600340#endif // LAYER_LOGGING_H