blob: 4054d4ed5b53efc62bf84c73cd1373f87dba3687 [file] [log] [blame]
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001/*
Jon Ashburn23d36b12016-02-02 17:47:28 -07002 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 * Copyright (C) 2015-2016 Google Inc.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06006 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06007 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060010 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011 * http://www.apache.org/licenses/LICENSE-2.0
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060012 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060013 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060018 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060019 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
Jon Ashburn23d36b12016-02-02 17:47:28 -070020 * Author: Jon Ashburn <jon@LunarG.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021 *
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060022 */
23
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -060024#define _GNU_SOURCE
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060025#include <stdio.h>
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060026#include <string.h>
27#include <stdlib.h>
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060028#include <inttypes.h>
Tony Barbour1d825c72015-06-18 16:29:32 -060029#ifndef WIN32
Courtney Goeltzenleuchter03663d02015-07-22 11:01:53 -060030#include <signal.h>
31#else
Tony Barbour1d825c72015-06-18 16:29:32 -060032#endif
Jon Ashburn480a50a2015-08-28 14:58:46 -070033#include "vk_loader_platform.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060034#include "debug_report.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070035#include "vulkan/vk_layer.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060036
Jon Ashburn23d36b12016-02-02 17:47:28 -070037typedef void(VKAPI_PTR *PFN_stringCallback)(char *message);
Courtney Goeltzenleuchter7dcc6a72015-06-11 16:01:11 -060038
Jon Ashburn5c042ea2015-08-04 11:14:18 -060039static const VkExtensionProperties debug_report_extension_info = {
Jon Ashburn23d36b12016-02-02 17:47:28 -070040 .extensionName = VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
41 .specVersion = VK_EXT_DEBUG_REPORT_SPEC_VERSION,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060042};
43
44void debug_report_add_instance_extensions(
Jon Ashburn23d36b12016-02-02 17:47:28 -070045 const struct loader_instance *inst,
46 struct loader_extension_list *ext_list) {
Jon Ashburne39a4f82015-08-28 13:38:21 -060047 loader_add_to_ext_list(inst, ext_list, 1, &debug_report_extension_info);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060048}
49
Jon Ashburn23d36b12016-02-02 17:47:28 -070050void debug_report_create_instance(struct loader_instance *ptr_instance,
51 const VkInstanceCreateInfo *pCreateInfo) {
Mark Young35159af2016-09-07 08:50:32 -060052 ptr_instance->enabled_known_extensions.ext_debug_report = 0;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060053
Jon Ashburnf19916e2016-01-11 13:12:43 -070054 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -070055 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
56 VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Mark Young35159af2016-09-07 08:50:32 -060057 ptr_instance->enabled_known_extensions.ext_debug_report = 1;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060058 return;
59 }
60 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060061}
62
Jon Ashburn23d36b12016-02-02 17:47:28 -070063VkResult
64util_CreateDebugReportCallback(struct loader_instance *inst,
65 VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
66 const VkAllocationCallbacks *pAllocator,
67 VkDebugReportCallbackEXT callback) {
Mark Young7e4da972016-08-25 14:54:58 -060068 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
69
Mark Young0ad83132016-06-30 13:02:42 -060070#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
71 {
72#else
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -070073 if (pAllocator != NULL) {
Mark Young7e4da972016-08-25 14:54:58 -060074 pNewDbgFuncNode =
75 (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(
76 pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
77 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -070078 } else {
Mark Young0ad83132016-06-30 13:02:42 -060079#endif
Mark Young7e4da972016-08-25 14:54:58 -060080 pNewDbgFuncNode =
81 (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(
82 inst, sizeof(VkLayerDbgFunctionNode),
83 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -070084 }
Mark Young7e4da972016-08-25 14:54:58 -060085 if (!pNewDbgFuncNode) {
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -070086 return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young7e4da972016-08-25 14:54:58 -060087 }
88 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -070089
90 pNewDbgFuncNode->msgCallback = callback;
91 pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
92 pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
93 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
94 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
95 inst->DbgFunctionHead = pNewDbgFuncNode;
96
97 return VK_SUCCESS;
98}
99
Mark Young35159af2016-09-07 08:50:32 -0600100static VKAPI_ATTR VkResult VKAPI_CALL debug_report_CreateDebugReportCallbackEXT(
101 VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
102 const VkAllocationCallbacks *pAllocator,
103 VkDebugReportCallbackEXT *pCallback) {
Jon Ashburne0e64572015-09-30 12:56:42 -0600104 struct loader_instance *inst = loader_get_instance(instance);
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600105 loader_platform_thread_lock_mutex(&loader_lock);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700106 VkResult result = inst->disp->CreateDebugReportCallbackEXT(
107 instance, pCreateInfo, pAllocator, pCallback);
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600108 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600109 return result;
110}
111
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700112// Utility function to handle reporting
Jon Ashburn23d36b12016-02-02 17:47:28 -0700113VkBool32 util_DebugReportMessage(const struct loader_instance *inst,
114 VkFlags msgFlags,
115 VkDebugReportObjectTypeEXT objectType,
116 uint64_t srcObject, size_t location,
117 int32_t msgCode, const char *pLayerPrefix,
118 const char *pMsg) {
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700119 VkBool32 bail = false;
120 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
121 while (pTrav) {
122 if (pTrav->msgFlags & msgFlags) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700123 if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location,
124 msgCode, pLayerPrefix, pMsg,
125 pTrav->pUserData)) {
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700126 bail = true;
127 }
128 }
129 pTrav = pTrav->pNext;
130 }
131
132 return bail;
133}
134
Jon Ashburn23d36b12016-02-02 17:47:28 -0700135void util_DestroyDebugReportCallback(struct loader_instance *inst,
136 VkDebugReportCallbackEXT callback,
137 const VkAllocationCallbacks *pAllocator) {
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700138 VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
139 VkLayerDbgFunctionNode *pPrev = pTrav;
140
141 while (pTrav) {
142 if (pTrav->msgCallback == callback) {
143 pPrev->pNext = pTrav->pNext;
144 if (inst->DbgFunctionHead == pTrav)
145 inst->DbgFunctionHead = pTrav->pNext;
Mark Young0ad83132016-06-30 13:02:42 -0600146#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
147 {
148#else
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700149 if (pAllocator != NULL) {
150 pAllocator->pfnFree(pAllocator->pUserData, pTrav);
151 } else {
Mark Young0ad83132016-06-30 13:02:42 -0600152#endif
153 loader_instance_heap_free(inst, pTrav);
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700154 }
155 break;
156 }
157 pPrev = pTrav;
158 pTrav = pTrav->pNext;
159 }
160}
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700161
Ian Elliottad6300f2016-03-31 10:48:19 -0600162// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
163// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
164// then allocates array that can hold that many structs, as well as that many
165// VkDebugReportCallbackEXT handles. It then copies each
166// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Jon Ashburncc407a22016-04-15 09:25:03 -0600167VkResult util_CopyDebugReportCreateInfos(
168 const void *pChain, const VkAllocationCallbacks *pAllocator,
169 uint32_t *num_callbacks, VkDebugReportCallbackCreateInfoEXT **infos,
170 VkDebugReportCallbackEXT **callbacks) {
Ian Elliottad6300f2016-03-31 10:48:19 -0600171 uint32_t n = *num_callbacks = 0;
Mark Young0ad83132016-06-30 13:02:42 -0600172 VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
173 VkDebugReportCallbackEXT *pCallbacks = NULL;
Ian Elliottad6300f2016-03-31 10:48:19 -0600174
175 // NOTE: The loader is not using pAllocator, and so this function doesn't
176 // either.
177
178 const void *pNext = pChain;
179 while (pNext) {
180 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
181 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType ==
182 VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
183 n++;
184 }
185 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
186 }
187 if (n == 0) {
188 return VK_SUCCESS;
189 }
190
Mark Young0ad83132016-06-30 13:02:42 -0600191// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
192#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
193 {
194#else
195 if (pAllocator != NULL) {
196 pInfos = *infos =
197 ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
198 pAllocator->pUserData,
199 n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
200 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
201 } else {
202#endif
203 pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(
Jon Ashburncc407a22016-04-15 09:25:03 -0600204 n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
Mark Young0ad83132016-06-30 13:02:42 -0600205 }
Ian Elliottad6300f2016-03-31 10:48:19 -0600206 if (!pInfos) {
207 return VK_ERROR_OUT_OF_HOST_MEMORY;
208 }
Mark Young0ad83132016-06-30 13:02:42 -0600209// 3rd, allocate memory for a unique handle for each callback:
210#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
211 {
212#else
213 if (pAllocator != NULL) {
214 pCallbacks = *callbacks =
215 ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
216 pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT),
217 sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
218 } else {
219#endif
220 pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(
221 n * sizeof(VkDebugReportCallbackEXT)));
222 }
Ian Elliottad6300f2016-03-31 10:48:19 -0600223 if (!pCallbacks) {
224 free(pInfos);
225 return VK_ERROR_OUT_OF_HOST_MEMORY;
226 }
227 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
228 // vkDestroyInstance, and assign a unique handle to each callback (just
229 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
230 pNext = pChain;
231 while (pNext) {
232 if (((VkInstanceCreateInfo *)pNext)->sType ==
233 VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
Jon Ashburncc407a22016-04-15 09:25:03 -0600234 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
Ian Elliottad6300f2016-03-31 10:48:19 -0600235 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
236 }
237 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
238 }
239
240 *num_callbacks = n;
241 return VK_SUCCESS;
242}
243
244void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator,
245 VkDebugReportCallbackCreateInfoEXT *infos,
Jon Ashburncc407a22016-04-15 09:25:03 -0600246 VkDebugReportCallbackEXT *callbacks) {
Ian Elliottad6300f2016-03-31 10:48:19 -0600247 free(infos);
248 free(callbacks);
249}
250
Jon Ashburncc407a22016-04-15 09:25:03 -0600251VkResult util_CreateDebugReportCallbacks(
252 struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
253 uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
254 VkDebugReportCallbackEXT *callbacks) {
Jamie Madill2b6b8d52016-04-04 15:09:51 -0400255 VkResult rtn = VK_SUCCESS;
Jon Ashburncc407a22016-04-15 09:25:03 -0600256 for (uint32_t i = 0; i < num_callbacks; i++) {
257 rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator,
Ian Elliottad6300f2016-03-31 10:48:19 -0600258 callbacks[i]);
259 if (rtn != VK_SUCCESS) {
Jon Ashburncc407a22016-04-15 09:25:03 -0600260 for (uint32_t j = 0; j < i; j++) {
261 util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
Ian Elliottad6300f2016-03-31 10:48:19 -0600262 }
263 return rtn;
264 }
265 }
266 return rtn;
267}
268
269void util_DestroyDebugReportCallbacks(struct loader_instance *inst,
270 const VkAllocationCallbacks *pAllocator,
271 uint32_t num_callbacks,
Jon Ashburncc407a22016-04-15 09:25:03 -0600272 VkDebugReportCallbackEXT *callbacks) {
273 for (uint32_t i = 0; i < num_callbacks; i++) {
274 util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
Ian Elliottad6300f2016-03-31 10:48:19 -0600275 }
276}
277
Jon Ashburn23d36b12016-02-02 17:47:28 -0700278static VKAPI_ATTR void VKAPI_CALL
Mark Young35159af2016-09-07 08:50:32 -0600279debug_report_DestroyDebugReportCallbackEXT(
280 VkInstance instance, VkDebugReportCallbackEXT callback,
281 const VkAllocationCallbacks *pAllocator) {
Jon Ashburne0e64572015-09-30 12:56:42 -0600282 struct loader_instance *inst = loader_get_instance(instance);
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600283 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600284
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700285 inst->disp->DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600286
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700287 util_DestroyDebugReportCallback(inst, callback, pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600288
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600289 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600290}
291
Mark Young35159af2016-09-07 08:50:32 -0600292static VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700293 VkInstance instance, VkDebugReportFlagsEXT flags,
294 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
295 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700296 struct loader_instance *inst = loader_get_instance(instance);
297
Jon Ashburn23d36b12016-02-02 17:47:28 -0700298 inst->disp->DebugReportMessageEXT(instance, flags, objType, object,
299 location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700300}
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600301
302/*
303 * This is the instance chain terminator function
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700304 * for CreateDebugReportCallback
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600305 */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600306
Jon Ashburn1530c342016-02-26 13:14:27 -0700307VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallback(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700308 VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
309 const VkAllocationCallbacks *pAllocator,
310 VkDebugReportCallbackEXT *pCallback) {
Mark Young9b0636f2016-10-13 10:51:14 -0600311 VkDebugReportCallbackEXT *icd_info = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600312 const struct loader_icd *icd;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700313 struct loader_instance *inst = (struct loader_instance *)instance;
Karl Schultz2558bd32016-02-24 14:39:39 -0700314 VkResult res = VK_SUCCESS;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600315 uint32_t storage_idx;
Mark Young7e4da972016-08-25 14:54:58 -0600316 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600317
Mark Young0ad83132016-06-30 13:02:42 -0600318#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
319 {
320#else
321 if (pAllocator != NULL) {
322 icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
323 pAllocator->pUserData,
324 inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
325 sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
326 memset(icd_info, 0,
327 inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
328 } else {
329#endif
330 icd_info =
331 calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
332 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600333 if (!icd_info) {
Mark Young9b0636f2016-10-13 10:51:14 -0600334 res = VK_ERROR_OUT_OF_HOST_MEMORY;
335 goto out;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600336 }
337
338 storage_idx = 0;
339 for (icd = inst->icds; icd; icd = icd->next) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700340 if (!icd->CreateDebugReportCallbackEXT) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600341 continue;
342 }
343
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700344 res = icd->CreateDebugReportCallbackEXT(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700345 icd->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600346
347 if (res != VK_SUCCESS) {
Mark Young9b0636f2016-10-13 10:51:14 -0600348 goto out;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600349 }
350 storage_idx++;
351 }
352
Mark Young7e4da972016-08-25 14:54:58 -0600353 // Setup the debug report callback in the terminator since a layer may want
354 // to grab the information itself (RenderDoc) and then return back to the
355 // user callback a sub-set of the messages.
356#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
357 if (pAllocator != NULL) {
358 pNewDbgFuncNode =
359 (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(
360 pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
361 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
362 } else {
363#else
364 {
365#endif
366 pNewDbgFuncNode =
367 (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(
368 inst, sizeof(VkLayerDbgFunctionNode),
369 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
370 }
371 if (!pNewDbgFuncNode) {
Mark Young9b0636f2016-10-13 10:51:14 -0600372 res = VK_ERROR_OUT_OF_HOST_MEMORY;
373 goto out;
Mark Young7e4da972016-08-25 14:54:58 -0600374 }
375 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
376
Mark Young7e4da972016-08-25 14:54:58 -0600377 pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
378 pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
379 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
380 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
381 inst->DbgFunctionHead = pNewDbgFuncNode;
382
Mark Young9b0636f2016-10-13 10:51:14 -0600383 *(VkDebugReportCallbackEXT **)pCallback = icd_info;
384 pNewDbgFuncNode->msgCallback = *pCallback;
385
386out:
387
388 // Roll back on errors
Mark Youngd82497d2016-10-14 14:18:56 -0600389 if (VK_SUCCESS != res) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600390 storage_idx = 0;
391 for (icd = inst->icds; icd; icd = icd->next) {
Mark Younga26d47c2016-05-04 16:44:10 -0600392 if (NULL == icd->DestroyDebugReportCallbackEXT) {
393 continue;
394 }
395
Chia-I Wue2fc5522015-10-26 20:04:44 +0800396 if (icd_info[storage_idx]) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700397 icd->DestroyDebugReportCallbackEXT(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700398 icd->instance, icd_info[storage_idx], pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600399 }
400 storage_idx++;
401 }
402
Mark Young9b0636f2016-10-13 10:51:14 -0600403#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
404 {
405#else
406 if (pAllocator != NULL) {
407 if (NULL != pNewDbgFuncNode) {
408 pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
409 }
410 if (NULL != icd_info) {
411 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
412 }
413 } else {
414#endif
415 if (NULL != pNewDbgFuncNode) {
416 free(pNewDbgFuncNode);
417 }
418 if (NULL != icd_info) {
419 free(icd_info);
420 }
421 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600422 }
423
Mark Youngd82497d2016-10-14 14:18:56 -0600424 return res;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600425}
426
427/*
428 * This is the instance chain terminator function
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700429 * for DestroyDebugReportCallback
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600430 */
Mark Young0ad83132016-06-30 13:02:42 -0600431VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallback(
432 VkInstance instance, VkDebugReportCallbackEXT callback,
433 const VkAllocationCallbacks *pAllocator) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600434 uint32_t storage_idx;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700435 VkDebugReportCallbackEXT *icd_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600436 const struct loader_icd *icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600437
Jon Ashburn23d36b12016-02-02 17:47:28 -0700438 struct loader_instance *inst = (struct loader_instance *)instance;
439 icd_info = *(VkDebugReportCallbackEXT **)&callback;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600440 storage_idx = 0;
441 for (icd = inst->icds; icd; icd = icd->next) {
Mark Younga26d47c2016-05-04 16:44:10 -0600442 if (NULL == icd->DestroyDebugReportCallbackEXT) {
443 continue;
444 }
445
Chia-I Wue2fc5522015-10-26 20:04:44 +0800446 if (icd_info[storage_idx]) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700447 icd->DestroyDebugReportCallbackEXT(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700448 icd->instance, icd_info[storage_idx], pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600449 }
450 storage_idx++;
451 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600452}
453
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700454/*
455 * This is the instance chain terminator function
456 * for DebugReportMessage
457 */
Mark Young0ad83132016-06-30 13:02:42 -0600458VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessage(
459 VkInstance instance, VkDebugReportFlagsEXT flags,
460 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
461 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700462 const struct loader_icd *icd;
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700463
Jon Ashburn23d36b12016-02-02 17:47:28 -0700464 struct loader_instance *inst = (struct loader_instance *)instance;
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700465
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700466 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700467 for (icd = inst->icds; icd; icd = icd->next) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700468 if (icd->DebugReportMessageEXT != NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700469 icd->DebugReportMessageEXT(icd->instance, flags, objType, object,
470 location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700471 }
472 }
473
474 /*
475 * Now that all ICDs have seen the message, call the necessary callbacks.
Jon Ashburn23d36b12016-02-02 17:47:28 -0700476 * Ignoring "bail" return value as there is nothing to bail from at this
477 * point.
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700478 */
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700479
Jon Ashburn23d36b12016-02-02 17:47:28 -0700480 util_DebugReportMessage(inst, flags, objType, object, location, msgCode,
481 pLayerPrefix, pMsg);
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700482
483 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700484}
485
Jon Ashburn23d36b12016-02-02 17:47:28 -0700486bool debug_report_instance_gpa(struct loader_instance *ptr_instance,
487 const char *name, void **addr) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -0700488 // debug_report is currently advertised to be supported by the loader,
489 // so always return the entry points if name matches and it's enabled
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600490 *addr = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600491
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700492 if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
Mark Young35159af2016-09-07 08:50:32 -0600493 *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1)
494 ? (void *)debug_report_CreateDebugReportCallbackEXT
Jon Ashburn23d36b12016-02-02 17:47:28 -0700495 : NULL;
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600496 return true;
497 }
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700498 if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
Mark Young35159af2016-09-07 08:50:32 -0600499 *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1)
500 ? (void *)debug_report_DestroyDebugReportCallbackEXT
Jon Ashburn23d36b12016-02-02 17:47:28 -0700501 : NULL;
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600502 return true;
503 }
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700504 if (!strcmp("vkDebugReportMessageEXT", name)) {
Mark Young35159af2016-09-07 08:50:32 -0600505 *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1)
506 ? (void *)debug_report_DebugReportMessageEXT
Jon Ashburn23d36b12016-02-02 17:47:28 -0700507 : NULL;
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700508 return true;
509 }
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600510 return false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600511}