blob: 357216129b3844b3ffdf4e0a9d40b1bc0e46088b [file] [log] [blame]
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001/*
2 * Vulkan
3 *
4 * Copyright (C) 2015 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 * Jon Ashburn <jon@lunarg.com>
26 * Courtney Goeltzenleuchter <courtney@lunarg.com>
27 */
28
29#include <string.h>
30#include <stdlib.h>
31#include "debug_report.h"
32#include "vkLayer.h"
33
34static const struct loader_extension_property debug_report_extension_info = {
35 .info = {
36 .sType = VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
37 .name = DEBUG_REPORT_EXTENSION_NAME,
38 .version = VK_DEBUG_REPORT_EXTENSION_VERSION,
39 .description = "loader: debug report extension",
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060040 },
41 .origin = VK_EXTENSION_ORIGIN_LOADER,
42 .hosted = true,
43};
44
45void debug_report_add_instance_extensions(
46 struct loader_extension_list *ext_list)
47{
48 loader_add_to_ext_list(ext_list, 1, &debug_report_extension_info);
49}
50
51void debug_report_create_instance(
52 struct loader_instance *ptr_instance)
53{
54 ptr_instance->debug_report_enabled = has_vk_extension_property(
55 &debug_report_extension_info.info,
56 &ptr_instance->enabled_instance_extensions);
57}
58
59static VkResult debug_report_DbgCreateMsgCallback(
60 VkInstance instance,
61 VkFlags msgFlags,
62 const PFN_vkDbgMsgCallback pfnMsgCallback,
63 void* pUserData,
64 VkDbgMsgCallback* pMsgCallback)
65{
66 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *) malloc(sizeof(VkLayerDbgFunctionNode));
67 if (!pNewDbgFuncNode)
68 return VK_ERROR_OUT_OF_HOST_MEMORY;
69
70 struct loader_instance *inst = (struct loader_instance *) instance;
71 VkResult result = inst->disp->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
72 if (result == VK_SUCCESS) {
73 pNewDbgFuncNode->msgCallback = *pMsgCallback;
74 pNewDbgFuncNode->pfnMsgCallback = pfnMsgCallback;
75 pNewDbgFuncNode->msgFlags = msgFlags;
76 pNewDbgFuncNode->pUserData = pUserData;
77 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
78 inst->DbgFunctionHead = pNewDbgFuncNode;
79 } else {
80 free(pNewDbgFuncNode);
81 }
82 return result;
83}
84
85static VkResult debug_report_DbgDestroyMsgCallback(
86 VkInstance instance,
87 VkLayerDispatchTable nextTable,
88 VkDbgMsgCallback msg_callback)
89{
90 struct loader_instance *inst = (struct loader_instance *) instance;
91 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
92 VkLayerDbgFunctionNode *pPrev = pTrav;
93
94 VkResult result = nextTable.DbgDestroyMsgCallback(instance, msg_callback);
95
96 while (pTrav) {
97 if (pTrav->msgCallback == msg_callback) {
98 pPrev->pNext = pTrav->pNext;
99 if (inst->DbgFunctionHead == pTrav)
100 inst->DbgFunctionHead = pTrav->pNext;
101 free(pTrav);
102 break;
103 }
104 pPrev = pTrav;
105 pTrav = pTrav->pNext;
106 }
107
108 return result;
109}
110
111
112/*
113 * This is the instance chain terminator function
114 * for DbgCreateMsgCallback
115 */
116VkResult loader_DbgCreateMsgCallback(
117 VkInstance instance,
118 VkFlags msgFlags,
119 const PFN_vkDbgMsgCallback pfnMsgCallback,
120 const void* pUserData,
121 VkDbgMsgCallback* pMsgCallback)
122{
123 VkDbgMsgCallback *icd_info;
124 const struct loader_icd *icd;
125 struct loader_instance *inst;
126 VkResult res;
127 uint32_t storage_idx;
128
129 if (instance == VK_NULL_HANDLE)
130 return VK_ERROR_INVALID_HANDLE;
131
132 assert(loader.icds_scanned);
133
134 for (inst = loader.instances; inst; inst = inst->next) {
135 if ((VkInstance) inst == instance)
136 break;
137 }
138
139 if (inst == VK_NULL_HANDLE)
140 return VK_ERROR_INVALID_HANDLE;
141
142 icd_info = calloc(sizeof(VkDbgMsgCallback), inst->total_icd_count);
143 if (!icd_info) {
144 return VK_ERROR_OUT_OF_HOST_MEMORY;
145 }
146
147 storage_idx = 0;
148 for (icd = inst->icds; icd; icd = icd->next) {
149 if (!icd->DbgCreateMsgCallback) {
150 continue;
151 }
152
153 res = icd->DbgCreateMsgCallback(
154 icd->instance,
155 msgFlags,
156 pfnMsgCallback,
157 pUserData,
158 &icd_info[storage_idx]);
159
160 if (res != VK_SUCCESS) {
161 break;
162 }
163 storage_idx++;
164 }
165
166 /* roll back on errors */
167 if (icd) {
168 storage_idx = 0;
169 for (icd = inst->icds; icd; icd = icd->next) {
170 if (icd_info[storage_idx]) {
171 icd->DbgDestroyMsgCallback(
172 icd->instance,
173 icd_info[storage_idx]);
174 }
175 storage_idx++;
176 }
177
178 return res;
179 }
180
181 *pMsgCallback = (VkDbgMsgCallback) icd_info;
182
183 return VK_SUCCESS;
184}
185
186/*
187 * This is the instance chain terminator function
188 * for DbgDestroyMsgCallback
189 */
190VkResult loader_DbgDestroyMsgCallback(
191 VkInstance instance,
192 VkDbgMsgCallback msgCallback)
193{
194 uint32_t storage_idx;
195 VkDbgMsgCallback *icd_info;
196 const struct loader_icd *icd;
197 VkResult res = VK_SUCCESS;
198 struct loader_instance *inst;
199
200 if (instance == VK_NULL_HANDLE)
201 return VK_ERROR_INVALID_HANDLE;
202
203 assert(loader.icds_scanned);
204
205 for (inst = loader.instances; inst; inst = inst->next) {
206 if ((VkInstance) inst == instance)
207 break;
208 }
209
210 if (inst == VK_NULL_HANDLE)
211 return VK_ERROR_INVALID_HANDLE;
212
213 icd_info = (VkDbgMsgCallback *) msgCallback;
214 storage_idx = 0;
215 for (icd = inst->icds; icd; icd = icd->next) {
216 if (icd_info[storage_idx]) {
217 icd->DbgDestroyMsgCallback(
218 icd->scanned_icds->instance,
219 icd_info[storage_idx]);
220 }
221 storage_idx++;
222 }
223 return res;
224}
225
226// DebugReport utility callback functions
227static void VKAPI StringCallback(
228 VkFlags msgFlags,
229 VkObjectType objType,
230 VkObject srcObject,
231 size_t location,
232 int32_t msgCode,
233 const char* pLayerPrefix,
234 const char* pMsg,
235 void* pUserData)
236{
237
238}
239
240static void VKAPI StdioCallback(
241 VkFlags msgFlags,
242 VkObjectType objType,
243 VkObject srcObject,
244 size_t location,
245 int32_t msgCode,
246 const char* pLayerPrefix,
247 const char* pMsg,
248 void* pUserData)
249{
250
251}
252
253static void VKAPI BreakCallback(
254 VkFlags msgFlags,
255 VkObjectType objType,
256 VkObject srcObject,
257 size_t location,
258 int32_t msgCode,
259 const char* pLayerPrefix,
260 const char* pMsg,
261 void* pUserData)
262{
263
264}
265
266void *debug_report_instance_gpa(
267 struct loader_instance *ptr_instance,
268 const char* name)
269{
270 if (ptr_instance == VK_NULL_HANDLE || !ptr_instance->debug_report_enabled)
271 return NULL;
272
273 if (!strcmp("vkDbgCreateMsgCallback", name))
274 return (void *) debug_report_DbgCreateMsgCallback;
275 else if (!strcmp("vkDbgDestroyMsgCallback", name))
276 return (void *) debug_report_DbgDestroyMsgCallback;
Jon Ashburnc6aecd72015-05-26 13:56:43 -0600277 else if (!strcmp("vkDbgStringCallback", name))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600278 return (void *) StringCallback;
Jon Ashburnc6aecd72015-05-26 13:56:43 -0600279 else if (!strcmp("vkDbgStdioCallback", name))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600280 return (void *) StdioCallback;
Jon Ashburnc6aecd72015-05-26 13:56:43 -0600281 else if (!strcmp("vkDbgBreakCallback", name))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600282 return (void *) BreakCallback;
283
284 return NULL;
285}