blob: cab771795e14c1cc7fa880fd279c6ca55996fb9d [file] [log] [blame]
Tobin Ehlisacab8882014-11-14 13:01:02 -07001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Tobin Ehlisacab8882014-11-14 13:01:02 -07003 *
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
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060025#include "vk_layer.h"
Courtney Goeltzenleuchter8b0e68d2015-07-05 22:13:43 -060026#include "vk_layer_extension_utils.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060027#include "vk_enum_string_helper.h"
Mark Lobodzinski14305ad2015-06-23 11:35:12 -060028
Tobin Ehlis3c26a542014-11-18 11:28:33 -070029// Object Tracker ERROR codes
30typedef enum _OBJECT_TRACK_ERROR
31{
Chia-I Wub1466182015-01-05 14:33:42 +080032 OBJTRACK_NONE, // Used for INFO & other non-error messages
33 OBJTRACK_UNKNOWN_OBJECT, // Updating uses of object that's not in global object list
34 OBJTRACK_INTERNAL_ERROR, // Bug with data tracking within the layer
35 OBJTRACK_DESTROY_OBJECT_FAILED, // Couldn't find object to be destroyed
Mark Lobodzinski7a3d5ff2015-05-05 18:24:45 -050036 OBJTRACK_OBJECT_TYPE_MISMATCH, // Object did not match corresponding Object Type
Chia-I Wub1466182015-01-05 14:33:42 +080037 OBJTRACK_OBJECT_LEAK, // OBJECT was not correctly freed/destroyed
38 OBJTRACK_OBJCOUNT_MAX_EXCEEDED, // Request for Object data in excess of max obj count
Tobin Ehlis235c20e2015-01-16 08:56:30 -070039 OBJTRACK_INVALID_FENCE, // Requested status of unsubmitted fence object
Tobin Ehlis586aa012015-06-08 17:36:28 -060040 OBJTRACK_INVALID_OBJECT, // Object used that has never been created
Tobin Ehlis3c26a542014-11-18 11:28:33 -070041} OBJECT_TRACK_ERROR;
42
Tobin Ehlis235c20e2015-01-16 08:56:30 -070043// Object Status -- used to track state of individual objects
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -050044typedef VkFlags ObjectStatusFlags;
45typedef enum _ObjectStatusFlagBits
Tobin Ehlis235c20e2015-01-16 08:56:30 -070046{
Mark Lobodzinski01552702015-02-03 10:06:31 -060047 OBJSTATUS_NONE = 0x00000000, // No status is set
48 OBJSTATUS_FENCE_IS_SUBMITTED = 0x00000001, // Fence has been submitted
49 OBJSTATUS_VIEWPORT_BOUND = 0x00000002, // Viewport state object has been bound
50 OBJSTATUS_RASTER_BOUND = 0x00000004, // Viewport state object has been bound
51 OBJSTATUS_COLOR_BLEND_BOUND = 0x00000008, // Viewport state object has been bound
52 OBJSTATUS_DEPTH_STENCIL_BOUND = 0x00000010, // Viewport state object has been bound
Mark Lobodzinski4186e712015-02-03 11:52:26 -060053 OBJSTATUS_GPU_MEM_MAPPED = 0x00000020, // Memory object is currently mapped
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -050054} ObjectStatusFlagBits;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080055
Tobin Ehlisacab8882014-11-14 13:01:02 -070056typedef struct _OBJTRACK_NODE {
Mark Lobodzinski7d2d5ac2015-05-20 17:33:47 -050057 VkObject vkObj;
58 VkObjectType objType;
59 ObjectStatusFlags status;
Tobin Ehlisacab8882014-11-14 13:01:02 -070060} OBJTRACK_NODE;
Mark Lobodzinskie1d3f0c2015-02-09 10:20:53 -060061
Tobin Ehlisacab8882014-11-14 13:01:02 -070062// prototype for extension functions
Mark Lobodzinski14305ad2015-06-23 11:35:12 -060063uint64_t objTrackGetObjectCount(VkDevice device);
64VkResult objTrackGetObjects(VkDevice device, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
65uint64_t objTrackGetObjectsOfTypeCount(VkDevice, VkObjectType type);
66VkResult objTrackGetObjectsOfType(VkDevice, VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
Mark Lobodzinskie1d3f0c2015-02-09 10:20:53 -060067
Tobin Ehlis3c26a542014-11-18 11:28:33 -070068// Func ptr typedefs
Mark Lobodzinski14305ad2015-06-23 11:35:12 -060069typedef uint64_t (*OBJ_TRACK_GET_OBJECT_COUNT)(VkDevice);
70typedef VkResult (*OBJ_TRACK_GET_OBJECTS)(VkDevice, VkObjectType, uint64_t, OBJTRACK_NODE*);
71typedef uint64_t (*OBJ_TRACK_GET_OBJECTS_OF_TYPE_COUNT)(VkDevice, VkObjectType);
72typedef VkResult (*OBJ_TRACK_GET_OBJECTS_OF_TYPE)(VkDevice, VkObjectType, uint64_t, OBJTRACK_NODE*);
73
74typedef struct _layer_data {
75 debug_report_data *report_data;
76 //TODO: put instance data here
77 VkDbgMsgCallback logging_callback;
Courtney Goeltzenleuchter8b0e68d2015-07-05 22:13:43 -060078 bool wsi_lunarg_enabled;
79 bool objtrack_extensions_enabled;
Mark Lobodzinski14305ad2015-06-23 11:35:12 -060080} layer_data;
81
82static std::unordered_map<void*, layer_data *> layer_data_map;
83static device_table_map ObjectTracker_device_table_map;
84static instance_table_map ObjectTracker_instance_table_map;
85
86static long long unsigned int object_track_index = 0;
87static int objLockInitialized = 0;
88static loader_platform_thread_mutex objLock;
89
90// Objects stored in a global map w/ struct containing basic info
91unordered_map<VkObject, OBJTRACK_NODE*> objMap;
92
93#define NUM_OBJECT_TYPES (VK_NUM_OBJECT_TYPE + (VK_OBJECT_TYPE_SWAP_CHAIN_WSI - VK_OBJECT_TYPE_DISPLAY_WSI))
94
95static uint64_t numObjs[NUM_OBJECT_TYPES] = {0};
96static uint64_t numTotalObjs = 0;
97static VkPhysicalDeviceQueueProperties *queueInfo = NULL;
98static uint32_t queueCount = 0;
99
100template layer_data *get_my_data_ptr<layer_data>(
101 void *data_key, std::unordered_map<void *, layer_data *> &data_map);
102
103//
104// Internal Object Tracker Functions
105//
106
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600107static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
108{
Courtney Goeltzenleuchter8b0e68d2015-07-05 22:13:43 -0600109 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
110 my_device_data->wsi_lunarg_enabled = false;
111 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
112 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_WSI_LUNARG_EXTENSION_NAME) == 0)
113 my_device_data->wsi_lunarg_enabled = true;
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600114
Courtney Goeltzenleuchter8b0e68d2015-07-05 22:13:43 -0600115 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], "OBJTRACK_EXTENSIONS") == 0)
116 my_device_data->objtrack_extensions_enabled = true;
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600117 }
118}
119
120// Indicate device or instance dispatch table type
121typedef enum _DispTableType
122{
123 DISP_TBL_TYPE_INSTANCE,
124 DISP_TBL_TYPE_DEVICE,
125} DispTableType;
126
127debug_report_data *mdd(VkObject object)
128{
129 dispatch_key key = get_dispatch_key(object);
130 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600131 return my_data->report_data;
132}
133
134debug_report_data *mid(VkInstance object)
135{
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600136 dispatch_key key = get_dispatch_key(object);
137 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600138 return my_data->report_data;
139}
140
141// For each Queue's doubly linked-list of mem refs
142typedef struct _OT_MEM_INFO {
143 VkDeviceMemory mem;
144 struct _OT_MEM_INFO *pNextMI;
145 struct _OT_MEM_INFO *pPrevMI;
146
147} OT_MEM_INFO;
148
149// Track Queue information
150typedef struct _OT_QUEUE_INFO {
151 OT_MEM_INFO *pMemRefList;
152 struct _OT_QUEUE_INFO *pNextQI;
153 uint32_t queueNodeIndex;
154 VkQueue queue;
155 uint32_t refCount;
156} OT_QUEUE_INFO;
157
158// Global list of QueueInfo structures, one per queue
159static OT_QUEUE_INFO *g_pQueueInfo = NULL;
160
161// Convert an object type enum to an object type array index
162static uint32_t
163objTypeToIndex(
164 uint32_t objType)
165{
166 uint32_t index = objType;
167 if (objType > VK_OBJECT_TYPE_END_RANGE) {
168 // These come from vk_wsi_lunarg.h, rebase
169 index = (index -(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000)) + VK_OBJECT_TYPE_END_RANGE;
170 }
171 return index;
172}
173
174// Validate that object is in the object map
175static void
176validate_object(
177 const VkObject dispatchable_object,
178 const VkObject object)
179{
180 if (objMap.find(object) == objMap.end()) {
Tobin Ehlis3aa50502015-06-25 12:29:25 -0600181 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, object, 0, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600182 "Invalid Object %p", object);
183 }
184}
185
186// Validate that object parameter matches designated object type
187static void
188validateObjectType(
189 VkObject dispatchable_object,
190 const char *apiName,
191 VkObjectType objType,
192 VkObject object)
193{
194 if (objMap.find(object) != objMap.end()) {
195 OBJTRACK_NODE* pNode = objMap[object];
196 // Found our object, check type
197 if (strcmp(string_VkObjectType(pNode->objType), string_VkObjectType(objType)) != 0) {
198 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, objType, object, 0, OBJTRACK_OBJECT_TYPE_MISMATCH, "OBJTRACK",
199 "ERROR: Object Parameter Type %s does not match designated type %s", string_VkObjectType(pNode->objType), string_VkObjectType(objType));
200 }
201 }
202}
203
204// Add new queue to head of global queue list
205static void
206addQueueInfo(
207 uint32_t queueNodeIndex,
208 VkQueue queue)
209{
210 OT_QUEUE_INFO *pQueueInfo = new OT_QUEUE_INFO;
211
212 if (pQueueInfo != NULL) {
213 memset(pQueueInfo, 0, sizeof(OT_QUEUE_INFO));
214 pQueueInfo->queue = queue;
215 pQueueInfo->queueNodeIndex = queueNodeIndex;
216 pQueueInfo->pNextQI = g_pQueueInfo;
217 g_pQueueInfo = pQueueInfo;
218 }
219 else {
220 log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK",
221 "ERROR: VK_ERROR_OUT_OF_HOST_MEMORY -- could not allocate memory for Queue Information");
222 }
223}
224
225// Destroy memRef lists and free all memory
226static void
227destroyQueueMemRefLists(void)
228{
229 OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;
230 OT_QUEUE_INFO *pDelQueueInfo = NULL;
231 while (pQueueInfo != NULL) {
232 OT_MEM_INFO *pMemInfo = pQueueInfo->pMemRefList;
233 while (pMemInfo != NULL) {
234 OT_MEM_INFO *pDelMemInfo = pMemInfo;
235 pMemInfo = pMemInfo->pNextMI;
236 delete pDelMemInfo;
237 }
238 pDelQueueInfo = pQueueInfo;
239 pQueueInfo = pQueueInfo->pNextQI;
240 delete pDelQueueInfo;
241 }
242 g_pQueueInfo = pQueueInfo;
243}
244
245
246static void
247create_obj(
248 VkObject dispatchable_object,
249 VkObject vkObj,
250 VkObjectType objType)
251{
252 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_INFO_BIT, objType, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
253 "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkObjectType(objType),
254 reinterpret_cast<VkUintPtrLeast64>(vkObj));
255
256 OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;
257 pNewObjNode->vkObj = vkObj;
258 pNewObjNode->objType = objType;
259 pNewObjNode->status = OBJSTATUS_NONE;
260 objMap[vkObj] = pNewObjNode;
261 uint32_t objIndex = objTypeToIndex(objType);
262 numObjs[objIndex]++;
263 numTotalObjs++;
264}
265
266// Parse global list to find obj type, then remove obj from obj type list, finally
267// remove obj from global list
268static void
269destroy_obj(
270 VkObject dispatchable_object,
271 VkObject vkObj)
272{
273 if (objMap.find(vkObj) != objMap.end()) {
274 OBJTRACK_NODE* pNode = objMap[vkObj];
275 uint32_t objIndex = objTypeToIndex(pNode->objType);
276 assert(numTotalObjs > 0);
277 numTotalObjs--;
278 assert(numObjs[objIndex] > 0);
279 numObjs[objIndex]--;
280 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_INFO_BIT, pNode->objType, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
281 "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%lu total objs remain & %lu %s objs).",
282 string_VkObjectType(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj), numTotalObjs, numObjs[objIndex],
283 string_VkObjectType(pNode->objType));
284
285 delete pNode;
286 objMap.erase(vkObj);
287 } else {
288 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
289 "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
290 reinterpret_cast<VkUintPtrLeast64>(vkObj));
291 }
292}
293
294// Set selected flag state for an object node
295static void
296set_status(
297 VkObject dispatchable_object,
298 VkObject vkObj,
299 VkObjectType objType,
300 ObjectStatusFlags status_flag)
301{
302 if (vkObj != VK_NULL_HANDLE) {
303 if (objMap.find(vkObj) != objMap.end()) {
304 OBJTRACK_NODE* pNode = objMap[vkObj];
305 pNode->status |= status_flag;
306 return;
307 }
308 else {
309 // If we do not find it print an error
310 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
311 "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",
312 reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));
313 }
314 }
315}
316
317// Reset selected flag state for an object node
318static void
319reset_status(
320 VkObject dispatchable_object,
321 VkObject vkObj,
322 VkObjectType objType,
323 ObjectStatusFlags status_flag)
324{
325 if (objMap.find(vkObj) != objMap.end()) {
326 OBJTRACK_NODE* pNode = objMap[vkObj];
327 pNode->status &= ~status_flag;
328 return;
329 }
330 else {
331 // If we do not find it print an error
332 log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, objType, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
333 "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",
334 reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));
335 }
336}
337
338static void
339setGpuQueueInfoState(
Tony Barbour426b9052015-06-24 16:06:58 -0600340 uint32_t count,
341 void *pData)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600342{
Tony Barbour426b9052015-06-24 16:06:58 -0600343 queueCount = count;
344 queueInfo = (VkPhysicalDeviceQueueProperties*)realloc((void*)queueInfo, count * sizeof(VkPhysicalDeviceQueueProperties));
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600345 if (queueInfo != NULL) {
Tony Barbour426b9052015-06-24 16:06:58 -0600346 memcpy(queueInfo, pData, count * sizeof(VkPhysicalDeviceQueueProperties));
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600347 }
348}
349
350// Check Queue type flags for selected queue operations
351static void
352validateQueueFlags(
353 VkQueue queue,
354 const char *function)
355{
356 OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;
357 while ((pQueueInfo != NULL) && (pQueueInfo->queue != queue)) {
358 pQueueInfo = pQueueInfo->pNextQI;
359 }
360 if (pQueueInfo != NULL) {
361 if ((queueInfo != NULL) && (queueInfo[pQueueInfo->queueNodeIndex].queueFlags & VK_QUEUE_SPARSE_MEMMGR_BIT) == 0) {
362 log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
363 "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not set", function);
364 } else {
365 log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
366 "Attempting %s on a possibly non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not known", function);
367 }
368 }
369}
370
371// Check object status for selected flag state
Courtney Goeltzenleuchter1f41f542015-07-09 11:44:38 -0600372static VkBool32
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600373validate_status(
374 VkObject dispatchable_object,
375 VkObject vkObj,
376 VkObjectType objType,
377 ObjectStatusFlags status_mask,
378 ObjectStatusFlags status_flag,
379 VkFlags msg_flags,
380 OBJECT_TRACK_ERROR error_code,
381 const char *fail_msg)
382{
383 if (objMap.find(vkObj) != objMap.end()) {
384 OBJTRACK_NODE* pNode = objMap[vkObj];
385 if ((pNode->status & status_mask) != status_flag) {
386 char str[1024];
387 log_msg(mdd(dispatchable_object), msg_flags, pNode->objType, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
388 "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkObjectType(objType),
389 reinterpret_cast<VkUintPtrLeast64>(vkObj), fail_msg);
390 return VK_FALSE;
391 }
392 return VK_TRUE;
393 }
394 else {
395 // If we do not find it print an error
396 log_msg(mdd(dispatchable_object), msg_flags, (VkObjectType) 0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
397 "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",
398 reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));
399 return VK_FALSE;
400 }
401}
402
403#include "vk_dispatch_table_helper.h"
404static void
405initObjectTracker(
406 layer_data *my_data)
407{
408 uint32_t report_flags = 0;
409 uint32_t debug_action = 0;
410 FILE *log_output = NULL;
411 const char *option_str;
412 // initialize ObjectTracker options
413 report_flags = getLayerOptionFlags("ObjectTrackerReportFlags", 0);
414 getLayerOptionEnum("ObjectTrackerDebugAction", (uint32_t *) &debug_action);
415
416 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
417 {
418 option_str = getLayerOption("ObjectTrackerLogFilename");
419 if (option_str) {
420 log_output = fopen(option_str, "w");
421 }
422 if (log_output == NULL) {
423 log_output = stdout;
424 }
425
426 layer_create_msg_callback(my_data->report_data, report_flags, log_callback, (void *) log_output, &my_data->logging_callback);
427 }
428
429 if (!objLockInitialized)
430 {
431 // TODO/TBD: Need to delete this mutex sometime. How??? One
432 // suggestion is to call this during vkCreateInstance(), and then we
433 // can clean it up during vkDestroyInstance(). However, that requires
434 // that the layer have per-instance locks. We need to come back and
435 // address this soon.
436 loader_platform_thread_create_mutex(&objLock);
437 objLockInitialized = 1;
438 }
439}
440
441
442//
443// Non-auto-generated API functions called by generated code
444//
445
446VkResult
447explicit_CreateInstance(
448 const VkInstanceCreateInfo *pCreateInfo,
449 VkInstance * pInstance)
450{
451 loader_platform_thread_lock_mutex(&objLock);
452 VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, *pInstance);
453 VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pInstance);
454
455 if (result == VK_SUCCESS) {
456 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
457 my_data->report_data = debug_report_create_instance(
Courtney Goeltzenleuchter8b0e68d2015-07-05 22:13:43 -0600458 pInstanceTable,
459 *pInstance,
460 pCreateInfo->extensionCount,
461 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600462
463 initObjectTracker(my_data);
Tobin Ehlis86b52ec2015-06-30 14:31:50 -0600464 create_obj(*pInstance, *pInstance, VK_OBJECT_TYPE_INSTANCE);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600465 }
466 loader_platform_thread_unlock_mutex(&objLock);
467 return result;
468}
469
470VkResult
471explicit_DestroyInstance(
472 VkInstance instance)
473{
474 loader_platform_thread_lock_mutex(&objLock);
475 validate_object(instance, instance);
476
477 destroy_obj(instance, instance);
478 // Report any remaining objects in LL
479 for (auto it = objMap.begin(); it != objMap.end(); ++it) {
480 OBJTRACK_NODE* pNode = it->second; if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {
481 // Cannot destroy physical device so ignore
482 } else {
483 log_msg(mid(instance), VK_DBG_REPORT_ERROR_BIT, pNode->objType, pNode->vkObj, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK",
484 "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType),
485 reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));
486 }
487 }
488
489 dispatch_key key = get_dispatch_key(instance);
490 VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, instance);
491 VkResult result = pInstanceTable->DestroyInstance(instance);
492
493 // Clean up logging callback, if any
494 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
495 if (my_data->logging_callback) {
496 layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback);
497 }
498
499 layer_debug_report_destroy_instance(mid(instance));
500 layer_data_map.erase(pInstanceTable);
501
502 ObjectTracker_instance_table_map.erase(key);
503 assert(ObjectTracker_instance_table_map.size() == 0 && "Should not have any instance mappings hanging around");
504
505 loader_platform_thread_unlock_mutex(&objLock);
506 return result;
507}
508
509VkResult
Tony Barbour426b9052015-06-24 16:06:58 -0600510explicit_GetPhysicalDeviceQueueProperties(
511 VkPhysicalDevice gpu,
512 uint32_t count,
513 VkPhysicalDeviceQueueProperties* pProperties)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600514{
Tony Barbour426b9052015-06-24 16:06:58 -0600515 VkResult result = get_dispatch_table(ObjectTracker_instance_table_map, gpu)->GetPhysicalDeviceQueueProperties(gpu, count, pProperties);
516
517 loader_platform_thread_lock_mutex(&objLock);
518 setGpuQueueInfoState(count, pProperties);
519 loader_platform_thread_unlock_mutex(&objLock);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600520 return result;
521}
522
523VkResult
524explicit_CreateDevice(
525 VkPhysicalDevice gpu,
526 const VkDeviceCreateInfo *pCreateInfo,
527 VkDevice *pDevice)
528{
529 loader_platform_thread_lock_mutex(&objLock);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600530// VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, gpu);
531 VkLayerDispatchTable *pDeviceTable = get_dispatch_table(ObjectTracker_device_table_map, *pDevice);
532 VkResult result = pDeviceTable->CreateDevice(gpu, pCreateInfo, pDevice);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600533 if (result == VK_SUCCESS) {
534 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
535 //// VkLayerDispatchTable *pTable = get_dispatch_table(ObjectTracker_device_table_map, *pDevice);
536 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
537 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600538 create_obj(*pDevice, *pDevice, VK_OBJECT_TYPE_DEVICE);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600539 }
540
541 loader_platform_thread_unlock_mutex(&objLock);
542 return result;
543}
544
545VkResult
546explicit_DestroyDevice(
547 VkDevice device)
548{
549 loader_platform_thread_lock_mutex(&objLock);
550 validate_object(device, device);
551 destroy_obj(device, device);
552 // Report any remaining objects
553 for (auto it = objMap.begin(); it != objMap.end(); ++it) {
554 OBJTRACK_NODE* pNode = it->second;
555 if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {
556 // Cannot destroy physical device so ignore
557 } else {
558 log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE, device, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK",
559 "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType),
560 reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));
561 }
562 }
563 // Clean up Queue's MemRef Linked Lists
564 destroyQueueMemRefLists();
565
566 loader_platform_thread_unlock_mutex(&objLock);
567
568 dispatch_key key = get_dispatch_key(device);
569 VkLayerDispatchTable *pDisp = get_dispatch_table(ObjectTracker_device_table_map, device);
570 VkResult result = pDisp->DestroyDevice(device);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600571 ObjectTracker_device_table_map.erase(key);
572 assert(ObjectTracker_device_table_map.size() == 0 && "Should not have any instance mappings hanging around");
573
574 return result;
575}
576
577VkResult
578explicit_GetDeviceQueue(
579 VkDevice device,
580 uint32_t queueNodeIndex,
581 uint32_t queueIndex,
582 VkQueue *pQueue)
583{
584 loader_platform_thread_lock_mutex(&objLock);
585 validate_object(device, device);
586 loader_platform_thread_unlock_mutex(&objLock);
587
588 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
589
590 loader_platform_thread_lock_mutex(&objLock);
591 addQueueInfo(queueNodeIndex, *pQueue);
592 loader_platform_thread_unlock_mutex(&objLock);
593
594 return result;
595}
596
597VkResult
598explicit_QueueSubmit(
599 VkQueue queue,
600 uint32_t cmdBufferCount,
601 const VkCmdBuffer *pCmdBuffers,
602 VkFence fence)
603{
604 loader_platform_thread_lock_mutex(&objLock);
605 set_status(queue, fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);
606 // TODO: Fix for updated memory reference mechanism
607 // validate_memory_mapping_status(pMemRefs, memRefCount);
608 // validate_mem_ref_count(memRefCount);
609 loader_platform_thread_unlock_mutex(&objLock);
610
611 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueSubmit(queue, cmdBufferCount, pCmdBuffers, fence);
612
613 return result;
614}
615
616VkResult
617explicit_MapMemory(
618 VkDevice device,
619 VkDeviceMemory mem,
620 VkDeviceSize offset,
621 VkDeviceSize size,
622 VkFlags flags,
623 void **ppData)
624{
625 loader_platform_thread_lock_mutex(&objLock);
626 set_status(device, mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);
627 validate_object(device, device);
628 loader_platform_thread_unlock_mutex(&objLock);
629
630 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->MapMemory(device, mem, offset, size, flags, ppData);
631
632 return result;
633}
634
635VkResult
636explicit_UnmapMemory(
637 VkDevice device,
638 VkDeviceMemory mem)
639{
640 loader_platform_thread_lock_mutex(&objLock);
641 reset_status(device, mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);
642 validate_object(device, device);
643 loader_platform_thread_unlock_mutex(&objLock);
644
645 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->UnmapMemory(device, mem);
646
647 return result;
648}
649
650VkResult
651explicit_DestroyObject(
652 VkDevice device,
653 VkObjectType objType,
654 VkObject object)
655{
656 loader_platform_thread_lock_mutex(&objLock);
657 validate_object(device, device);
658 validate_object(device, object);
659 loader_platform_thread_unlock_mutex(&objLock);
660
661 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->DestroyObject(device, objType, object);
662
663 loader_platform_thread_lock_mutex(&objLock);
664 validateObjectType(device, "vkDestroyObject", objType, object);
665 destroy_obj(device, object);
666 loader_platform_thread_unlock_mutex(&objLock);
667
668 return result;
669}
670
671VkResult
Tony Barbour426b9052015-06-24 16:06:58 -0600672explicit_GetObjectMemoryRequirements(
673 VkDevice device,
674 VkObjectType objType,
675 VkObject object,
676 VkMemoryRequirements* pMemoryRequirements)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600677{
678 loader_platform_thread_lock_mutex(&objLock);
Tony Barbour426b9052015-06-24 16:06:58 -0600679 validateObjectType(device, "vkGetObjectMemoryRequirements", objType, object);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600680 validate_object(device, device);
681 validate_object(device, object);
682 loader_platform_thread_unlock_mutex(&objLock);
683
Tony Barbour426b9052015-06-24 16:06:58 -0600684 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetObjectMemoryRequirements(device, objType, object, pMemoryRequirements);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600685
686 return result;
687}
688
689VkResult
690explicit_QueueBindSparseBufferMemory(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600691 VkQueue queue,
692 VkBuffer buffer,
693 uint32_t numBindings,
694 const VkSparseMemoryBindInfo* pBindInfo)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600695{
696 loader_platform_thread_lock_mutex(&objLock);
697 validateQueueFlags(queue, "QueueBindSparseBufferMemory");
698 validate_object(queue, buffer);
699 loader_platform_thread_unlock_mutex(&objLock);
700
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600701 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueBindSparseBufferMemory(queue, buffer, numBindings, pBindInfo);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600702 return result;
703}
704
705VkResult
706explicit_QueueBindSparseImageMemory(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600707 VkQueue queue,
708 VkImage image,
709 uint32_t numBindings,
710 const VkSparseImageMemoryBindInfo* pBindInfo)
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600711{
712 loader_platform_thread_lock_mutex(&objLock);
713 validateQueueFlags(queue, "QueueBindSparseImageMemory");
714 loader_platform_thread_unlock_mutex(&objLock);
715
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600716 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueBindSparseImageMemory(queue, image, numBindings, pBindInfo);
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600717 return result;
718}
719
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600720VkResult
721explicit_QueueBindSparseImageOpaqueMemory(
722 VkQueue queue,
723 VkImage image,
724 uint32_t numBindings,
725 const VkSparseMemoryBindInfo* pBindInfo)
726{
727 loader_platform_thread_lock_mutex(&objLock);
728 validateQueueFlags(queue, "QueueBindSparseImageOpaqueMemory");
729 loader_platform_thread_unlock_mutex(&objLock);
730
731 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueBindSparseImageOpaqueMemory(queue, image, numBindings, pBindInfo);
732 return result;
733}
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600734
735VkResult
736explicit_GetFenceStatus(
737 VkDevice device,
738 VkFence fence)
739{
740 loader_platform_thread_lock_mutex(&objLock);
741 // Warn if submitted_flag is not set
742 validate_status(device, fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED,
743 VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");
744 validate_object(device, device);
745 loader_platform_thread_unlock_mutex(&objLock);
746
747 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetFenceStatus(device, fence);
748
749 return result;
750}
751
752VkResult
753explicit_WaitForFences(
754 VkDevice device,
755 uint32_t fenceCount,
756 const VkFence *pFences,
Courtney Goeltzenleuchter1f41f542015-07-09 11:44:38 -0600757 VkBool32 waitAll,
Mark Lobodzinski14305ad2015-06-23 11:35:12 -0600758 uint64_t timeout)
759{
760 loader_platform_thread_lock_mutex(&objLock);
761 // Warn if waiting on unsubmitted fence
762 for (uint32_t i = 0; i < fenceCount; i++) {
763 validate_status(device, pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED,
764 VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");
765 }
766 validate_object(device, device);
767 loader_platform_thread_unlock_mutex(&objLock);
768
769 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
770
771 return result;
772}
773
774VkResult
775explicit_AllocDescriptorSets(
776 VkDevice device,
777 VkDescriptorPool descriptorPool,
778 VkDescriptorSetUsage setUsage,
779 uint32_t count,
780 const VkDescriptorSetLayout *pSetLayouts,
781 VkDescriptorSet *pDescriptorSets,
782 uint32_t *pCount)
783{
784 loader_platform_thread_lock_mutex(&objLock);
785 validate_object(device, device);
786 validate_object(device, descriptorPool);
787 loader_platform_thread_unlock_mutex(&objLock);
788
789 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->AllocDescriptorSets(
790 device, descriptorPool, setUsage, count, pSetLayouts, pDescriptorSets, pCount);
791
792 loader_platform_thread_lock_mutex(&objLock);
793 for (uint32_t i = 0; i < *pCount; i++) {
794 create_obj(device, pDescriptorSets[i], VK_OBJECT_TYPE_DESCRIPTOR_SET);
795 }
796 loader_platform_thread_unlock_mutex(&objLock);
797
798 return result;
799}
800
801VkResult
802explicit_DestroySwapChainWSI(
803 VkSwapChainWSI swapChain)
804{
805
806 loader_platform_thread_lock_mutex(&objLock);
807 destroy_obj(swapChain, swapChain);
808 loader_platform_thread_unlock_mutex(&objLock);
809
810 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, swapChain)->DestroySwapChainWSI(swapChain);
811
812 return result;
813}
814
815VkResult
816explicit_FreeMemory(
817 VkDevice device,
818 VkDeviceMemory mem)
819{
820 loader_platform_thread_lock_mutex(&objLock);
821 validate_object(device, device);
822 loader_platform_thread_unlock_mutex(&objLock);
823
824 VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->FreeMemory(device, mem);
825
826 loader_platform_thread_lock_mutex(&objLock);
827 destroy_obj(device, mem);
828 loader_platform_thread_unlock_mutex(&objLock);
829
830 return result;
831}