blob: 9370abd578d931120a243f8aafc391915f00ca01 [file] [log] [blame]
Courtney Goeltzenleuchter41fa5b02015-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 Goeltzenleuchter3e19bf62015-06-14 09:50:18 -060032#include <stdarg.h>
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060033#include <stdbool.h>
34#include <unordered_map>
35#include "vkLayer.h"
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -060036#include "layer_data.h"
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060037#include "layers_table.h"
38
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060039typedef struct _debug_report_data {
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060040 VkLayerDbgFunctionNode *g_pDbgFunctionHead;
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -060041 VkFlags active_flags;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060042 bool g_DEBUG_REPORT;
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060043} debug_report_data;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060044
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060045template debug_report_data *get_my_data_ptr<debug_report_data>(
Courtney Goeltzenleuchterf1eb2492015-06-11 16:01:11 -060046 void *data_key,
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060047 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060048
49// Utility function to handle reporting
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -060050static inline void debug_report_log_msg(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060051 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-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 Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060075static inline debug_report_data *debug_report_create_instance(
76 VkLayerInstanceDispatchTable *table,
77 VkInstance inst,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060078 uint32_t extension_count,
79 const VkExtensionProperties* pEnabledExtensions) // layer or extension name to be enabled
80{
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060081 debug_report_data *debug_data;
82 PFN_vkGetInstanceProcAddr gpa = table->GetInstanceProcAddr;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060083
Courtney Goeltzenleuchter1f1fbbd2015-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 Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060091 for (uint32_t i = 0; i < extension_count; i++) {
92 /* TODO: Check other property fields */
93 if (strcmp(pEnabledExtensions[i].name, DEBUG_REPORT_EXTENSION_NAME) == 0) {
94 debug_data->g_DEBUG_REPORT = true;
95 }
96 }
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -060097 return debug_data;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -060098}
99
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600100static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data)
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600101{
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600102 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
103 VkLayerDbgFunctionNode *pTravNext;
104
105 /* Clear out any leftover callbacks */
106 while (pTrav) {
107 pTravNext = pTrav->pNext;
108
109 debug_report_log_msg(
110 debug_data, VK_DBG_REPORT_WARN_BIT,
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600111 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600112 0, DEBUG_REPORT_CALLBACK_REF,
113 "DebugReport",
114 "Debug Report callbacks not removed before DestroyInstance");
115
116 free(pTrav);
117 pTrav = pTravNext;
118 }
119 debug_data->g_pDbgFunctionHead = NULL;
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600120
121 free(debug_data);
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600122}
123
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600124static inline debug_report_data *layer_debug_report_create_device(
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600125 debug_report_data *instance_debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600126 VkDevice device)
127{
Courtney Goeltzenleuchter7ad921d2015-06-14 11:29:24 -0600128 /* DEBUG_REPORT shares data between Instance and Device,
129 * so just return instance's data pointer */
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600130 return instance_debug_data;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600131}
132
133static inline void layer_debug_report_destroy_device(VkDevice device)
134{
Courtney Goeltzenleuchter7ad921d2015-06-14 11:29:24 -0600135 /* Nothing to do since we're using instance data record */
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600136}
137
138static inline VkResult layer_create_msg_callback(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600139 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600140 VkFlags msgFlags,
141 const PFN_vkDbgMsgCallback pfnMsgCallback,
142 void *pUserData,
143 VkDbgMsgCallback *pMsgCallback)
144{
145 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode));
146 if (!pNewDbgFuncNode)
147 return VK_ERROR_OUT_OF_HOST_MEMORY;
148
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600149 pNewDbgFuncNode->msgCallback = *pMsgCallback;
150 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
151 pNewDbgFuncNode->msgFlags = msgFlags;
152 pNewDbgFuncNode->pUserData = pUserData;
153 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600154
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600155 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600156 debug_data->active_flags |= msgFlags;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600157
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600158 debug_report_log_msg(
159 debug_data, VK_DBG_REPORT_DEBUG_BIT,
160 VK_OBJECT_TYPE_MSG_CALLBACK, *pMsgCallback,
161 0, DEBUG_REPORT_CALLBACK_REF,
162 "DebugReport",
163 "Added callback");
164 return VK_SUCCESS;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600165}
166
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -0600167static inline void layer_destroy_msg_callback(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600168 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600169 VkDbgMsgCallback msg_callback)
170{
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600171 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
172 VkLayerDbgFunctionNode *pPrev = pTrav;
173
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600174 debug_data->active_flags = 0;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600175 while (pTrav) {
176 if (pTrav->msgCallback == msg_callback) {
177 pPrev->pNext = pTrav->pNext;
178 if (debug_data->g_pDbgFunctionHead == pTrav) {
179 debug_data->g_pDbgFunctionHead = pTrav->pNext;
180 }
181 free(pTrav);
182 debug_report_log_msg(
183 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600184 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback,
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600185 0, DEBUG_REPORT_NONE,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600186 "DebugReport",
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600187 "Destroyed callback");
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600188 }
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600189 debug_data->active_flags |= pTrav->msgFlags;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600190 pPrev = pTrav;
191 pTrav = pTrav->pNext;
192 }
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600193}
194
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -0600195static inline void* debug_report_get_instance_proc_addr(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600196 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600197 const char *funcName)
198{
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600199 if (!debug_data || !debug_data->g_DEBUG_REPORT) {
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600200 return NULL;
201 }
202
203 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
204 return (void *) vkDbgCreateMsgCallback;
205 }
206 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
207 return (void *) vkDbgDestroyMsgCallback;
208 }
209
210 return NULL;
211}
212
213/*
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600214 * Output log message via DEBUG_REPORT
215 * Takes format and variable arg list so that output string
216 * is only computed if a message needs to be logged
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600217 */
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -0600218static inline void log_msg(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600219 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600220 VkFlags msgFlags,
221 VkObjectType objectType,
222 VkObject srcObject,
223 size_t location,
224 int32_t msgCode,
225 const char* pLayerPrefix,
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600226 const char* format,
227 ...)
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600228{
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600229 if (!(debug_data->active_flags & msgFlags)) {
230 /* message is not wanted */
231 return;
232 }
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600233
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600234 char str[1024];
235 va_list argptr;
236 va_start(argptr, format);
237 vsnprintf(str, 1024, format, argptr);
238 va_end(argptr);
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600239 debug_report_log_msg(debug_data, msgFlags, objectType,
240 srcObject, location, msgCode,
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600241 pLayerPrefix, str);
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600242}
243
Courtney Goeltzenleuchter7ad921d2015-06-14 11:29:24 -0600244static inline void VKAPI log_callback(
245 VkFlags msgFlags,
246 VkObjectType objType,
247 VkObject srcObject,
248 size_t location,
249 int32_t msgCode,
250 const char* pLayerPrefix,
251 const char* pMsg,
252 void* pUserData)
253{
254 char msg_flags[30];
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600255
Courtney Goeltzenleuchter7ad921d2015-06-14 11:29:24 -0600256 print_msg_flags(msgFlags, msg_flags);
257
Courtney Goeltzenleuchter284e3902015-06-16 17:01:30 -0600258 fprintf((FILE *) pUserData, "%s(%s): object: 0x%p type: %d location: %zu msgCode: %d: %s\n",
Courtney Goeltzenleuchter7ad921d2015-06-14 11:29:24 -0600259 pLayerPrefix, msg_flags, srcObject, objType, location, msgCode, pMsg);
260}
261#endif // LAYER_LOGGING_H