blob: 0f0884450e2289bb1633e1f830c8077cab72bf2f [file] [log] [blame]
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06001/*
2 * Vulkan
3 *
4 * Copyright (C) 2014 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 * Courtney Goeltzenleuchter <courtney@lunarg.com>
26 */
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"
Tobin Ehlis0c6f9ee2015-07-03 09:42:57 -060037#include "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 */
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600256static inline VkBool32 log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600257 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600258 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600259 VkDbgObjectType objectType,
260 uint64_t srcObject,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600261 size_t location,
262 int32_t msgCode,
263 const char* pLayerPrefix,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600264 const char* format,
265 ...)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600266{
Courtney Goeltzenleuchter61cb70a2015-06-26 15:14:50 -0600267 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600268 /* message is not wanted */
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600269 return false;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600270 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600271
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600272 char str[1024];
273 va_list argptr;
274 va_start(argptr, format);
275 vsnprintf(str, 1024, format, argptr);
276 va_end(argptr);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600277 return debug_report_log_msg(
278 debug_data, msgFlags, objectType,
279 srcObject, location, msgCode,
280 pLayerPrefix, str);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600281}
282
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600283static inline VkBool32 VKAPI log_callback(
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600284 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600285 VkDbgObjectType objType,
286 uint64_t srcObject,
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600287 size_t location,
288 int32_t msgCode,
289 const char* pLayerPrefix,
290 const char* pMsg,
291 void* pUserData)
292{
293 char msg_flags[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600294
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600295 print_msg_flags(msgFlags, msg_flags);
296
Mark Lobodzinskia1456492015-10-06 09:57:52 -0600297 fprintf((FILE *) pUserData, "%s(%s): object: %#" PRIx64 " type: %d location: %lu msgCode: %d: %s\n",
298 pLayerPrefix, msg_flags, srcObject, objType, (unsigned long)location, msgCode, pMsg);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600299 fflush((FILE *) pUserData);
300
301 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600302}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600303
304static inline VkBool32 VKAPI win32_debug_output_msg(
305 VkFlags msgFlags,
306 VkDbgObjectType objType,
307 uint64_t srcObject,
308 size_t location,
309 int32_t msgCode,
310 const char* pLayerPrefix,
311 const char* pMsg,
312 void* pUserData)
313{
314#ifdef WIN32
315 char msg_flags[30];
316 char buf[2048];
317
318 print_msg_flags(msgFlags, msg_flags);
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600319 _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 -0600320 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
321
322 OutputDebugString(buf);
323#endif
324
325 return false;
326}
327
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600328#endif // LAYER_LOGGING_H