1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
2  * Copyright (c) 2015-2016 Valve Corporation
3  * Copyright (c) 2015-2016 LunarG, Inc.
4  * Copyright (C) 2015-2016 Google Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and/or associated documentation files (the "Materials"), to
8  * deal in the Materials without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Materials, and to permit persons to whom the Materials
11  * are furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice(s) and this permission notice shall be included
14  * in all copies or substantial portions of the Materials.
15  *
16  * THE MATERIALS ARE 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.
19  *
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23  * USE OR OTHER DEALINGS IN THE MATERIALS
24  *
25  * Author: Jon Ashburn <jon@lunarg.com>
26  * Author: Mark Lobodzinski <mark@lunarg.com>
27  * Author: Tobin Ehlis <tobin@lunarg.com>
28  */
29 
30 #include "vulkan/vk_layer.h"
31 #include "vk_layer_extension_utils.h"
32 #include "vk_enum_string_helper.h"
33 #include "vk_layer_table.h"
34 #include "vk_layer_utils.h"
35 
36 // Object Tracker ERROR codes
37 typedef enum _OBJECT_TRACK_ERROR {
38     OBJTRACK_NONE,                     // Used for INFO & other non-error messages
39     OBJTRACK_UNKNOWN_OBJECT,           // Updating uses of object that's not in global object list
40     OBJTRACK_INTERNAL_ERROR,           // Bug with data tracking within the layer
41     OBJTRACK_DESTROY_OBJECT_FAILED,    // Couldn't find object to be destroyed
42     OBJTRACK_OBJECT_LEAK,              // OBJECT was not correctly freed/destroyed
43     OBJTRACK_OBJCOUNT_MAX_EXCEEDED,    // Request for Object data in excess of max obj count
44     OBJTRACK_INVALID_OBJECT,           // Object used that has never been created
45     OBJTRACK_DESCRIPTOR_POOL_MISMATCH, // Descriptor Pools specified incorrectly
46     OBJTRACK_COMMAND_POOL_MISMATCH,    // Command Pools specified incorrectly
47 } OBJECT_TRACK_ERROR;
48 
49 // Object Status -- used to track state of individual objects
50 typedef VkFlags ObjectStatusFlags;
51 typedef enum _ObjectStatusFlagBits {
52     OBJSTATUS_NONE = 0x00000000,                     // No status is set
53     OBJSTATUS_FENCE_IS_SUBMITTED = 0x00000001,       // Fence has been submitted
54     OBJSTATUS_VIEWPORT_BOUND = 0x00000002,           // Viewport state object has been bound
55     OBJSTATUS_RASTER_BOUND = 0x00000004,             // Viewport state object has been bound
56     OBJSTATUS_COLOR_BLEND_BOUND = 0x00000008,        // Viewport state object has been bound
57     OBJSTATUS_DEPTH_STENCIL_BOUND = 0x00000010,      // Viewport state object has been bound
58     OBJSTATUS_GPU_MEM_MAPPED = 0x00000020,           // Memory object is currently mapped
59     OBJSTATUS_COMMAND_BUFFER_SECONDARY = 0x00000040, // Command Buffer is of type SECONDARY
60 } ObjectStatusFlagBits;
61 
62 typedef struct _OBJTRACK_NODE {
63     uint64_t vkObj;                     // Object handle
64     VkDebugReportObjectTypeEXT objType; // Object type identifier
65     ObjectStatusFlags status;           // Object state
66     uint64_t parentObj;                 // Parent object
67     uint64_t belongsTo;                 // Object Scope -- owning device/instance
68 } OBJTRACK_NODE;
69 
70 // prototype for extension functions
71 uint64_t objTrackGetObjectCount(VkDevice device);
72 uint64_t objTrackGetObjectsOfTypeCount(VkDevice, VkDebugReportObjectTypeEXT type);
73 
74 // Func ptr typedefs
75 typedef uint64_t (*OBJ_TRACK_GET_OBJECT_COUNT)(VkDevice);
76 typedef uint64_t (*OBJ_TRACK_GET_OBJECTS_OF_TYPE_COUNT)(VkDevice, VkDebugReportObjectTypeEXT);
77 
78 struct layer_data {
79     debug_report_data *report_data;
80     // TODO: put instance data here
81     std::vector<VkDebugReportCallbackEXT> logging_callback;
82     bool wsi_enabled;
83     bool objtrack_extensions_enabled;
84 
layer_datalayer_data85     layer_data() : report_data(nullptr), wsi_enabled(false), objtrack_extensions_enabled(false){};
86 };
87 
88 struct instExts {
89     bool wsi_enabled;
90 };
91 
92 static std::unordered_map<void *, struct instExts> instanceExtMap;
93 static std::unordered_map<void *, layer_data *> layer_data_map;
94 static device_table_map object_tracker_device_table_map;
95 static instance_table_map object_tracker_instance_table_map;
96 
97 // We need additionally validate image usage using a separate map
98 // of swapchain-created images
99 static unordered_map<uint64_t, OBJTRACK_NODE *> swapchainImageMap;
100 
101 static long long unsigned int object_track_index = 0;
102 static int objLockInitialized = 0;
103 static loader_platform_thread_mutex objLock;
104 
105 // Objects stored in a global map w/ struct containing basic info
106 // unordered_map<const void*, OBJTRACK_NODE*> objMap;
107 
108 #define NUM_OBJECT_TYPES (VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT + 1)
109 
110 static uint64_t numObjs[NUM_OBJECT_TYPES] = {0};
111 static uint64_t numTotalObjs = 0;
112 static VkQueueFamilyProperties *queueInfo = NULL;
113 static uint32_t queueCount = 0;
114 
115 template layer_data *get_my_data_ptr<layer_data>(void *data_key, std::unordered_map<void *, layer_data *> &data_map);
116 
117 //
118 // Internal Object Tracker Functions
119 //
120 
createDeviceRegisterExtensions(const VkDeviceCreateInfo * pCreateInfo,VkDevice device)121 static void createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
122     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
123     VkLayerDispatchTable *pDisp = get_dispatch_table(object_tracker_device_table_map, device);
124     PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
125     pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
126     pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
127     pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
128     pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
129     pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
130     my_device_data->wsi_enabled = false;
131     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
132         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
133             my_device_data->wsi_enabled = true;
134 
135         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], "OBJTRACK_EXTENSIONS") == 0)
136             my_device_data->objtrack_extensions_enabled = true;
137     }
138 }
139 
createInstanceRegisterExtensions(const VkInstanceCreateInfo * pCreateInfo,VkInstance instance)140 static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
141     uint32_t i;
142     VkLayerInstanceDispatchTable *pDisp = get_dispatch_table(object_tracker_instance_table_map, instance);
143     PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
144 
145     pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR");
146     pDisp->GetPhysicalDeviceSurfaceSupportKHR =
147         (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
148     pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR =
149         (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
150     pDisp->GetPhysicalDeviceSurfaceFormatsKHR =
151         (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
152     pDisp->GetPhysicalDeviceSurfacePresentModesKHR =
153         (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
154 
155 #if VK_USE_PLATFORM_WIN32_KHR
156     pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR");
157     pDisp->GetPhysicalDeviceWin32PresentationSupportKHR =
158         (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
159 #endif // VK_USE_PLATFORM_WIN32_KHR
160 #ifdef VK_USE_PLATFORM_XCB_KHR
161     pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(instance, "vkCreateXcbSurfaceKHR");
162     pDisp->GetPhysicalDeviceXcbPresentationSupportKHR =
163         (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
164 #endif // VK_USE_PLATFORM_XCB_KHR
165 #ifdef VK_USE_PLATFORM_XLIB_KHR
166     pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(instance, "vkCreateXlibSurfaceKHR");
167     pDisp->GetPhysicalDeviceXlibPresentationSupportKHR =
168         (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
169 #endif // VK_USE_PLATFORM_XLIB_KHR
170 #ifdef VK_USE_PLATFORM_MIR_KHR
171     pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)gpa(instance, "vkCreateMirSurfaceKHR");
172     pDisp->GetPhysicalDeviceMirPresentationSupportKHR =
173         (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
174 #endif // VK_USE_PLATFORM_MIR_KHR
175 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
176     pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(instance, "vkCreateWaylandSurfaceKHR");
177     pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR =
178         (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
179 #endif //  VK_USE_PLATFORM_WAYLAND_KHR
180 #ifdef VK_USE_PLATFORM_ANDROID_KHR
181     pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(instance, "vkCreateAndroidSurfaceKHR");
182 #endif // VK_USE_PLATFORM_ANDROID_KHR
183 
184     instanceExtMap[pDisp].wsi_enabled = false;
185     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
186         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0)
187             instanceExtMap[pDisp].wsi_enabled = true;
188     }
189 }
190 
191 // Indicate device or instance dispatch table type
192 typedef enum _DispTableType {
193     DISP_TBL_TYPE_INSTANCE,
194     DISP_TBL_TYPE_DEVICE,
195 } DispTableType;
196 
mdd(const void * object)197 debug_report_data *mdd(const void *object) {
198     dispatch_key key = get_dispatch_key(object);
199     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
200     return my_data->report_data;
201 }
202 
mid(VkInstance object)203 debug_report_data *mid(VkInstance object) {
204     dispatch_key key = get_dispatch_key(object);
205     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
206     return my_data->report_data;
207 }
208 
209 // For each Queue's doubly linked-list of mem refs
210 typedef struct _OT_MEM_INFO {
211     VkDeviceMemory mem;
212     struct _OT_MEM_INFO *pNextMI;
213     struct _OT_MEM_INFO *pPrevMI;
214 
215 } OT_MEM_INFO;
216 
217 // Track Queue information
218 typedef struct _OT_QUEUE_INFO {
219     OT_MEM_INFO *pMemRefList;
220     struct _OT_QUEUE_INFO *pNextQI;
221     uint32_t queueNodeIndex;
222     VkQueue queue;
223     uint32_t refCount;
224 } OT_QUEUE_INFO;
225 
226 // Global list of QueueInfo structures, one per queue
227 static OT_QUEUE_INFO *g_pQueueInfo = NULL;
228 
229 // Convert an object type enum to an object type array index
objTypeToIndex(uint32_t objType)230 static uint32_t objTypeToIndex(uint32_t objType) {
231     uint32_t index = objType;
232     return index;
233 }
234 
235 // Add new queue to head of global queue list
addQueueInfo(uint32_t queueNodeIndex,VkQueue queue)236 static void addQueueInfo(uint32_t queueNodeIndex, VkQueue queue) {
237     OT_QUEUE_INFO *pQueueInfo = new OT_QUEUE_INFO;
238 
239     if (pQueueInfo != NULL) {
240         memset(pQueueInfo, 0, sizeof(OT_QUEUE_INFO));
241         pQueueInfo->queue = queue;
242         pQueueInfo->queueNodeIndex = queueNodeIndex;
243         pQueueInfo->pNextQI = g_pQueueInfo;
244         g_pQueueInfo = pQueueInfo;
245     } else {
246         log_msg(mdd(queue), VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, reinterpret_cast<uint64_t>(queue),
247                 __LINE__, OBJTRACK_INTERNAL_ERROR, "OBJTRACK",
248                 "ERROR:  VK_ERROR_OUT_OF_HOST_MEMORY -- could not allocate memory for Queue Information");
249     }
250 }
251 
252 // Destroy memRef lists and free all memory
destroyQueueMemRefLists(void)253 static void destroyQueueMemRefLists(void) {
254     OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;
255     OT_QUEUE_INFO *pDelQueueInfo = NULL;
256     while (pQueueInfo != NULL) {
257         OT_MEM_INFO *pMemInfo = pQueueInfo->pMemRefList;
258         while (pMemInfo != NULL) {
259             OT_MEM_INFO *pDelMemInfo = pMemInfo;
260             pMemInfo = pMemInfo->pNextMI;
261             delete pDelMemInfo;
262         }
263         pDelQueueInfo = pQueueInfo;
264         pQueueInfo = pQueueInfo->pNextQI;
265         delete pDelQueueInfo;
266     }
267     g_pQueueInfo = pQueueInfo;
268 }
269 
setGpuQueueInfoState(uint32_t count,void * pData)270 static void setGpuQueueInfoState(uint32_t count, void *pData) {
271     queueCount = count;
272     queueInfo = (VkQueueFamilyProperties *)realloc((void *)queueInfo, count * sizeof(VkQueueFamilyProperties));
273     if (queueInfo != NULL) {
274         memcpy(queueInfo, pData, count * sizeof(VkQueueFamilyProperties));
275     }
276 }
277 
278 // Check Queue type flags for selected queue operations
validateQueueFlags(VkQueue queue,const char * function)279 static void validateQueueFlags(VkQueue queue, const char *function) {
280     OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;
281     while ((pQueueInfo != NULL) && (pQueueInfo->queue != queue)) {
282         pQueueInfo = pQueueInfo->pNextQI;
283     }
284     if (pQueueInfo != NULL) {
285         if ((queueInfo != NULL) && (queueInfo[pQueueInfo->queueNodeIndex].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) == 0) {
286             log_msg(mdd(queue), VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT,
287                     reinterpret_cast<uint64_t>(queue), __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
288                     "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_SPARSE_BINDING_BIT not set", function);
289         }
290     }
291 }
292 
293 /* TODO: Port to new type safety */
294 #if 0
295 // Check object status for selected flag state
296 static VkBool32
297 validate_status(
298     VkObject            dispatchable_object,
299     VkObject            vkObj,
300     VkObjectType        objType,
301     ObjectStatusFlags   status_mask,
302     ObjectStatusFlags   status_flag,
303     VkFlags             msg_flags,
304     OBJECT_TRACK_ERROR  error_code,
305     const char         *fail_msg)
306 {
307     if (objMap.find(vkObj) != objMap.end()) {
308         OBJTRACK_NODE* pNode = objMap[vkObj];
309         if ((pNode->status & status_mask) != status_flag) {
310             char str[1024];
311             log_msg(mdd(dispatchable_object), msg_flags, pNode->objType, vkObj, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
312                 "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkObjectType(objType),
313                 static_cast<uint64_t>(vkObj), fail_msg);
314             return VK_FALSE;
315         }
316         return VK_TRUE;
317     }
318     else {
319         // If we do not find it print an error
320         log_msg(mdd(dispatchable_object), msg_flags, (VkObjectType) 0, vkObj, __LINE__, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
321             "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",
322             static_cast<uint64_t>(vkObj), string_VkObjectType(objType));
323         return VK_FALSE;
324     }
325 }
326 #endif
327 
328 #include "vk_dispatch_table_helper.h"
329 
init_object_tracker(layer_data * my_data,const VkAllocationCallbacks * pAllocator)330 static void init_object_tracker(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
331 
332     layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_object_tracker");
333 
334     if (!objLockInitialized) {
335         // TODO/TBD: Need to delete this mutex sometime.  How???  One
336         // suggestion is to call this during vkCreateInstance(), and then we
337         // can clean it up during vkDestroyInstance().  However, that requires
338         // that the layer have per-instance locks.  We need to come back and
339         // address this soon.
340         loader_platform_thread_create_mutex(&objLock);
341         objLockInitialized = 1;
342     }
343 }
344 
345 //
346 // Forward declarations
347 //
348 
349 static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDevice vkObj, VkDebugReportObjectTypeEXT objType);
350 static void create_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType);
351 static void create_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType);
352 static void create_device(VkPhysicalDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType);
353 static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType);
354 static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
355 static VkBool32 validate_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType,
356                                   bool null_allowed);
357 static VkBool32 validate_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType,
358                                 bool null_allowed);
359 static VkBool32 validate_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object, VkDebugReportObjectTypeEXT objType,
360                                          bool null_allowed);
361 static VkBool32 validate_descriptor_set_layout(VkDevice dispatchable_object, VkDescriptorSetLayout object,
362                                                VkDebugReportObjectTypeEXT objType, bool null_allowed);
363 static VkBool32 validate_command_pool(VkDevice dispatchable_object, VkCommandPool object, VkDebugReportObjectTypeEXT objType,
364                                       bool null_allowed);
365 static VkBool32 validate_buffer(VkQueue dispatchable_object, VkBuffer object, VkDebugReportObjectTypeEXT objType,
366                                 bool null_allowed);
367 static void create_pipeline(VkDevice dispatchable_object, VkPipeline vkObj, VkDebugReportObjectTypeEXT objType);
368 static VkBool32 validate_pipeline_cache(VkDevice dispatchable_object, VkPipelineCache object, VkDebugReportObjectTypeEXT objType,
369                                         bool null_allowed);
370 static VkBool32 validate_render_pass(VkDevice dispatchable_object, VkRenderPass object, VkDebugReportObjectTypeEXT objType,
371                                      bool null_allowed);
372 static VkBool32 validate_shader_module(VkDevice dispatchable_object, VkShaderModule object, VkDebugReportObjectTypeEXT objType,
373                                        bool null_allowed);
374 static VkBool32 validate_pipeline_layout(VkDevice dispatchable_object, VkPipelineLayout object, VkDebugReportObjectTypeEXT objType,
375                                          bool null_allowed);
376 static VkBool32 validate_pipeline(VkDevice dispatchable_object, VkPipeline object, VkDebugReportObjectTypeEXT objType,
377                                   bool null_allowed);
378 static void destroy_command_pool(VkDevice dispatchable_object, VkCommandPool object);
379 static void destroy_command_buffer(VkCommandBuffer dispatchable_object, VkCommandBuffer object);
380 static void destroy_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object);
381 static void destroy_descriptor_set(VkDevice dispatchable_object, VkDescriptorSet object);
382 static void destroy_device_memory(VkDevice dispatchable_object, VkDeviceMemory object);
383 static void destroy_swapchain_khr(VkDevice dispatchable_object, VkSwapchainKHR object);
384 static VkBool32 set_device_memory_status(VkDevice dispatchable_object, VkDeviceMemory object, VkDebugReportObjectTypeEXT objType,
385                                          ObjectStatusFlags status_flag);
386 static VkBool32 reset_device_memory_status(VkDevice dispatchable_object, VkDeviceMemory object, VkDebugReportObjectTypeEXT objType,
387                                            ObjectStatusFlags status_flag);
388 #if 0
389 static VkBool32 validate_status(VkDevice dispatchable_object, VkFence object, VkDebugReportObjectTypeEXT objType,
390     ObjectStatusFlags status_mask, ObjectStatusFlags status_flag, VkFlags msg_flags, OBJECT_TRACK_ERROR  error_code,
391     const char         *fail_msg);
392 #endif
393 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkPhysicalDeviceMap;
394 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkDeviceMap;
395 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkImageMap;
396 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkQueueMap;
397 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkDescriptorSetMap;
398 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkBufferMap;
399 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkFenceMap;
400 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkSemaphoreMap;
401 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkCommandPoolMap;
402 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkCommandBufferMap;
403 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkSwapchainKHRMap;
404 extern unordered_map<uint64_t, OBJTRACK_NODE *> VkSurfaceKHRMap;
405 
create_physical_device(VkInstance dispatchable_object,VkPhysicalDevice vkObj,VkDebugReportObjectTypeEXT objType)406 static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDevice vkObj, VkDebugReportObjectTypeEXT objType) {
407     log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__,
408             OBJTRACK_NONE, "OBJTRACK", "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
409             string_VkDebugReportObjectTypeEXT(objType), reinterpret_cast<uint64_t>(vkObj));
410 
411     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
412     pNewObjNode->objType = objType;
413     pNewObjNode->belongsTo = (uint64_t)dispatchable_object;
414     pNewObjNode->status = OBJSTATUS_NONE;
415     pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);
416     VkPhysicalDeviceMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode;
417     uint32_t objIndex = objTypeToIndex(objType);
418     numObjs[objIndex]++;
419     numTotalObjs++;
420 }
421 
create_surface_khr(VkInstance dispatchable_object,VkSurfaceKHR vkObj,VkDebugReportObjectTypeEXT objType)422 static void create_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR vkObj, VkDebugReportObjectTypeEXT objType) {
423     // TODO: Add tracking of surface objects
424     log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, (uint64_t)(vkObj), __LINE__, OBJTRACK_NONE,
425             "OBJTRACK", "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
426             string_VkDebugReportObjectTypeEXT(objType), (uint64_t)(vkObj));
427 
428     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
429     pNewObjNode->objType = objType;
430     pNewObjNode->belongsTo = (uint64_t)dispatchable_object;
431     pNewObjNode->status = OBJSTATUS_NONE;
432     pNewObjNode->vkObj = (uint64_t)(vkObj);
433     VkSurfaceKHRMap[(uint64_t)vkObj] = pNewObjNode;
434     uint32_t objIndex = objTypeToIndex(objType);
435     numObjs[objIndex]++;
436     numTotalObjs++;
437 }
438 
destroy_surface_khr(VkInstance dispatchable_object,VkSurfaceKHR object)439 static void destroy_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR object) {
440     uint64_t object_handle = (uint64_t)(object);
441     if (VkSurfaceKHRMap.find(object_handle) != VkSurfaceKHRMap.end()) {
442         OBJTRACK_NODE *pNode = VkSurfaceKHRMap[(uint64_t)object];
443         uint32_t objIndex = objTypeToIndex(pNode->objType);
444         assert(numTotalObjs > 0);
445         numTotalObjs--;
446         assert(numObjs[objIndex] > 0);
447         numObjs[objIndex]--;
448         log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, pNode->objType, object_handle, __LINE__,
449                 OBJTRACK_NONE, "OBJTRACK",
450                 "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",
451                 string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t)(object), numTotalObjs, numObjs[objIndex],
452                 string_VkDebugReportObjectTypeEXT(pNode->objType));
453         delete pNode;
454         VkSurfaceKHRMap.erase(object_handle);
455     } else {
456         log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, object_handle, __LINE__,
457                 OBJTRACK_NONE, "OBJTRACK",
458                 "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?", object_handle);
459     }
460 }
461 
alloc_command_buffer(VkDevice device,VkCommandPool commandPool,VkCommandBuffer vkObj,VkDebugReportObjectTypeEXT objType,VkCommandBufferLevel level)462 static void alloc_command_buffer(VkDevice device, VkCommandPool commandPool, VkCommandBuffer vkObj,
463                                  VkDebugReportObjectTypeEXT objType, VkCommandBufferLevel level) {
464     log_msg(mdd(device), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE,
465             "OBJTRACK", "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
466             string_VkDebugReportObjectTypeEXT(objType), reinterpret_cast<uint64_t>(vkObj));
467 
468     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
469     pNewObjNode->objType = objType;
470     pNewObjNode->belongsTo = (uint64_t)device;
471     pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);
472     pNewObjNode->parentObj = (uint64_t)commandPool;
473     if (level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
474         pNewObjNode->status = OBJSTATUS_COMMAND_BUFFER_SECONDARY;
475     } else {
476         pNewObjNode->status = OBJSTATUS_NONE;
477     }
478     VkCommandBufferMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode;
479     uint32_t objIndex = objTypeToIndex(objType);
480     numObjs[objIndex]++;
481     numTotalObjs++;
482 }
483 
free_command_buffer(VkDevice device,VkCommandPool commandPool,VkCommandBuffer commandBuffer)484 static void free_command_buffer(VkDevice device, VkCommandPool commandPool, VkCommandBuffer commandBuffer) {
485     uint64_t object_handle = reinterpret_cast<uint64_t>(commandBuffer);
486     if (VkCommandBufferMap.find(object_handle) != VkCommandBufferMap.end()) {
487         OBJTRACK_NODE *pNode = VkCommandBufferMap[(uint64_t)commandBuffer];
488 
489         if (pNode->parentObj != (uint64_t)(commandPool)) {
490             log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, object_handle, __LINE__,
491                     OBJTRACK_COMMAND_POOL_MISMATCH, "OBJTRACK",
492                     "FreeCommandBuffers is attempting to free Command Buffer 0x%" PRIxLEAST64
493                     " belonging to Command Pool 0x%" PRIxLEAST64 " from pool 0x%" PRIxLEAST64 ").",
494                     reinterpret_cast<uint64_t>(commandBuffer), pNode->parentObj, (uint64_t)(commandPool));
495         } else {
496 
497             uint32_t objIndex = objTypeToIndex(pNode->objType);
498             assert(numTotalObjs > 0);
499             numTotalObjs--;
500             assert(numObjs[objIndex] > 0);
501             numObjs[objIndex]--;
502             log_msg(mdd(device), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE,
503                     "OBJTRACK", "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",
504                     string_VkDebugReportObjectTypeEXT(pNode->objType), reinterpret_cast<uint64_t>(commandBuffer), numTotalObjs,
505                     numObjs[objIndex], string_VkDebugReportObjectTypeEXT(pNode->objType));
506             delete pNode;
507             VkCommandBufferMap.erase(object_handle);
508         }
509     } else {
510         log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, object_handle, __LINE__, OBJTRACK_NONE,
511                 "OBJTRACK", "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
512                 object_handle);
513     }
514 }
515 
alloc_descriptor_set(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorSet vkObj,VkDebugReportObjectTypeEXT objType)516 static void alloc_descriptor_set(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSet vkObj,
517                                  VkDebugReportObjectTypeEXT objType) {
518     log_msg(mdd(device), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, (uint64_t)(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",
519             "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++, string_VkDebugReportObjectTypeEXT(objType),
520             (uint64_t)(vkObj));
521 
522     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
523     pNewObjNode->objType = objType;
524     pNewObjNode->belongsTo = (uint64_t)device;
525     pNewObjNode->status = OBJSTATUS_NONE;
526     pNewObjNode->vkObj = (uint64_t)(vkObj);
527     pNewObjNode->parentObj = (uint64_t)descriptorPool;
528     VkDescriptorSetMap[(uint64_t)vkObj] = pNewObjNode;
529     uint32_t objIndex = objTypeToIndex(objType);
530     numObjs[objIndex]++;
531     numTotalObjs++;
532 }
533 
free_descriptor_set(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorSet descriptorSet)534 static void free_descriptor_set(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSet descriptorSet) {
535     uint64_t object_handle = (uint64_t)(descriptorSet);
536     if (VkDescriptorSetMap.find(object_handle) != VkDescriptorSetMap.end()) {
537         OBJTRACK_NODE *pNode = VkDescriptorSetMap[(uint64_t)descriptorSet];
538 
539         if (pNode->parentObj != (uint64_t)(descriptorPool)) {
540             log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, object_handle, __LINE__,
541                     OBJTRACK_DESCRIPTOR_POOL_MISMATCH, "OBJTRACK",
542                     "FreeDescriptorSets is attempting to free descriptorSet 0x%" PRIxLEAST64
543                     " belonging to Descriptor Pool 0x%" PRIxLEAST64 " from pool 0x%" PRIxLEAST64 ").",
544                     (uint64_t)(descriptorSet), pNode->parentObj, (uint64_t)(descriptorPool));
545         } else {
546             uint32_t objIndex = objTypeToIndex(pNode->objType);
547             assert(numTotalObjs > 0);
548             numTotalObjs--;
549             assert(numObjs[objIndex] > 0);
550             numObjs[objIndex]--;
551             log_msg(mdd(device), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE,
552                     "OBJTRACK", "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",
553                     string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t)(descriptorSet), numTotalObjs, numObjs[objIndex],
554                     string_VkDebugReportObjectTypeEXT(pNode->objType));
555             delete pNode;
556             VkDescriptorSetMap.erase(object_handle);
557         }
558     } else {
559         log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, object_handle, __LINE__, OBJTRACK_NONE,
560                 "OBJTRACK", "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
561                 object_handle);
562     }
563 }
564 
create_queue(VkDevice dispatchable_object,VkQueue vkObj,VkDebugReportObjectTypeEXT objType)565 static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType) {
566     log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__,
567             OBJTRACK_NONE, "OBJTRACK", "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
568             string_VkDebugReportObjectTypeEXT(objType), reinterpret_cast<uint64_t>(vkObj));
569 
570     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
571     pNewObjNode->objType = objType;
572     pNewObjNode->belongsTo = (uint64_t)dispatchable_object;
573     pNewObjNode->status = OBJSTATUS_NONE;
574     pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);
575     VkQueueMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode;
576     uint32_t objIndex = objTypeToIndex(objType);
577     numObjs[objIndex]++;
578     numTotalObjs++;
579 }
create_swapchain_image_obj(VkDevice dispatchable_object,VkImage vkObj,VkSwapchainKHR swapchain)580 static void create_swapchain_image_obj(VkDevice dispatchable_object, VkImage vkObj, VkSwapchainKHR swapchain) {
581     log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)vkObj,
582             __LINE__, OBJTRACK_NONE, "OBJTRACK", "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
583             "SwapchainImage", (uint64_t)(vkObj));
584 
585     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
586     pNewObjNode->belongsTo = (uint64_t)dispatchable_object;
587     pNewObjNode->objType = VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT;
588     pNewObjNode->status = OBJSTATUS_NONE;
589     pNewObjNode->vkObj = (uint64_t)vkObj;
590     pNewObjNode->parentObj = (uint64_t)swapchain;
591     swapchainImageMap[(uint64_t)(vkObj)] = pNewObjNode;
592 }
593 
create_device(VkInstance dispatchable_object,VkDevice vkObj,VkDebugReportObjectTypeEXT objType)594 static void create_device(VkInstance dispatchable_object, VkDevice vkObj, VkDebugReportObjectTypeEXT objType) {
595     log_msg(mid(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, (uint64_t)(vkObj), __LINE__, OBJTRACK_NONE,
596             "OBJTRACK", "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
597             string_VkDebugReportObjectTypeEXT(objType), (uint64_t)(vkObj));
598 
599     OBJTRACK_NODE *pNewObjNode = new OBJTRACK_NODE;
600     pNewObjNode->belongsTo = (uint64_t)dispatchable_object;
601     pNewObjNode->objType = objType;
602     pNewObjNode->status = OBJSTATUS_NONE;
603     pNewObjNode->vkObj = (uint64_t)(vkObj);
604     VkDeviceMap[(uint64_t)vkObj] = pNewObjNode;
605     uint32_t objIndex = objTypeToIndex(objType);
606     numObjs[objIndex]++;
607     numTotalObjs++;
608 }
609 
610 //
611 // Non-auto-generated API functions called by generated code
612 //
explicit_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)613 VkResult explicit_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
614                                  VkInstance *pInstance) {
615     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
616 
617     assert(chain_info->u.pLayerInfo);
618     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
619     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
620     if (fpCreateInstance == NULL) {
621         return VK_ERROR_INITIALIZATION_FAILED;
622     }
623 
624     // Advance the link info for the next element on the chain
625     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
626 
627     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
628     if (result != VK_SUCCESS) {
629         return result;
630     }
631 
632     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
633     initInstanceTable(*pInstance, fpGetInstanceProcAddr, object_tracker_instance_table_map);
634     VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, *pInstance);
635 
636     my_data->report_data = debug_report_create_instance(pInstanceTable, *pInstance, pCreateInfo->enabledExtensionCount,
637                                                         pCreateInfo->ppEnabledExtensionNames);
638 
639     init_object_tracker(my_data, pAllocator);
640     createInstanceRegisterExtensions(pCreateInfo, *pInstance);
641 
642     create_instance(*pInstance, *pInstance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT);
643 
644     return result;
645 }
646 
explicit_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice gpu,uint32_t * pCount,VkQueueFamilyProperties * pProperties)647 void explicit_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice gpu, uint32_t *pCount, VkQueueFamilyProperties *pProperties) {
648     get_dispatch_table(object_tracker_instance_table_map, gpu)->GetPhysicalDeviceQueueFamilyProperties(gpu, pCount, pProperties);
649 
650     loader_platform_thread_lock_mutex(&objLock);
651     if (pProperties != NULL)
652         setGpuQueueInfoState(*pCount, pProperties);
653     loader_platform_thread_unlock_mutex(&objLock);
654 }
655 
explicit_CreateDevice(VkPhysicalDevice gpu,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)656 VkResult explicit_CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
657                                VkDevice *pDevice) {
658     loader_platform_thread_lock_mutex(&objLock);
659     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
660 
661     assert(chain_info->u.pLayerInfo);
662     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
663     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
664     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
665     if (fpCreateDevice == NULL) {
666         loader_platform_thread_unlock_mutex(&objLock);
667         return VK_ERROR_INITIALIZATION_FAILED;
668     }
669 
670     // Advance the link info for the next element on the chain
671     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
672 
673     VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
674     if (result != VK_SUCCESS) {
675         loader_platform_thread_unlock_mutex(&objLock);
676         return result;
677     }
678 
679     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
680     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
681     my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
682 
683     initDeviceTable(*pDevice, fpGetDeviceProcAddr, object_tracker_device_table_map);
684 
685     createDeviceRegisterExtensions(pCreateInfo, *pDevice);
686 
687     if (VkPhysicalDeviceMap.find((uint64_t)gpu) != VkPhysicalDeviceMap.end()) {
688         OBJTRACK_NODE *pNewObjNode = VkPhysicalDeviceMap[(uint64_t)gpu];
689         create_device((VkInstance)pNewObjNode->belongsTo, *pDevice, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT);
690     }
691 
692     loader_platform_thread_unlock_mutex(&objLock);
693     return result;
694 }
695 
explicit_EnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)696 VkResult explicit_EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
697                                            VkPhysicalDevice *pPhysicalDevices) {
698     VkBool32 skipCall = VK_FALSE;
699     loader_platform_thread_lock_mutex(&objLock);
700     skipCall |= validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);
701     loader_platform_thread_unlock_mutex(&objLock);
702     if (skipCall)
703         return VK_ERROR_VALIDATION_FAILED_EXT;
704     VkResult result = get_dispatch_table(object_tracker_instance_table_map, instance)
705                           ->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
706     loader_platform_thread_lock_mutex(&objLock);
707     if (result == VK_SUCCESS) {
708         if (pPhysicalDevices) {
709             for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
710                 create_physical_device(instance, pPhysicalDevices[i], VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT);
711             }
712         }
713     }
714     loader_platform_thread_unlock_mutex(&objLock);
715     return result;
716 }
717 
explicit_GetDeviceQueue(VkDevice device,uint32_t queueNodeIndex,uint32_t queueIndex,VkQueue * pQueue)718 void explicit_GetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue *pQueue) {
719     loader_platform_thread_lock_mutex(&objLock);
720     validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
721     loader_platform_thread_unlock_mutex(&objLock);
722 
723     get_dispatch_table(object_tracker_device_table_map, device)->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
724 
725     loader_platform_thread_lock_mutex(&objLock);
726     addQueueInfo(queueNodeIndex, *pQueue);
727     create_queue(device, *pQueue, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT);
728     loader_platform_thread_unlock_mutex(&objLock);
729 }
730 
explicit_MapMemory(VkDevice device,VkDeviceMemory mem,VkDeviceSize offset,VkDeviceSize size,VkFlags flags,void ** ppData)731 VkResult explicit_MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags,
732                             void **ppData) {
733     VkBool32 skipCall = VK_FALSE;
734     loader_platform_thread_lock_mutex(&objLock);
735     skipCall |= set_device_memory_status(device, mem, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, OBJSTATUS_GPU_MEM_MAPPED);
736     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
737     loader_platform_thread_unlock_mutex(&objLock);
738     if (skipCall == VK_TRUE)
739         return VK_ERROR_VALIDATION_FAILED_EXT;
740 
741     VkResult result =
742         get_dispatch_table(object_tracker_device_table_map, device)->MapMemory(device, mem, offset, size, flags, ppData);
743 
744     return result;
745 }
746 
explicit_UnmapMemory(VkDevice device,VkDeviceMemory mem)747 void explicit_UnmapMemory(VkDevice device, VkDeviceMemory mem) {
748     VkBool32 skipCall = VK_FALSE;
749     loader_platform_thread_lock_mutex(&objLock);
750     skipCall |= reset_device_memory_status(device, mem, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, OBJSTATUS_GPU_MEM_MAPPED);
751     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
752     loader_platform_thread_unlock_mutex(&objLock);
753     if (skipCall == VK_TRUE)
754         return;
755 
756     get_dispatch_table(object_tracker_device_table_map, device)->UnmapMemory(device, mem);
757 }
758 
explicit_QueueBindSparse(VkQueue queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence fence)759 VkResult explicit_QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) {
760     loader_platform_thread_lock_mutex(&objLock);
761     validateQueueFlags(queue, "QueueBindSparse");
762 
763     for (uint32_t i = 0; i < bindInfoCount; i++) {
764         for (uint32_t j = 0; j < pBindInfo[i].bufferBindCount; j++)
765             validate_buffer(queue, pBindInfo[i].pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, false);
766         for (uint32_t j = 0; j < pBindInfo[i].imageOpaqueBindCount; j++)
767             validate_image(queue, pBindInfo[i].pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, false);
768         for (uint32_t j = 0; j < pBindInfo[i].imageBindCount; j++)
769             validate_image(queue, pBindInfo[i].pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, false);
770     }
771 
772     loader_platform_thread_unlock_mutex(&objLock);
773 
774     VkResult result =
775         get_dispatch_table(object_tracker_device_table_map, queue)->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
776     return result;
777 }
778 
explicit_AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)779 VkResult explicit_AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
780                                          VkCommandBuffer *pCommandBuffers) {
781     VkBool32 skipCall = VK_FALSE;
782     loader_platform_thread_lock_mutex(&objLock);
783     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
784     skipCall |= validate_command_pool(device, pAllocateInfo->commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false);
785     loader_platform_thread_unlock_mutex(&objLock);
786 
787     if (skipCall) {
788         return VK_ERROR_VALIDATION_FAILED_EXT;
789     }
790 
791     VkResult result =
792         get_dispatch_table(object_tracker_device_table_map, device)->AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
793 
794     loader_platform_thread_lock_mutex(&objLock);
795     for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
796         alloc_command_buffer(device, pAllocateInfo->commandPool, pCommandBuffers[i], VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
797                              pAllocateInfo->level);
798     }
799     loader_platform_thread_unlock_mutex(&objLock);
800 
801     return result;
802 }
803 
explicit_AllocateDescriptorSets(VkDevice device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)804 VkResult explicit_AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
805                                          VkDescriptorSet *pDescriptorSets) {
806     VkBool32 skipCall = VK_FALSE;
807     loader_platform_thread_lock_mutex(&objLock);
808     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
809     skipCall |=
810         validate_descriptor_pool(device, pAllocateInfo->descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false);
811     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
812         skipCall |= validate_descriptor_set_layout(device, pAllocateInfo->pSetLayouts[i],
813                                                    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, false);
814     }
815     loader_platform_thread_unlock_mutex(&objLock);
816     if (skipCall)
817         return VK_ERROR_VALIDATION_FAILED_EXT;
818 
819     VkResult result =
820         get_dispatch_table(object_tracker_device_table_map, device)->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
821 
822     if (VK_SUCCESS == result) {
823         loader_platform_thread_lock_mutex(&objLock);
824         for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
825             alloc_descriptor_set(device, pAllocateInfo->descriptorPool, pDescriptorSets[i],
826                                  VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT);
827         }
828         loader_platform_thread_unlock_mutex(&objLock);
829     }
830 
831     return result;
832 }
833 
explicit_FreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)834 void explicit_FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
835                                  const VkCommandBuffer *pCommandBuffers) {
836     loader_platform_thread_lock_mutex(&objLock);
837     validate_command_pool(device, commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false);
838     validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
839     loader_platform_thread_unlock_mutex(&objLock);
840 
841     get_dispatch_table(object_tracker_device_table_map, device)
842         ->FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
843 
844     loader_platform_thread_lock_mutex(&objLock);
845     for (uint32_t i = 0; i < commandBufferCount; i++) {
846         free_command_buffer(device, commandPool, *pCommandBuffers);
847         pCommandBuffers++;
848     }
849     loader_platform_thread_unlock_mutex(&objLock);
850 }
851 
explicit_DestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)852 void explicit_DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
853     loader_platform_thread_lock_mutex(&objLock);
854     // A swapchain's images are implicitly deleted when the swapchain is deleted.
855     // Remove this swapchain's images from our map of such images.
856     unordered_map<uint64_t, OBJTRACK_NODE *>::iterator itr = swapchainImageMap.begin();
857     while (itr != swapchainImageMap.end()) {
858         OBJTRACK_NODE *pNode = (*itr).second;
859         if (pNode->parentObj == (uint64_t)(swapchain)) {
860             swapchainImageMap.erase(itr++);
861         } else {
862             ++itr;
863         }
864     }
865     destroy_swapchain_khr(device, swapchain);
866     loader_platform_thread_unlock_mutex(&objLock);
867 
868     get_dispatch_table(object_tracker_device_table_map, device)->DestroySwapchainKHR(device, swapchain, pAllocator);
869 }
870 
explicit_FreeMemory(VkDevice device,VkDeviceMemory mem,const VkAllocationCallbacks * pAllocator)871 void explicit_FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) {
872     loader_platform_thread_lock_mutex(&objLock);
873     validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
874     loader_platform_thread_unlock_mutex(&objLock);
875 
876     get_dispatch_table(object_tracker_device_table_map, device)->FreeMemory(device, mem, pAllocator);
877 
878     loader_platform_thread_lock_mutex(&objLock);
879     destroy_device_memory(device, mem);
880     loader_platform_thread_unlock_mutex(&objLock);
881 }
882 
explicit_FreeDescriptorSets(VkDevice device,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)883 VkResult explicit_FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count,
884                                      const VkDescriptorSet *pDescriptorSets) {
885     loader_platform_thread_lock_mutex(&objLock);
886     validate_descriptor_pool(device, descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false);
887     validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
888     loader_platform_thread_unlock_mutex(&objLock);
889     VkResult result = get_dispatch_table(object_tracker_device_table_map, device)
890                           ->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
891 
892     loader_platform_thread_lock_mutex(&objLock);
893     for (uint32_t i = 0; i < count; i++) {
894         free_descriptor_set(device, descriptorPool, *pDescriptorSets++);
895     }
896     loader_platform_thread_unlock_mutex(&objLock);
897     return result;
898 }
899 
explicit_DestroyDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,const VkAllocationCallbacks * pAllocator)900 void explicit_DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
901     VkBool32 skipCall = VK_FALSE;
902     loader_platform_thread_lock_mutex(&objLock);
903     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
904     skipCall |= validate_descriptor_pool(device, descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false);
905     loader_platform_thread_unlock_mutex(&objLock);
906     if (skipCall) {
907         return;
908     }
909     // A DescriptorPool's descriptor sets are implicitly deleted when the pool is deleted.
910     // Remove this pool's descriptor sets from our descriptorSet map.
911     loader_platform_thread_lock_mutex(&objLock);
912     unordered_map<uint64_t, OBJTRACK_NODE *>::iterator itr = VkDescriptorSetMap.begin();
913     while (itr != VkDescriptorSetMap.end()) {
914         OBJTRACK_NODE *pNode = (*itr).second;
915         auto del_itr = itr++;
916         if (pNode->parentObj == (uint64_t)(descriptorPool)) {
917             destroy_descriptor_set(device, (VkDescriptorSet)((*del_itr).first));
918         }
919     }
920     destroy_descriptor_pool(device, descriptorPool);
921     loader_platform_thread_unlock_mutex(&objLock);
922     get_dispatch_table(object_tracker_device_table_map, device)->DestroyDescriptorPool(device, descriptorPool, pAllocator);
923 }
924 
explicit_DestroyCommandPool(VkDevice device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)925 void explicit_DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
926     VkBool32 skipCall = VK_FALSE;
927     loader_platform_thread_lock_mutex(&objLock);
928     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
929     skipCall |= validate_command_pool(device, commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false);
930     loader_platform_thread_unlock_mutex(&objLock);
931     if (skipCall) {
932         return;
933     }
934     loader_platform_thread_lock_mutex(&objLock);
935     // A CommandPool's command buffers are implicitly deleted when the pool is deleted.
936     // Remove this pool's cmdBuffers from our cmd buffer map.
937     unordered_map<uint64_t, OBJTRACK_NODE *>::iterator itr = VkCommandBufferMap.begin();
938     unordered_map<uint64_t, OBJTRACK_NODE *>::iterator del_itr;
939     while (itr != VkCommandBufferMap.end()) {
940         OBJTRACK_NODE *pNode = (*itr).second;
941         del_itr = itr++;
942         if (pNode->parentObj == (uint64_t)(commandPool)) {
943             destroy_command_buffer(reinterpret_cast<VkCommandBuffer>((*del_itr).first),
944                                    reinterpret_cast<VkCommandBuffer>((*del_itr).first));
945         }
946     }
947     destroy_command_pool(device, commandPool);
948     loader_platform_thread_unlock_mutex(&objLock);
949     get_dispatch_table(object_tracker_device_table_map, device)->DestroyCommandPool(device, commandPool, pAllocator);
950 }
951 
explicit_GetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pCount,VkImage * pSwapchainImages)952 VkResult explicit_GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, VkImage *pSwapchainImages) {
953     VkBool32 skipCall = VK_FALSE;
954     loader_platform_thread_lock_mutex(&objLock);
955     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
956     loader_platform_thread_unlock_mutex(&objLock);
957     if (skipCall)
958         return VK_ERROR_VALIDATION_FAILED_EXT;
959 
960     VkResult result = get_dispatch_table(object_tracker_device_table_map, device)
961                           ->GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages);
962 
963     if (pSwapchainImages != NULL) {
964         loader_platform_thread_lock_mutex(&objLock);
965         for (uint32_t i = 0; i < *pCount; i++) {
966             create_swapchain_image_obj(device, pSwapchainImages[i], swapchain);
967         }
968         loader_platform_thread_unlock_mutex(&objLock);
969     }
970     return result;
971 }
972 
973 // TODO: Add special case to codegen to cover validating all the pipelines instead of just the first
explicit_CreateGraphicsPipelines(VkDevice device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkGraphicsPipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)974 VkResult explicit_CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
975                                           const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
976                                           VkPipeline *pPipelines) {
977     VkBool32 skipCall = VK_FALSE;
978     loader_platform_thread_lock_mutex(&objLock);
979     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
980     if (pCreateInfos) {
981         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
982             if (pCreateInfos[idx0].basePipelineHandle) {
983                 skipCall |= validate_pipeline(device, pCreateInfos[idx0].basePipelineHandle,
984                                               VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, true);
985             }
986             if (pCreateInfos[idx0].layout) {
987                 skipCall |= validate_pipeline_layout(device, pCreateInfos[idx0].layout,
988                                                      VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT, false);
989             }
990             if (pCreateInfos[idx0].pStages) {
991                 for (uint32_t idx1 = 0; idx1 < pCreateInfos[idx0].stageCount; ++idx1) {
992                     if (pCreateInfos[idx0].pStages[idx1].module) {
993                         skipCall |= validate_shader_module(device, pCreateInfos[idx0].pStages[idx1].module,
994                                                            VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, false);
995                     }
996                 }
997             }
998             if (pCreateInfos[idx0].renderPass) {
999                 skipCall |=
1000                     validate_render_pass(device, pCreateInfos[idx0].renderPass, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, false);
1001             }
1002         }
1003     }
1004     if (pipelineCache) {
1005         skipCall |= validate_pipeline_cache(device, pipelineCache, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT, false);
1006     }
1007     loader_platform_thread_unlock_mutex(&objLock);
1008     if (skipCall)
1009         return VK_ERROR_VALIDATION_FAILED_EXT;
1010     VkResult result = get_dispatch_table(object_tracker_device_table_map, device)
1011                           ->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1012     loader_platform_thread_lock_mutex(&objLock);
1013     if (result == VK_SUCCESS) {
1014         for (uint32_t idx2 = 0; idx2 < createInfoCount; ++idx2) {
1015             create_pipeline(device, pPipelines[idx2], VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT);
1016         }
1017     }
1018     loader_platform_thread_unlock_mutex(&objLock);
1019     return result;
1020 }
1021 
1022 // TODO: Add special case to codegen to cover validating all the pipelines instead of just the first
explicit_CreateComputePipelines(VkDevice device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkComputePipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)1023 VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
1024                                          const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
1025                                          VkPipeline *pPipelines) {
1026     VkBool32 skipCall = VK_FALSE;
1027     loader_platform_thread_lock_mutex(&objLock);
1028     skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
1029     if (pCreateInfos) {
1030         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
1031             if (pCreateInfos[idx0].basePipelineHandle) {
1032                 skipCall |= validate_pipeline(device, pCreateInfos[idx0].basePipelineHandle,
1033                                               VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, true);
1034             }
1035             if (pCreateInfos[idx0].layout) {
1036                 skipCall |= validate_pipeline_layout(device, pCreateInfos[idx0].layout,
1037                                                      VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT, false);
1038             }
1039             if (pCreateInfos[idx0].stage.module) {
1040                 skipCall |= validate_shader_module(device, pCreateInfos[idx0].stage.module,
1041                                                    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, false);
1042             }
1043         }
1044     }
1045     if (pipelineCache) {
1046         skipCall |= validate_pipeline_cache(device, pipelineCache, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT, false);
1047     }
1048     loader_platform_thread_unlock_mutex(&objLock);
1049     if (skipCall)
1050         return VK_ERROR_VALIDATION_FAILED_EXT;
1051     VkResult result = get_dispatch_table(object_tracker_device_table_map, device)
1052                           ->CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
1053     loader_platform_thread_lock_mutex(&objLock);
1054     if (result == VK_SUCCESS) {
1055         for (uint32_t idx1 = 0; idx1 < createInfoCount; ++idx1) {
1056             create_pipeline(device, pPipelines[idx1], VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT);
1057         }
1058     }
1059     loader_platform_thread_unlock_mutex(&objLock);
1060     return result;
1061 }
1062