blob: 4ba1027ad94edc09998cd6ede7e879548b438611 [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 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 Goeltzenleuchter37d482d2015-06-14 11:28:24 -060051static inline void 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{
61 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
62 while (pTrav) {
63 if (pTrav->msgFlags & msgFlags) {
64 pTrav->pfnMsgCallback(msgFlags,
65 objectType, srcObject,
66 location,
67 msgCode,
68 pLayerPrefix,
69 pMsg,
70 (void *) pTrav->pUserData);
71 }
72 pTrav = pTrav->pNext;
73 }
74}
75
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060076static inline debug_report_data *debug_report_create_instance(
77 VkLayerInstanceDispatchTable *table,
78 VkInstance inst,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060079 uint32_t extension_count,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060080 const char*const* ppEnabledExtensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060081{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060082 debug_report_data *debug_data;
83 PFN_vkGetInstanceProcAddr gpa = table->GetInstanceProcAddr;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060084
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060085 table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback");
86 table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback");
87
88 debug_data = (debug_report_data *) malloc(sizeof(debug_report_data));
89 if (!debug_data) return NULL;
90
91 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060092 for (uint32_t i = 0; i < extension_count; i++) {
93 /* TODO: Check other property fields */
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060094 if (strcmp(ppEnabledExtensions[i], DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060095 debug_data->g_DEBUG_REPORT = true;
96 }
97 }
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060098 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060099}
100
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600101static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600102{
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600103 VkLayerDbgFunctionNode *pTrav;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600104 VkLayerDbgFunctionNode *pTravNext;
105
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600106 if (!debug_data) {
107 return;
108 }
109
110 pTrav = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600111 /* Clear out any leftover callbacks */
112 while (pTrav) {
113 pTravNext = pTrav->pNext;
114
115 debug_report_log_msg(
116 debug_data, VK_DBG_REPORT_WARN_BIT,
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -0600117 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback.handle,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600118 0, DEBUG_REPORT_CALLBACK_REF,
119 "DebugReport",
120 "Debug Report callbacks not removed before DestroyInstance");
121
122 free(pTrav);
123 pTrav = pTravNext;
124 }
125 debug_data->g_pDbgFunctionHead = NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600126
127 free(debug_data);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600128}
129
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600130static inline debug_report_data *layer_debug_report_create_device(
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600131 debug_report_data *instance_debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600132 VkDevice device)
133{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600134 /* DEBUG_REPORT shares data between Instance and Device,
135 * so just return instance's data pointer */
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600136 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600137}
138
139static inline void layer_debug_report_destroy_device(VkDevice device)
140{
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600141 /* Nothing to do since we're using instance data record */
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600142}
143
144static inline VkResult layer_create_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600145 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600146 VkFlags msgFlags,
147 const PFN_vkDbgMsgCallback pfnMsgCallback,
148 void *pUserData,
149 VkDbgMsgCallback *pMsgCallback)
150{
151 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode));
152 if (!pNewDbgFuncNode)
153 return VK_ERROR_OUT_OF_HOST_MEMORY;
154
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600155 pNewDbgFuncNode->msgCallback = *pMsgCallback;
156 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
157 pNewDbgFuncNode->msgFlags = msgFlags;
158 pNewDbgFuncNode->pUserData = pUserData;
159 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600160
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600161 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600162 debug_data->active_flags |= msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600163
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600164 debug_report_log_msg(
165 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -0600166 VK_OBJECT_TYPE_MSG_CALLBACK, (*pMsgCallback).handle,
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600167 0, DEBUG_REPORT_CALLBACK_REF,
168 "DebugReport",
169 "Added callback");
170 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600171}
172
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600173static inline void layer_destroy_msg_callback(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600174 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600175 VkDbgMsgCallback msg_callback)
176{
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600177 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
178 VkLayerDbgFunctionNode *pPrev = pTrav;
179
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600180 debug_data->active_flags = 0;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600181 while (pTrav) {
182 if (pTrav->msgCallback == msg_callback) {
183 pPrev->pNext = pTrav->pNext;
184 if (debug_data->g_pDbgFunctionHead == pTrav) {
185 debug_data->g_pDbgFunctionHead = pTrav->pNext;
186 }
187 free(pTrav);
188 debug_report_log_msg(
189 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -0600190 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback.handle,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600191 0, DEBUG_REPORT_NONE,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600192 "DebugReport",
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600193 "Destroyed callback");
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600194 }
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600195 debug_data->active_flags |= pTrav->msgFlags;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600196 pPrev = pTrav;
197 pTrav = pTrav->pNext;
198 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600199}
200
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600201static inline void* debug_report_get_instance_proc_addr(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600202 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600203 const char *funcName)
204{
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600205 if (!debug_data || !debug_data->g_DEBUG_REPORT) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600206 return NULL;
207 }
208
209 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
210 return (void *) vkDbgCreateMsgCallback;
211 }
212 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
213 return (void *) vkDbgDestroyMsgCallback;
214 }
215
216 return NULL;
217}
218
219/*
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600220 * Output log message via DEBUG_REPORT
221 * Takes format and variable arg list so that output string
222 * is only computed if a message needs to be logged
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600223 */
Courtney Goeltzenleuchter37d482d2015-06-14 11:28:24 -0600224static inline void log_msg(
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600225 debug_report_data *debug_data,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600226 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600227 VkDbgObjectType objectType,
228 uint64_t srcObject,
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600229 size_t location,
230 int32_t msgCode,
231 const char* pLayerPrefix,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600232 const char* format,
233 ...)
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600234{
Courtney Goeltzenleuchter61cb70a2015-06-26 15:14:50 -0600235 if (!debug_data || !(debug_data->active_flags & msgFlags)) {
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600236 /* message is not wanted */
237 return;
238 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600239
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600240 char str[1024];
241 va_list argptr;
242 va_start(argptr, format);
243 vsnprintf(str, 1024, format, argptr);
244 va_end(argptr);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600245 debug_report_log_msg(debug_data, msgFlags, objectType,
246 srcObject, location, msgCode,
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600247 pLayerPrefix, str);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600248}
249
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600250static inline void VKAPI log_callback(
251 VkFlags msgFlags,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600252 VkDbgObjectType objType,
253 uint64_t srcObject,
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600254 size_t location,
255 int32_t msgCode,
256 const char* pLayerPrefix,
257 const char* pMsg,
258 void* pUserData)
259{
260 char msg_flags[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600261
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600262 print_msg_flags(msgFlags, msg_flags);
263
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -0600264 fprintf((FILE *) pUserData, "%s(%s): object: %#" PRIx64 " type: %d location: %zu msgCode: %d: %s\n",
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600265 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
266}
267#endif // LAYER_LOGGING_H