blob: be0a09cec6bf1bd9ac938e23cd26abd5ad379bfa [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 Ehlis0c6f9ee2015-07-03 09:42:57 -060035#include "vk_layer.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060036#include "vk_layer_data.h"
37#include "vk_layer_table.h"
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060038
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060039typedef struct _debug_report_data {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060040 VkLayerDbgFunctionNode *g_pDbgFunctionHead;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -060041 VkFlags active_flags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060042 bool g_DEBUG_REPORT;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060043} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060044
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060045template debug_report_data *get_my_data_ptr<debug_report_data>(
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060046 void *data_key,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060047 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060048
49// Utility function to handle reporting
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -060050static inline void debug_report_log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060051 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060052 VkFlags msgFlags,
53 VkObjectType objectType,
54 VkObject srcObject,
55 size_t location,
56 int32_t msgCode,
57 const char* pLayerPrefix,
58 const char* pMsg)
59{
60 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
61 while (pTrav) {
62 if (pTrav->msgFlags & msgFlags) {
63 pTrav->pfnMsgCallback(msgFlags,
64 objectType, srcObject,
65 location,
66 msgCode,
67 pLayerPrefix,
68 pMsg,
69 (void *) pTrav->pUserData);
70 }
71 pTrav = pTrav->pNext;
72 }
73}
74
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060075static inline debug_report_data *debug_report_create_instance(
76 VkLayerInstanceDispatchTable *table,
77 VkInstance inst,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060078 uint32_t extension_count,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060079 const char*const* ppEnabledExtensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060080{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060081 debug_report_data *debug_data;
82 PFN_vkGetInstanceProcAddr gpa = table->GetInstanceProcAddr;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060083
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060084 table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback");
85 table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback");
86
87 debug_data = (debug_report_data *) malloc(sizeof(debug_report_data));
88 if (!debug_data) return NULL;
89
90 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060091 for (uint32_t i = 0; i < extension_count; i++) {
92 /* TODO: Check other property fields */
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060093 if (strcmp(ppEnabledExtensions[i], DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060094 debug_data->g_DEBUG_REPORT = true;
95 }
96 }
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060097 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060098}
99
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600100static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600101{
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600102 VkLayerDbgFunctionNode *pTrav;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600103 VkLayerDbgFunctionNode *pTravNext;
104
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600105 if (!debug_data) {
106 return;
107 }
108
109 pTrav = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600110 /* Clear out any leftover callbacks */
111 while (pTrav) {
112 pTravNext = pTrav->pNext;
113
114 debug_report_log_msg(
115 debug_data, VK_DBG_REPORT_WARN_BIT,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600116 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600117 0, DEBUG_REPORT_CALLBACK_REF,
118 "DebugReport",
119 "Debug Report callbacks not removed before DestroyInstance");
120
121 free(pTrav);
122 pTrav = pTravNext;
123 }
124 debug_data->g_pDbgFunctionHead = NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600125
126 free(debug_data);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600127}
128
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600129static inline debug_report_data *layer_debug_report_create_device(
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600130 debug_report_data *instance_debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600131 VkDevice device)
132{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600133 /* DEBUG_REPORT shares data between Instance and Device,
134 * so just return instance's data pointer */
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600135 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600136}
137
138static inline void layer_debug_report_destroy_device(VkDevice device)
139{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600140 /* Nothing to do since we're using instance data record */
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600141}
142
143static inline VkResult layer_create_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600144 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600145 VkFlags msgFlags,
146 const PFN_vkDbgMsgCallback pfnMsgCallback,
147 void *pUserData,
148 VkDbgMsgCallback *pMsgCallback)
149{
150 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode));
151 if (!pNewDbgFuncNode)
152 return VK_ERROR_OUT_OF_HOST_MEMORY;
153
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600154 pNewDbgFuncNode->msgCallback = *pMsgCallback;
155 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
156 pNewDbgFuncNode->msgFlags = msgFlags;
157 pNewDbgFuncNode->pUserData = pUserData;
158 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600159
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600160 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600161 debug_data->active_flags |= msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600162
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600163 debug_report_log_msg(
164 debug_data, VK_DBG_REPORT_DEBUG_BIT,
165 VK_OBJECT_TYPE_MSG_CALLBACK, *pMsgCallback,
166 0, DEBUG_REPORT_CALLBACK_REF,
167 "DebugReport",
168 "Added callback");
169 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600170}
171
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600172static inline void layer_destroy_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600173 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600174 VkDbgMsgCallback msg_callback)
175{
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600176 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
177 VkLayerDbgFunctionNode *pPrev = pTrav;
178
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600179 debug_data->active_flags = 0;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600180 while (pTrav) {
181 if (pTrav->msgCallback == msg_callback) {
182 pPrev->pNext = pTrav->pNext;
183 if (debug_data->g_pDbgFunctionHead == pTrav) {
184 debug_data->g_pDbgFunctionHead = pTrav->pNext;
185 }
186 free(pTrav);
187 debug_report_log_msg(
188 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600189 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600190 0, DEBUG_REPORT_NONE,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600191 "DebugReport",
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600192 "Destroyed callback");
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600193 }
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600194 debug_data->active_flags |= pTrav->msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600195 pPrev = pTrav;
196 pTrav = pTrav->pNext;
197 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600198}
199
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600200static inline void* debug_report_get_instance_proc_addr(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600201 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600202 const char *funcName)
203{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600204 if (!debug_data || !debug_data->g_DEBUG_REPORT) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600205 return NULL;
206 }
207
208 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
209 return (void *) vkDbgCreateMsgCallback;
210 }
211 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
212 return (void *) vkDbgDestroyMsgCallback;
213 }
214
215 return NULL;
216}
217
218/*
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600219 * Output log message via DEBUG_REPORT
220 * Takes format and variable arg list so that output string
221 * is only computed if a message needs to be logged
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600222 */
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600223static inline void log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600224 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600225 VkFlags msgFlags,
226 VkObjectType objectType,
227 VkObject srcObject,
228 size_t location,
229 int32_t msgCode,
230 const char* pLayerPrefix,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600231 const char* format,
232 ...)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600233{
Courtney Goeltzenleuchter61cb70a2015-06-26 15:14:50 -0600234 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600235 /* message is not wanted */
236 return;
237 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600238
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600239 char str[1024];
240 va_list argptr;
241 va_start(argptr, format);
242 vsnprintf(str, 1024, format, argptr);
243 va_end(argptr);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600244 debug_report_log_msg(debug_data, msgFlags, objectType,
245 srcObject, location, msgCode,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600246 pLayerPrefix, str);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600247}
248
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600249static inline void VKAPI log_callback(
250 VkFlags msgFlags,
251 VkObjectType objType,
252 VkObject srcObject,
253 size_t location,
254 int32_t msgCode,
255 const char* pLayerPrefix,
256 const char* pMsg,
257 void* pUserData)
258{
259 char msg_flags[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600260
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600261 print_msg_flags(msgFlags, msg_flags);
262
Courtney Goeltzenleuchter95f2c0d2015-06-16 17:01:30 -0600263 fprintf((FILE *) pUserData, "%s(%s): object: 0x%p type: %d location: %zu msgCode: %d: %s\n",
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600264 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
265}
266#endif // LAYER_LOGGING_H