blob: 68155a6367ab1cae3aa3017434ed88fadb610e29 [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 Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600128 /* DEBUG_REPORT shared data between Instance and Device */
129 return instance_debug_data;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600130}
131
132static inline void layer_debug_report_destroy_device(VkDevice device)
133{
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600134}
135
136static inline VkResult layer_create_msg_callback(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600137 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600138 VkFlags msgFlags,
139 const PFN_vkDbgMsgCallback pfnMsgCallback,
140 void *pUserData,
141 VkDbgMsgCallback *pMsgCallback)
142{
143 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode*)malloc(sizeof(VkLayerDbgFunctionNode));
144 if (!pNewDbgFuncNode)
145 return VK_ERROR_OUT_OF_HOST_MEMORY;
146
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600147 pNewDbgFuncNode->msgCallback = *pMsgCallback;
148 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
149 pNewDbgFuncNode->msgFlags = msgFlags;
150 pNewDbgFuncNode->pUserData = pUserData;
151 pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600152
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600153 debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600154 debug_data->active_flags |= msgFlags;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600155
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600156 debug_report_log_msg(
157 debug_data, VK_DBG_REPORT_DEBUG_BIT,
158 VK_OBJECT_TYPE_MSG_CALLBACK, *pMsgCallback,
159 0, DEBUG_REPORT_CALLBACK_REF,
160 "DebugReport",
161 "Added callback");
162 return VK_SUCCESS;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600163}
164
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -0600165static inline void layer_destroy_msg_callback(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600166 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600167 VkDbgMsgCallback msg_callback)
168{
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600169 VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
170 VkLayerDbgFunctionNode *pPrev = pTrav;
171
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600172 debug_data->active_flags = 0;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600173 while (pTrav) {
174 if (pTrav->msgCallback == msg_callback) {
175 pPrev->pNext = pTrav->pNext;
176 if (debug_data->g_pDbgFunctionHead == pTrav) {
177 debug_data->g_pDbgFunctionHead = pTrav->pNext;
178 }
179 free(pTrav);
180 debug_report_log_msg(
181 debug_data, VK_DBG_REPORT_DEBUG_BIT,
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600182 VK_OBJECT_TYPE_MSG_CALLBACK, pTrav->msgCallback,
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600183 0, DEBUG_REPORT_NONE,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600184 "DebugReport",
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600185 "Destroyed callback");
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600186 }
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600187 debug_data->active_flags |= pTrav->msgFlags;
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600188 pPrev = pTrav;
189 pTrav = pTrav->pNext;
190 }
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600191}
192
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -0600193static inline void* debug_report_get_instance_proc_addr(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600194 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600195 const char *funcName)
196{
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600197 if (!debug_data || !debug_data->g_DEBUG_REPORT) {
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600198 return NULL;
199 }
200
201 if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
202 return (void *) vkDbgCreateMsgCallback;
203 }
204 if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
205 return (void *) vkDbgDestroyMsgCallback;
206 }
207
208 return NULL;
209}
210
211/*
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600212 * Output log message via DEBUG_REPORT
213 * Takes format and variable arg list so that output string
214 * is only computed if a message needs to be logged
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600215 */
Courtney Goeltzenleuchter0e121512015-06-14 11:28:24 -0600216static inline void log_msg(
Courtney Goeltzenleuchter1f1fbbd2015-06-14 12:03:26 -0600217 debug_report_data *debug_data,
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600218 VkFlags msgFlags,
219 VkObjectType objectType,
220 VkObject srcObject,
221 size_t location,
222 int32_t msgCode,
223 const char* pLayerPrefix,
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600224 const char* format,
225 ...)
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600226{
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600227 if (!(debug_data->active_flags & msgFlags)) {
228 /* message is not wanted */
229 return;
230 }
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600231
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600232 char str[1024];
233 va_list argptr;
234 va_start(argptr, format);
235 vsnprintf(str, 1024, format, argptr);
236 va_end(argptr);
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600237 debug_report_log_msg(debug_data, msgFlags, objectType,
238 srcObject, location, msgCode,
Courtney Goeltzenleuchter3e19bf62015-06-14 09:50:18 -0600239 pLayerPrefix, str);
Courtney Goeltzenleuchter41fa5b02015-06-11 15:58:51 -0600240}
241
242#endif // LAYER_LOGGING_H
243