blob: 15233bc217a2f31ba05437c02d6738db42b94cab [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));
Mark Young0fea6922016-11-21 16:20:06 -0700218 if (!pCallbacks) {
219 pAllocator->pfnFree(pAllocator->pUserData, pInfos);
220 return VK_ERROR_OUT_OF_HOST_MEMORY;
221 }
Mark Young0ad83132016-06-30 13:02:42 -0600222 } else {
223#endif
224 pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(
225 n * sizeof(VkDebugReportCallbackEXT)));
Mark Young0fea6922016-11-21 16:20:06 -0700226 if (!pCallbacks) {
227 free(pInfos);
228 return VK_ERROR_OUT_OF_HOST_MEMORY;
229 }
Ian Elliottad6300f2016-03-31 10:48:19 -0600230 }
231 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
232 // vkDestroyInstance, and assign a unique handle to each callback (just
233 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
234 pNext = pChain;
235 while (pNext) {
236 if (((VkInstanceCreateInfo *)pNext)->sType ==
237 VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
Jon Ashburncc407a22016-04-15 09:25:03 -0600238 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
Karl Schultz94971292016-11-19 09:02:27 -0700239 *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
Ian Elliottad6300f2016-03-31 10:48:19 -0600240 }
241 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
242 }
243
244 *num_callbacks = n;
245 return VK_SUCCESS;
246}
247
248void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator,
249 VkDebugReportCallbackCreateInfoEXT *infos,
Jon Ashburncc407a22016-04-15 09:25:03 -0600250 VkDebugReportCallbackEXT *callbacks) {
Mark Young0fea6922016-11-21 16:20:06 -0700251#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
252 {
253#else
254 if (pAllocator != NULL) {
255 pAllocator->pfnFree(pAllocator->pUserData, infos);
256 pAllocator->pfnFree(pAllocator->pUserData, callbacks);
257 } else {
258#endif
259 free(infos);
260 free(callbacks);
261 }
Ian Elliottad6300f2016-03-31 10:48:19 -0600262}
263
Jon Ashburncc407a22016-04-15 09:25:03 -0600264VkResult util_CreateDebugReportCallbacks(
265 struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
266 uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
267 VkDebugReportCallbackEXT *callbacks) {
Jamie Madill2b6b8d52016-04-04 15:09:51 -0400268 VkResult rtn = VK_SUCCESS;
Jon Ashburncc407a22016-04-15 09:25:03 -0600269 for (uint32_t i = 0; i < num_callbacks; i++) {
270 rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator,
Ian Elliottad6300f2016-03-31 10:48:19 -0600271 callbacks[i]);
272 if (rtn != VK_SUCCESS) {
Jon Ashburncc407a22016-04-15 09:25:03 -0600273 for (uint32_t j = 0; j < i; j++) {
274 util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
Ian Elliottad6300f2016-03-31 10:48:19 -0600275 }
276 return rtn;
277 }
278 }
279 return rtn;
280}
281
282void util_DestroyDebugReportCallbacks(struct loader_instance *inst,
283 const VkAllocationCallbacks *pAllocator,
284 uint32_t num_callbacks,
Jon Ashburncc407a22016-04-15 09:25:03 -0600285 VkDebugReportCallbackEXT *callbacks) {
286 for (uint32_t i = 0; i < num_callbacks; i++) {
287 util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
Ian Elliottad6300f2016-03-31 10:48:19 -0600288 }
289}
290
Jon Ashburn23d36b12016-02-02 17:47:28 -0700291static VKAPI_ATTR void VKAPI_CALL
Mark Young35159af2016-09-07 08:50:32 -0600292debug_report_DestroyDebugReportCallbackEXT(
293 VkInstance instance, VkDebugReportCallbackEXT callback,
294 const VkAllocationCallbacks *pAllocator) {
Jon Ashburne0e64572015-09-30 12:56:42 -0600295 struct loader_instance *inst = loader_get_instance(instance);
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600296 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600297
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700298 inst->disp->DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600299
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700300 util_DestroyDebugReportCallback(inst, callback, pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600301
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600302 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600303}
304
Mark Young35159af2016-09-07 08:50:32 -0600305static VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700306 VkInstance instance, VkDebugReportFlagsEXT flags,
307 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
308 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700309 struct loader_instance *inst = loader_get_instance(instance);
310
Jon Ashburn23d36b12016-02-02 17:47:28 -0700311 inst->disp->DebugReportMessageEXT(instance, flags, objType, object,
312 location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700313}
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600314
315/*
316 * This is the instance chain terminator function
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700317 * for CreateDebugReportCallback
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600318 */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -0600319
Jon Ashburn1530c342016-02-26 13:14:27 -0700320VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallback(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700321 VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
322 const VkAllocationCallbacks *pAllocator,
323 VkDebugReportCallbackEXT *pCallback) {
Mark Young9b0636f2016-10-13 10:51:14 -0600324 VkDebugReportCallbackEXT *icd_info = NULL;
Mark Young0153e0b2016-11-03 14:27:13 -0600325 const struct loader_icd_term *icd_term;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700326 struct loader_instance *inst = (struct loader_instance *)instance;
Karl Schultz2558bd32016-02-24 14:39:39 -0700327 VkResult res = VK_SUCCESS;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600328 uint32_t storage_idx;
Mark Young7e4da972016-08-25 14:54:58 -0600329 VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600330
Mark Young0ad83132016-06-30 13:02:42 -0600331#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
332 {
333#else
334 if (pAllocator != NULL) {
335 icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
336 pAllocator->pUserData,
337 inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
338 sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
Karl Schultze2ef9e62017-01-13 14:01:35 -0700339 if (icd_info) {
340 memset(icd_info, 0,
341 inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
342 }
Mark Young0ad83132016-06-30 13:02:42 -0600343 } else {
344#endif
345 icd_info =
346 calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
347 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600348 if (!icd_info) {
Mark Young9b0636f2016-10-13 10:51:14 -0600349 res = VK_ERROR_OUT_OF_HOST_MEMORY;
350 goto out;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600351 }
352
353 storage_idx = 0;
Mark Young0153e0b2016-11-03 14:27:13 -0600354 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
355 if (!icd_term->CreateDebugReportCallbackEXT) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600356 continue;
357 }
358
Mark Young0153e0b2016-11-03 14:27:13 -0600359 res = icd_term->CreateDebugReportCallbackEXT(icd_term->instance,
360 pCreateInfo, pAllocator,
361 &icd_info[storage_idx]);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600362
363 if (res != VK_SUCCESS) {
Mark Young9b0636f2016-10-13 10:51:14 -0600364 goto out;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600365 }
366 storage_idx++;
367 }
368
Mark Young7e4da972016-08-25 14:54:58 -0600369 // Setup the debug report callback in the terminator since a layer may want
370 // to grab the information itself (RenderDoc) and then return back to the
371 // user callback a sub-set of the messages.
372#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
373 if (pAllocator != NULL) {
374 pNewDbgFuncNode =
375 (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(
376 pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
377 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
378 } else {
379#else
380 {
381#endif
382 pNewDbgFuncNode =
383 (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(
384 inst, sizeof(VkLayerDbgFunctionNode),
385 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
386 }
387 if (!pNewDbgFuncNode) {
Mark Young9b0636f2016-10-13 10:51:14 -0600388 res = VK_ERROR_OUT_OF_HOST_MEMORY;
389 goto out;
Mark Young7e4da972016-08-25 14:54:58 -0600390 }
391 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
392
Mark Young7e4da972016-08-25 14:54:58 -0600393 pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
394 pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
395 pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
396 pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
397 inst->DbgFunctionHead = pNewDbgFuncNode;
398
Mark Young9b0636f2016-10-13 10:51:14 -0600399 *(VkDebugReportCallbackEXT **)pCallback = icd_info;
400 pNewDbgFuncNode->msgCallback = *pCallback;
401
402out:
403
404 // Roll back on errors
Mark Youngd82497d2016-10-14 14:18:56 -0600405 if (VK_SUCCESS != res) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600406 storage_idx = 0;
Mark Young0153e0b2016-11-03 14:27:13 -0600407 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
408 if (NULL == icd_term->DestroyDebugReportCallbackEXT) {
Mark Younga26d47c2016-05-04 16:44:10 -0600409 continue;
410 }
411
Karl Schultze2ef9e62017-01-13 14:01:35 -0700412 if (icd_info && icd_info[storage_idx]) {
Mark Young0153e0b2016-11-03 14:27:13 -0600413 icd_term->DestroyDebugReportCallbackEXT(
414 icd_term->instance, icd_info[storage_idx], pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600415 }
416 storage_idx++;
417 }
418
Mark Young9b0636f2016-10-13 10:51:14 -0600419#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
420 {
421#else
422 if (pAllocator != NULL) {
423 if (NULL != pNewDbgFuncNode) {
424 pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
425 }
426 if (NULL != icd_info) {
427 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
428 }
429 } else {
430#endif
431 if (NULL != pNewDbgFuncNode) {
432 free(pNewDbgFuncNode);
433 }
434 if (NULL != icd_info) {
435 free(icd_info);
436 }
437 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600438 }
439
Mark Youngd82497d2016-10-14 14:18:56 -0600440 return res;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600441}
442
443/*
444 * This is the instance chain terminator function
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700445 * for DestroyDebugReportCallback
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600446 */
Mark Young0ad83132016-06-30 13:02:42 -0600447VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallback(
448 VkInstance instance, VkDebugReportCallbackEXT callback,
449 const VkAllocationCallbacks *pAllocator) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600450 uint32_t storage_idx;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700451 VkDebugReportCallbackEXT *icd_info;
Mark Young0153e0b2016-11-03 14:27:13 -0600452 const struct loader_icd_term *icd_term;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600453
Jon Ashburn23d36b12016-02-02 17:47:28 -0700454 struct loader_instance *inst = (struct loader_instance *)instance;
455 icd_info = *(VkDebugReportCallbackEXT **)&callback;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600456 storage_idx = 0;
Mark Young0153e0b2016-11-03 14:27:13 -0600457 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
458 if (NULL == icd_term->DestroyDebugReportCallbackEXT) {
Mark Younga26d47c2016-05-04 16:44:10 -0600459 continue;
460 }
461
Chia-I Wue2fc5522015-10-26 20:04:44 +0800462 if (icd_info[storage_idx]) {
Mark Young0153e0b2016-11-03 14:27:13 -0600463 icd_term->DestroyDebugReportCallbackEXT(
464 icd_term->instance, icd_info[storage_idx], pAllocator);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600465 }
466 storage_idx++;
467 }
Mark Young0fea6922016-11-21 16:20:06 -0700468
469#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
470 {
471#else
472 if (pAllocator != NULL) {
473 pAllocator->pfnFree(pAllocator->pUserData, icd_info);
474 } else {
475#endif
476 free(icd_info);
477 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600478}
479
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700480/*
481 * This is the instance chain terminator function
482 * for DebugReportMessage
483 */
Mark Young0ad83132016-06-30 13:02:42 -0600484VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessage(
485 VkInstance instance, VkDebugReportFlagsEXT flags,
486 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
487 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Young0153e0b2016-11-03 14:27:13 -0600488 const struct loader_icd_term *icd_term;
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700489
Jon Ashburn23d36b12016-02-02 17:47:28 -0700490 struct loader_instance *inst = (struct loader_instance *)instance;
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700491
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700492 loader_platform_thread_lock_mutex(&loader_lock);
Mark Young0153e0b2016-11-03 14:27:13 -0600493 for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
494 if (icd_term->DebugReportMessageEXT != NULL) {
495 icd_term->DebugReportMessageEXT(icd_term->instance, flags, objType,
496 object, location, msgCode,
497 pLayerPrefix, pMsg);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700498 }
499 }
500
501 /*
502 * Now that all ICDs have seen the message, call the necessary callbacks.
Jon Ashburn23d36b12016-02-02 17:47:28 -0700503 * Ignoring "bail" return value as there is nothing to bail from at this
504 * point.
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700505 */
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700506
Jon Ashburn23d36b12016-02-02 17:47:28 -0700507 util_DebugReportMessage(inst, flags, objType, object, location, msgCode,
508 pLayerPrefix, pMsg);
Courtney Goeltzenleuchter82887272015-12-02 15:29:33 -0700509
510 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700511}
512
Jon Ashburn23d36b12016-02-02 17:47:28 -0700513bool debug_report_instance_gpa(struct loader_instance *ptr_instance,
514 const char *name, void **addr) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -0700515 // debug_report is currently advertised to be supported by the loader,
516 // so always return the entry points if name matches and it's enabled
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600517 *addr = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600518
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700519 if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
Mark Young35159af2016-09-07 08:50:32 -0600520 *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1)
521 ? (void *)debug_report_CreateDebugReportCallbackEXT
Jon Ashburn23d36b12016-02-02 17:47:28 -0700522 : NULL;
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600523 return true;
524 }
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700525 if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
Mark Young35159af2016-09-07 08:50:32 -0600526 *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1)
527 ? (void *)debug_report_DestroyDebugReportCallbackEXT
Jon Ashburn23d36b12016-02-02 17:47:28 -0700528 : NULL;
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600529 return true;
530 }
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700531 if (!strcmp("vkDebugReportMessageEXT", name)) {
Mark Young35159af2016-09-07 08:50:32 -0600532 *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1)
533 ? (void *)debug_report_DebugReportMessageEXT
Jon Ashburn23d36b12016-02-02 17:47:28 -0700534 : NULL;
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700535 return true;
536 }
Jon Ashburnf7a48db2015-10-01 12:03:17 -0600537 return false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600538}