• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015-2019 The Khronos Group Inc.
2  * Copyright (c) 2015-2019 Valve Corporation
3  * Copyright (c) 2015-2019 LunarG, Inc.
4  * Copyright (C) 2015-2019 Google Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Mark Lobodzinski <mark@lunarg.com>
19  * Author: Jon Ashburn <jon@lunarg.com>
20  * Author: Tobin Ehlis <tobin@lunarg.com>
21  */
22 
23 #include "chassis.h"
24 
25 #include "object_lifetime_validation.h"
26 
27 uint64_t object_track_index = 0;
28 
29 // Add new queue to head of global queue list
AddQueueInfo(VkDevice device,uint32_t queue_node_index,VkQueue queue)30 void ObjectLifetimes::AddQueueInfo(VkDevice device, uint32_t queue_node_index, VkQueue queue) {
31     auto queueItem = queue_info_map.find(queue);
32     if (queueItem == queue_info_map.end()) {
33         ObjTrackQueueInfo *p_queue_info = new ObjTrackQueueInfo;
34         if (p_queue_info != NULL) {
35             memset(p_queue_info, 0, sizeof(ObjTrackQueueInfo));
36             p_queue_info->queue = queue;
37             p_queue_info->queue_node_index = queue_node_index;
38             queue_info_map[queue] = p_queue_info;
39         } else {
40             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, HandleToUint64(queue),
41                     kVUID_ObjectTracker_InternalError,
42                     "ERROR:  VK_ERROR_OUT_OF_HOST_MEMORY -- could not allocate memory for Queue Information");
43         }
44     }
45 }
46 
47 // Destroy memRef lists and free all memory
DestroyQueueDataStructures(VkDevice device)48 void ObjectLifetimes::DestroyQueueDataStructures(VkDevice device) {
49     for (auto queue_item : queue_info_map) {
50         delete queue_item.second;
51     }
52     queue_info_map.clear();
53 
54     // Destroy the items in the queue map
55     auto queue = object_map[kVulkanObjectTypeQueue].begin();
56     while (queue != object_map[kVulkanObjectTypeQueue].end()) {
57         uint32_t obj_index = queue->second->object_type;
58         assert(num_total_objects > 0);
59         num_total_objects--;
60         assert(num_objects[obj_index] > 0);
61         num_objects[obj_index]--;
62         log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, queue->second->handle,
63                 kVUID_ObjectTracker_Info, "OBJ_STAT Destroy Queue obj %s (%" PRIu64 " total objs remain & %" PRIu64 " Queue objs).",
64                 report_data->FormatHandle(queue->second->handle).c_str(), num_total_objects, num_objects[obj_index]);
65         delete queue->second;
66         queue = object_map[kVulkanObjectTypeQueue].erase(queue);
67     }
68 }
69 
70 // Check Queue type flags for selected queue operations
ValidateQueueFlags(VkQueue queue,const char * function)71 void ObjectLifetimes::ValidateQueueFlags(VkQueue queue, const char *function) {
72     auto queue_item = queue_info_map.find(queue);
73     if (queue_item != queue_info_map.end()) {
74         ObjTrackQueueInfo *pQueueInfo = queue_item->second;
75         if (pQueueInfo != NULL) {
76             if ((queue_family_properties[pQueueInfo->queue_node_index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) == 0) {
77                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, HandleToUint64(queue),
78                         "VUID-vkQueueBindSparse-queuetype",
79                         "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_SPARSE_BINDING_BIT not set.", function);
80             }
81         }
82     }
83 }
84 
85 // Look for this device object in any of the instance child devices lists.
86 // NOTE: This is of dubious value. In most circumstances Vulkan will die a flaming death if a dispatchable object is invalid.
87 // However, if this layer is loaded first and GetProcAddress is used to make API calls, it will detect bad DOs.
ValidateDeviceObject(uint64_t device_handle,const char * invalid_handle_code,const char * wrong_device_code)88 bool ObjectLifetimes::ValidateDeviceObject(uint64_t device_handle, const char *invalid_handle_code, const char *wrong_device_code) {
89     auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
90     auto instance_object_lifetime_data = GetObjectLifetimeData(instance_data->object_dispatch);
91     for (auto object : instance_object_lifetime_data->object_map[kVulkanObjectTypeDevice]) {
92         if (object.second->handle == device_handle) return false;
93     }
94     return log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device_handle,
95                    invalid_handle_code, "Invalid Device Object %s.", report_data->FormatHandle(device_handle).c_str());
96 }
97 
AllocateCommandBuffer(VkDevice device,const VkCommandPool command_pool,const VkCommandBuffer command_buffer,VkCommandBufferLevel level)98 void ObjectLifetimes::AllocateCommandBuffer(VkDevice device, const VkCommandPool command_pool, const VkCommandBuffer command_buffer,
99                                             VkCommandBufferLevel level) {
100     log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
101             HandleToUint64(command_buffer), kVUID_ObjectTracker_Info, "OBJ[0x%" PRIxLEAST64 "] : CREATE %s object %s.",
102             object_track_index++, "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT",
103             report_data->FormatHandle(command_buffer).c_str());
104 
105     ObjTrackState *pNewObjNode = new ObjTrackState;
106     pNewObjNode->object_type = kVulkanObjectTypeCommandBuffer;
107     pNewObjNode->handle = HandleToUint64(command_buffer);
108     pNewObjNode->parent_object = HandleToUint64(command_pool);
109     if (level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
110         pNewObjNode->status = OBJSTATUS_COMMAND_BUFFER_SECONDARY;
111     } else {
112         pNewObjNode->status = OBJSTATUS_NONE;
113     }
114     object_map[kVulkanObjectTypeCommandBuffer][HandleToUint64(command_buffer)] = pNewObjNode;
115     num_objects[kVulkanObjectTypeCommandBuffer]++;
116     num_total_objects++;
117 }
118 
ValidateCommandBuffer(VkDevice device,VkCommandPool command_pool,VkCommandBuffer command_buffer)119 bool ObjectLifetimes::ValidateCommandBuffer(VkDevice device, VkCommandPool command_pool, VkCommandBuffer command_buffer) {
120     bool skip = false;
121     uint64_t object_handle = HandleToUint64(command_buffer);
122     if (object_map[kVulkanObjectTypeCommandBuffer].find(object_handle) != object_map[kVulkanObjectTypeCommandBuffer].end()) {
123         ObjTrackState *pNode = object_map[kVulkanObjectTypeCommandBuffer][HandleToUint64(command_buffer)];
124 
125         if (pNode->parent_object != HandleToUint64(command_pool)) {
126             skip |=
127                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, object_handle,
128                         "VUID-vkFreeCommandBuffers-pCommandBuffers-parent",
129                         "FreeCommandBuffers is attempting to free Command Buffer %s belonging to Command Pool %s from pool %s).",
130                         report_data->FormatHandle(command_buffer).c_str(), report_data->FormatHandle(pNode->parent_object).c_str(),
131                         report_data->FormatHandle(command_pool).c_str());
132         }
133     } else {
134         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, object_handle,
135                         "VUID-vkFreeCommandBuffers-pCommandBuffers-00048", "Invalid %s Object %s.",
136                         object_string[kVulkanObjectTypeCommandBuffer], report_data->FormatHandle(object_handle).c_str());
137     }
138     return skip;
139 }
140 
AllocateDescriptorSet(VkDevice device,VkDescriptorPool descriptor_pool,VkDescriptorSet descriptor_set)141 void ObjectLifetimes::AllocateDescriptorSet(VkDevice device, VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set) {
142     log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
143             HandleToUint64(descriptor_set), kVUID_ObjectTracker_Info, "OBJ[0x%" PRIxLEAST64 "] : CREATE %s object %s.",
144             object_track_index++, "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT",
145             report_data->FormatHandle(descriptor_set).c_str());
146 
147     ObjTrackState *pNewObjNode = new ObjTrackState;
148     pNewObjNode->object_type = kVulkanObjectTypeDescriptorSet;
149     pNewObjNode->status = OBJSTATUS_NONE;
150     pNewObjNode->handle = HandleToUint64(descriptor_set);
151     pNewObjNode->parent_object = HandleToUint64(descriptor_pool);
152     object_map[kVulkanObjectTypeDescriptorSet][HandleToUint64(descriptor_set)] = pNewObjNode;
153     num_objects[kVulkanObjectTypeDescriptorSet]++;
154     num_total_objects++;
155 
156     auto itr = object_map[kVulkanObjectTypeDescriptorPool].find(HandleToUint64(descriptor_pool));
157     if (itr != object_map[kVulkanObjectTypeDescriptorPool].end()) {
158         ObjTrackState *pPoolNode = itr->second;
159         pPoolNode->child_objects->insert(HandleToUint64(descriptor_set));
160     }
161 }
162 
ValidateDescriptorSet(VkDevice device,VkDescriptorPool descriptor_pool,VkDescriptorSet descriptor_set)163 bool ObjectLifetimes::ValidateDescriptorSet(VkDevice device, VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set) {
164     bool skip = false;
165     uint64_t object_handle = HandleToUint64(descriptor_set);
166     auto dsItem = object_map[kVulkanObjectTypeDescriptorSet].find(object_handle);
167     if (dsItem != object_map[kVulkanObjectTypeDescriptorSet].end()) {
168         ObjTrackState *pNode = dsItem->second;
169 
170         if (pNode->parent_object != HandleToUint64(descriptor_pool)) {
171             skip |=
172                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, object_handle,
173                         "VUID-vkFreeDescriptorSets-pDescriptorSets-parent",
174                         "FreeDescriptorSets is attempting to free descriptorSet %s"
175                         " belonging to Descriptor Pool %s from pool %s).",
176                         report_data->FormatHandle(descriptor_set).c_str(), report_data->FormatHandle(pNode->parent_object).c_str(),
177                         report_data->FormatHandle(descriptor_pool).c_str());
178         }
179     } else {
180         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, object_handle,
181                         "VUID-vkFreeDescriptorSets-pDescriptorSets-00310", "Invalid %s Object %s.",
182                         object_string[kVulkanObjectTypeDescriptorSet], report_data->FormatHandle(object_handle).c_str());
183     }
184     return skip;
185 }
186 
187 template <typename DispObj>
ValidateDescriptorWrite(DispObj disp,VkWriteDescriptorSet const * desc,bool isPush)188 bool ObjectLifetimes::ValidateDescriptorWrite(DispObj disp, VkWriteDescriptorSet const *desc, bool isPush) {
189     bool skip = false;
190 
191     if (!isPush && desc->dstSet) {
192         skip |= ValidateObject(disp, desc->dstSet, kVulkanObjectTypeDescriptorSet, false, "VUID-VkWriteDescriptorSet-dstSet-00320",
193                                "VUID-VkWriteDescriptorSet-commonparent");
194     }
195 
196     if ((desc->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
197         (desc->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
198         for (uint32_t idx2 = 0; idx2 < desc->descriptorCount; ++idx2) {
199             skip |= ValidateObject(disp, desc->pTexelBufferView[idx2], kVulkanObjectTypeBufferView, false,
200                                    "VUID-VkWriteDescriptorSet-descriptorType-00323", "VUID-VkWriteDescriptorSet-commonparent");
201         }
202     }
203 
204     if ((desc->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
205         (desc->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || (desc->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
206         (desc->descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
207         for (uint32_t idx3 = 0; idx3 < desc->descriptorCount; ++idx3) {
208             skip |= ValidateObject(disp, desc->pImageInfo[idx3].imageView, kVulkanObjectTypeImageView, false,
209                                    "VUID-VkWriteDescriptorSet-descriptorType-00326", "VUID-VkDescriptorImageInfo-commonparent");
210         }
211     }
212 
213     if ((desc->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
214         (desc->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
215         (desc->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
216         (desc->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
217         for (uint32_t idx4 = 0; idx4 < desc->descriptorCount; ++idx4) {
218             if (desc->pBufferInfo[idx4].buffer) {
219                 skip |= ValidateObject(disp, desc->pBufferInfo[idx4].buffer, kVulkanObjectTypeBuffer, false,
220                                        "VUID-VkDescriptorBufferInfo-buffer-parameter", kVUIDUndefined);
221             }
222         }
223     }
224 
225     return skip;
226 }
227 
PreCallValidateCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t set,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites)228 bool ObjectLifetimes::PreCallValidateCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
229                                                              VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
230                                                              const VkWriteDescriptorSet *pDescriptorWrites) {
231     bool skip = false;
232     skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false,
233                            "VUID-vkCmdPushDescriptorSetKHR-commandBuffer-parameter", "VUID-vkCmdPushDescriptorSetKHR-commonparent");
234     skip |= ValidateObject(commandBuffer, layout, kVulkanObjectTypePipelineLayout, false,
235                            "VUID-vkCmdPushDescriptorSetKHR-layout-parameter", "VUID-vkCmdPushDescriptorSetKHR-commonparent");
236     if (pDescriptorWrites) {
237         for (uint32_t index0 = 0; index0 < descriptorWriteCount; ++index0) {
238             skip |= ValidateDescriptorWrite(commandBuffer, &pDescriptorWrites[index0], true);
239         }
240     }
241     return skip;
242 }
243 
CreateQueue(VkDevice device,VkQueue vkObj)244 void ObjectLifetimes::CreateQueue(VkDevice device, VkQueue vkObj) {
245     log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, HandleToUint64(vkObj),
246             kVUID_ObjectTracker_Info, "OBJ[0x%" PRIxLEAST64 "] : CREATE %s object %s", object_track_index++,
247             "VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT", report_data->FormatHandle(vkObj).c_str());
248 
249     ObjTrackState *p_obj_node = NULL;
250     auto queue_item = object_map[kVulkanObjectTypeQueue].find(HandleToUint64(vkObj));
251     if (queue_item == object_map[kVulkanObjectTypeQueue].end()) {
252         p_obj_node = new ObjTrackState;
253         object_map[kVulkanObjectTypeQueue][HandleToUint64(vkObj)] = p_obj_node;
254         num_objects[kVulkanObjectTypeQueue]++;
255         num_total_objects++;
256     } else {
257         p_obj_node = queue_item->second;
258     }
259     p_obj_node->object_type = kVulkanObjectTypeQueue;
260     p_obj_node->status = OBJSTATUS_NONE;
261     p_obj_node->handle = HandleToUint64(vkObj);
262 }
263 
CreateSwapchainImageObject(VkDevice dispatchable_object,VkImage swapchain_image,VkSwapchainKHR swapchain)264 void ObjectLifetimes::CreateSwapchainImageObject(VkDevice dispatchable_object, VkImage swapchain_image, VkSwapchainKHR swapchain) {
265     log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
266             HandleToUint64(swapchain_image), kVUID_ObjectTracker_Info, "OBJ[0x%" PRIxLEAST64 "] : CREATE %s object %s.",
267             object_track_index++, "SwapchainImage", report_data->FormatHandle(swapchain_image).c_str());
268 
269     ObjTrackState *pNewObjNode = new ObjTrackState;
270     pNewObjNode->object_type = kVulkanObjectTypeImage;
271     pNewObjNode->status = OBJSTATUS_NONE;
272     pNewObjNode->handle = HandleToUint64(swapchain_image);
273     pNewObjNode->parent_object = HandleToUint64(swapchain);
274     swapchainImageMap[HandleToUint64(swapchain_image)] = pNewObjNode;
275 }
276 
DeviceReportUndestroyedObjects(VkDevice device,VulkanObjectType object_type,const std::string & error_code)277 bool ObjectLifetimes::DeviceReportUndestroyedObjects(VkDevice device, VulkanObjectType object_type, const std::string &error_code) {
278     bool skip = false;
279     for (const auto &item : object_map[object_type]) {
280         const ObjTrackState *object_info = item.second;
281         skip |=
282             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], object_info->handle, error_code,
283                     "OBJ ERROR : For device %s, %s object %s has not been destroyed.", report_data->FormatHandle(device).c_str(),
284                     object_string[object_type], report_data->FormatHandle(object_info->handle).c_str());
285     }
286     return skip;
287 }
288 
DeviceDestroyUndestroyedObjects(VkDevice device,VulkanObjectType object_type)289 void ObjectLifetimes::DeviceDestroyUndestroyedObjects(VkDevice device, VulkanObjectType object_type) {
290     while (!object_map[object_type].empty()) {
291         auto item = object_map[object_type].begin();
292 
293         ObjTrackState *object_info = item->second;
294         DestroyObjectSilently(object_info->handle, object_type);
295     }
296 }
297 
PreCallValidateDestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)298 bool ObjectLifetimes::PreCallValidateDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
299     bool skip = false;
300 
301     // We validate here for coverage, though we'd not have made it this for with a bad instance.
302     skip |= ValidateObject(instance, instance, kVulkanObjectTypeInstance, true, "VUID-vkDestroyInstance-instance-parameter",
303                            kVUIDUndefined);
304 
305     // Validate that child devices have been destroyed
306     for (const auto &iit : object_map[kVulkanObjectTypeDevice]) {
307         ObjTrackState *pNode = iit.second;
308 
309         VkDevice device = reinterpret_cast<VkDevice>(pNode->handle);
310         VkDebugReportObjectTypeEXT debug_object_type = get_debug_report_enum[pNode->object_type];
311 
312         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, debug_object_type, pNode->handle,
313                         kVUID_ObjectTracker_ObjectLeak, "OBJ ERROR : %s object %s has not been destroyed.",
314                         string_VkDebugReportObjectTypeEXT(debug_object_type), report_data->FormatHandle(pNode->handle).c_str());
315 
316         // Report any remaining objects in LL
317         skip |= ReportUndestroyedObjects(device, "VUID-vkDestroyInstance-instance-00629");
318 
319         skip |= ValidateDestroyObject(instance, device, kVulkanObjectTypeDevice, pAllocator,
320                                       "VUID-vkDestroyInstance-instance-00630", "VUID-vkDestroyInstance-instance-00631");
321     }
322 
323     ValidateDestroyObject(instance, instance, kVulkanObjectTypeInstance, pAllocator, "VUID-vkDestroyInstance-instance-00630",
324                           "VUID-vkDestroyInstance-instance-00631");
325 
326     return skip;
327 }
328 
PreCallValidateEnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)329 bool ObjectLifetimes::PreCallValidateEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
330                                                               VkPhysicalDevice *pPhysicalDevices) {
331     bool skip = ValidateObject(instance, instance, kVulkanObjectTypeInstance, false,
332                                "VUID-vkEnumeratePhysicalDevices-instance-parameter", kVUIDUndefined);
333     return skip;
334 }
335 
PostCallRecordEnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices,VkResult result)336 void ObjectLifetimes::PostCallRecordEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
337                                                              VkPhysicalDevice *pPhysicalDevices, VkResult result) {
338     if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) return;
339     if (pPhysicalDevices) {
340         for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
341             CreateObject(instance, pPhysicalDevices[i], kVulkanObjectTypePhysicalDevice, nullptr);
342         }
343     }
344 }
345 
PreCallRecordDestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)346 void ObjectLifetimes::PreCallRecordDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
347     // Destroy physical devices
348     for (auto iit = object_map[kVulkanObjectTypePhysicalDevice].begin();
349          iit != object_map[kVulkanObjectTypePhysicalDevice].end();) {
350         ObjTrackState *pNode = iit->second;
351         VkPhysicalDevice physical_device = reinterpret_cast<VkPhysicalDevice>(pNode->handle);
352         RecordDestroyObject(instance, physical_device, kVulkanObjectTypePhysicalDevice);
353         iit = object_map[kVulkanObjectTypePhysicalDevice].begin();
354     }
355 
356     // Destroy child devices
357     for (auto iit = object_map[kVulkanObjectTypeDevice].begin(); iit != object_map[kVulkanObjectTypeDevice].end();) {
358         ObjTrackState *pNode = iit->second;
359         VkDevice device = reinterpret_cast<VkDevice>(pNode->handle);
360         DestroyUndestroyedObjects(device);
361 
362         RecordDestroyObject(instance, device, kVulkanObjectTypeDevice);
363         iit = object_map[kVulkanObjectTypeDevice].begin();
364     }
365 
366     object_map[kVulkanObjectTypeDevice].clear();
367 }
368 
PostCallRecordDestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)369 void ObjectLifetimes::PostCallRecordDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
370     RecordDestroyObject(instance, instance, kVulkanObjectTypeInstance);
371 }
372 
PreCallValidateDestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)373 bool ObjectLifetimes::PreCallValidateDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
374     bool skip = false;
375     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, true, "VUID-vkDestroyDevice-device-parameter", kVUIDUndefined);
376     skip |= ValidateDestroyObject(physical_device, device, kVulkanObjectTypeDevice, pAllocator, "VUID-vkDestroyDevice-device-00379",
377                                   "VUID-vkDestroyDevice-device-00380");
378     // Report any remaining objects associated with this VkDevice object in LL
379     skip |= ReportUndestroyedObjects(device, "VUID-vkDestroyDevice-device-00378");
380 
381     return skip;
382 }
383 
PreCallRecordDestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)384 void ObjectLifetimes::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
385     auto instance_data = GetLayerDataPtr(get_dispatch_key(physical_device), layer_data_map);
386     ValidationObject *validation_data = GetValidationObject(instance_data->object_dispatch, LayerObjectTypeObjectTracker);
387     ObjectLifetimes *object_lifetimes = static_cast<ObjectLifetimes *>(validation_data);
388     object_lifetimes->RecordDestroyObject(physical_device, device, kVulkanObjectTypeDevice);
389     DestroyUndestroyedObjects(device);
390 
391     // Clean up Queue's MemRef Linked Lists
392     DestroyQueueDataStructures(device);
393 }
394 
PreCallValidateGetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)395 bool ObjectLifetimes::PreCallValidateGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex,
396                                                     VkQueue *pQueue) {
397     bool skip = false;
398     skip |=
399         ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkGetDeviceQueue-device-parameter", kVUIDUndefined);
400     return skip;
401 }
402 
PostCallRecordGetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)403 void ObjectLifetimes::PostCallRecordGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex,
404                                                    VkQueue *pQueue) {
405     CreateQueue(device, *pQueue);
406     AddQueueInfo(device, queueFamilyIndex, *pQueue);
407 }
408 
PreCallValidateGetDeviceQueue2(VkDevice device,const VkDeviceQueueInfo2 * pQueueInfo,VkQueue * pQueue)409 bool ObjectLifetimes::PreCallValidateGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *pQueueInfo, VkQueue *pQueue) {
410     return ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkGetDeviceQueue2-device-parameter",
411                           kVUIDUndefined);
412 }
413 
PostCallRecordGetDeviceQueue2(VkDevice device,const VkDeviceQueueInfo2 * pQueueInfo,VkQueue * pQueue)414 void ObjectLifetimes::PostCallRecordGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *pQueueInfo, VkQueue *pQueue) {
415     CreateQueue(device, *pQueue);
416     AddQueueInfo(device, pQueueInfo->queueFamilyIndex, *pQueue);
417 }
418 
PreCallValidateUpdateDescriptorSets(VkDevice device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)419 bool ObjectLifetimes::PreCallValidateUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
420                                                           const VkWriteDescriptorSet *pDescriptorWrites,
421                                                           uint32_t descriptorCopyCount,
422                                                           const VkCopyDescriptorSet *pDescriptorCopies) {
423     bool skip = false;
424     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkUpdateDescriptorSets-device-parameter",
425                            kVUIDUndefined);
426     if (pDescriptorCopies) {
427         for (uint32_t idx0 = 0; idx0 < descriptorCopyCount; ++idx0) {
428             if (pDescriptorCopies[idx0].dstSet) {
429                 skip |= ValidateObject(device, pDescriptorCopies[idx0].dstSet, kVulkanObjectTypeDescriptorSet, false,
430                                        "VUID-VkCopyDescriptorSet-dstSet-parameter", "VUID-VkCopyDescriptorSet-commonparent");
431             }
432             if (pDescriptorCopies[idx0].srcSet) {
433                 skip |= ValidateObject(device, pDescriptorCopies[idx0].srcSet, kVulkanObjectTypeDescriptorSet, false,
434                                        "VUID-VkCopyDescriptorSet-srcSet-parameter", "VUID-VkCopyDescriptorSet-commonparent");
435             }
436         }
437     }
438     if (pDescriptorWrites) {
439         for (uint32_t idx1 = 0; idx1 < descriptorWriteCount; ++idx1) {
440             skip |= ValidateDescriptorWrite(device, &pDescriptorWrites[idx1], false);
441         }
442     }
443     return skip;
444 }
445 
PreCallValidateResetDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorPoolResetFlags flags)446 bool ObjectLifetimes::PreCallValidateResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
447                                                          VkDescriptorPoolResetFlags flags) {
448     bool skip = false;
449 
450     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkResetDescriptorPool-device-parameter",
451                            kVUIDUndefined);
452     skip |=
453         ValidateObject(device, descriptorPool, kVulkanObjectTypeDescriptorPool, false,
454                        "VUID-vkResetDescriptorPool-descriptorPool-parameter", "VUID-vkResetDescriptorPool-descriptorPool-parent");
455 
456     auto itr = object_map[kVulkanObjectTypeDescriptorPool].find(HandleToUint64(descriptorPool));
457     if (itr != object_map[kVulkanObjectTypeDescriptorPool].end()) {
458         ObjTrackState *pPoolNode = itr->second;
459         for (auto set : *pPoolNode->child_objects) {
460             skip |= ValidateDestroyObject(device, (VkDescriptorSet)set, kVulkanObjectTypeDescriptorSet, nullptr, kVUIDUndefined,
461                                           kVUIDUndefined);
462         }
463     }
464     return skip;
465 }
466 
PreCallRecordResetDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorPoolResetFlags flags)467 void ObjectLifetimes::PreCallRecordResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
468                                                        VkDescriptorPoolResetFlags flags) {
469     // A DescriptorPool's descriptor sets are implicitly deleted when the pool is reset. Remove this pool's descriptor sets from
470     // our descriptorSet map.
471     auto itr = object_map[kVulkanObjectTypeDescriptorPool].find(HandleToUint64(descriptorPool));
472     if (itr != object_map[kVulkanObjectTypeDescriptorPool].end()) {
473         ObjTrackState *pPoolNode = itr->second;
474         for (auto set : *pPoolNode->child_objects) {
475             RecordDestroyObject(device, (VkDescriptorSet)set, kVulkanObjectTypeDescriptorSet);
476         }
477         pPoolNode->child_objects->clear();
478     }
479 }
480 
PreCallValidateBeginCommandBuffer(VkCommandBuffer command_buffer,const VkCommandBufferBeginInfo * begin_info)481 bool ObjectLifetimes::PreCallValidateBeginCommandBuffer(VkCommandBuffer command_buffer,
482                                                         const VkCommandBufferBeginInfo *begin_info) {
483     bool skip = false;
484     skip |= ValidateObject(command_buffer, command_buffer, kVulkanObjectTypeCommandBuffer, false,
485                            "VUID-vkBeginCommandBuffer-commandBuffer-parameter", kVUIDUndefined);
486     if (begin_info) {
487         ObjTrackState *pNode = object_map[kVulkanObjectTypeCommandBuffer][HandleToUint64(command_buffer)];
488         if ((begin_info->pInheritanceInfo) && (pNode->status & OBJSTATUS_COMMAND_BUFFER_SECONDARY) &&
489             (begin_info->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
490             skip |= ValidateObject(command_buffer, begin_info->pInheritanceInfo->framebuffer, kVulkanObjectTypeFramebuffer, true,
491                                    "VUID-VkCommandBufferBeginInfo-flags-00055", "VUID-VkCommandBufferInheritanceInfo-commonparent");
492             skip |= ValidateObject(command_buffer, begin_info->pInheritanceInfo->renderPass, kVulkanObjectTypeRenderPass, false,
493                                    "VUID-VkCommandBufferBeginInfo-flags-00053", "VUID-VkCommandBufferInheritanceInfo-commonparent");
494         }
495     }
496     return skip;
497 }
498 
PreCallValidateGetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages)499 bool ObjectLifetimes::PreCallValidateGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
500                                                            uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
501     bool skip = false;
502     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkGetSwapchainImagesKHR-device-parameter",
503                            "VUID-vkGetSwapchainImagesKHR-commonparent");
504     skip |= ValidateObject(device, swapchain, kVulkanObjectTypeSwapchainKHR, false,
505                            "VUID-vkGetSwapchainImagesKHR-swapchain-parameter", "VUID-vkGetSwapchainImagesKHR-commonparent");
506     return skip;
507 }
508 
PostCallRecordGetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages,VkResult result)509 void ObjectLifetimes::PostCallRecordGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
510                                                           VkImage *pSwapchainImages, VkResult result) {
511     if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) return;
512     if (pSwapchainImages != NULL) {
513         for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
514             CreateSwapchainImageObject(device, pSwapchainImages[i], swapchain);
515         }
516     }
517 }
518 
PreCallValidateCreateDescriptorSetLayout(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout)519 bool ObjectLifetimes::PreCallValidateCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
520                                                                const VkAllocationCallbacks *pAllocator,
521                                                                VkDescriptorSetLayout *pSetLayout) {
522     bool skip = false;
523     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkCreateDescriptorSetLayout-device-parameter",
524                            kVUIDUndefined);
525     if (pCreateInfo) {
526         if (pCreateInfo->pBindings) {
527             for (uint32_t binding_index = 0; binding_index < pCreateInfo->bindingCount; ++binding_index) {
528                 const VkDescriptorSetLayoutBinding &binding = pCreateInfo->pBindings[binding_index];
529                 const bool is_sampler_type = binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
530                                              binding.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
531                 if (binding.pImmutableSamplers && is_sampler_type) {
532                     for (uint32_t index2 = 0; index2 < binding.descriptorCount; ++index2) {
533                         const VkSampler sampler = binding.pImmutableSamplers[index2];
534                         skip |= ValidateObject(device, sampler, kVulkanObjectTypeSampler, false,
535                                                "VUID-VkDescriptorSetLayoutBinding-descriptorType-00282", kVUIDUndefined);
536                     }
537                 }
538             }
539         }
540     }
541     return skip;
542 }
543 
PostCallRecordCreateDescriptorSetLayout(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout,VkResult result)544 void ObjectLifetimes::PostCallRecordCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
545                                                               const VkAllocationCallbacks *pAllocator,
546                                                               VkDescriptorSetLayout *pSetLayout, VkResult result) {
547     if (result != VK_SUCCESS) return;
548     CreateObject(device, *pSetLayout, kVulkanObjectTypeDescriptorSetLayout, pAllocator);
549 }
550 
ValidateSamplerObjects(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo)551 bool ObjectLifetimes::ValidateSamplerObjects(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo) {
552     bool skip = false;
553     if (pCreateInfo->pBindings) {
554         for (uint32_t index1 = 0; index1 < pCreateInfo->bindingCount; ++index1) {
555             for (uint32_t index2 = 0; index2 < pCreateInfo->pBindings[index1].descriptorCount; ++index2) {
556                 if (pCreateInfo->pBindings[index1].pImmutableSamplers) {
557                     skip |=
558                         ValidateObject(device, pCreateInfo->pBindings[index1].pImmutableSamplers[index2], kVulkanObjectTypeSampler,
559                                        true, "VUID-VkDescriptorSetLayoutBinding-descriptorType-00282", kVUIDUndefined);
560                 }
561             }
562         }
563     }
564     return skip;
565 }
566 
PreCallValidateGetDescriptorSetLayoutSupport(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)567 bool ObjectLifetimes::PreCallValidateGetDescriptorSetLayoutSupport(VkDevice device,
568                                                                    const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
569                                                                    VkDescriptorSetLayoutSupport *pSupport) {
570     bool skip = ValidateObject(device, device, kVulkanObjectTypeDevice, false,
571                                "VUID-vkGetDescriptorSetLayoutSupport-device-parameter", kVUIDUndefined);
572     if (pCreateInfo) {
573         skip |= ValidateSamplerObjects(device, pCreateInfo);
574     }
575     return skip;
576 }
PreCallValidateGetDescriptorSetLayoutSupportKHR(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)577 bool ObjectLifetimes::PreCallValidateGetDescriptorSetLayoutSupportKHR(VkDevice device,
578                                                                       const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
579                                                                       VkDescriptorSetLayoutSupport *pSupport) {
580     bool skip = ValidateObject(device, device, kVulkanObjectTypeDevice, false,
581                                "VUID-vkGetDescriptorSetLayoutSupportKHR-device-parameter", kVUIDUndefined);
582     if (pCreateInfo) {
583         skip |= ValidateSamplerObjects(device, pCreateInfo);
584     }
585     return skip;
586 }
587 
PreCallValidateGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties * pQueueFamilyProperties)588 bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
589                                                                             uint32_t *pQueueFamilyPropertyCount,
590                                                                             VkQueueFamilyProperties *pQueueFamilyProperties) {
591     return ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
592                           "VUID-vkGetPhysicalDeviceQueueFamilyProperties-physicalDevice-parameter", kVUIDUndefined);
593 }
594 
PostCallRecordGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties * pQueueFamilyProperties)595 void ObjectLifetimes::PostCallRecordGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
596                                                                            uint32_t *pQueueFamilyPropertyCount,
597                                                                            VkQueueFamilyProperties *pQueueFamilyProperties) {
598     if (pQueueFamilyProperties != NULL) {
599         if (queue_family_properties.size() < *pQueueFamilyPropertyCount) {
600             queue_family_properties.resize(*pQueueFamilyPropertyCount);
601         }
602         for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; i++) {
603             queue_family_properties[i] = pQueueFamilyProperties[i];
604         }
605     }
606 }
607 
PostCallRecordCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance,VkResult result)608 void ObjectLifetimes::PostCallRecordCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
609                                                    VkInstance *pInstance, VkResult result) {
610     if (result != VK_SUCCESS) return;
611     CreateObject(*pInstance, *pInstance, kVulkanObjectTypeInstance, pAllocator);
612 }
613 
PreCallValidateAllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)614 bool ObjectLifetimes::PreCallValidateAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
615                                                             VkCommandBuffer *pCommandBuffers) {
616     bool skip = false;
617     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkAllocateCommandBuffers-device-parameter",
618                            kVUIDUndefined);
619     skip |= ValidateObject(device, pAllocateInfo->commandPool, kVulkanObjectTypeCommandPool, false,
620                            "VUID-VkCommandBufferAllocateInfo-commandPool-parameter", kVUIDUndefined);
621     return skip;
622 }
623 
PostCallRecordAllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers,VkResult result)624 void ObjectLifetimes::PostCallRecordAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
625                                                            VkCommandBuffer *pCommandBuffers, VkResult result) {
626     if (result != VK_SUCCESS) return;
627     for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
628         AllocateCommandBuffer(device, pAllocateInfo->commandPool, pCommandBuffers[i], pAllocateInfo->level);
629     }
630 }
631 
PreCallValidateAllocateDescriptorSets(VkDevice device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)632 bool ObjectLifetimes::PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
633                                                             VkDescriptorSet *pDescriptorSets) {
634     bool skip = false;
635     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkAllocateDescriptorSets-device-parameter",
636                            kVUIDUndefined);
637     skip |= ValidateObject(device, pAllocateInfo->descriptorPool, kVulkanObjectTypeDescriptorPool, false,
638                            "VUID-VkDescriptorSetAllocateInfo-descriptorPool-parameter",
639                            "VUID-VkDescriptorSetAllocateInfo-commonparent");
640     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
641         skip |= ValidateObject(device, pAllocateInfo->pSetLayouts[i], kVulkanObjectTypeDescriptorSetLayout, false,
642                                "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-parameter",
643                                "VUID-VkDescriptorSetAllocateInfo-commonparent");
644     }
645     return skip;
646 }
647 
PostCallRecordAllocateDescriptorSets(VkDevice device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets,VkResult result)648 void ObjectLifetimes::PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
649                                                            VkDescriptorSet *pDescriptorSets, VkResult result) {
650     if (result != VK_SUCCESS) return;
651     for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
652         AllocateDescriptorSet(device, pAllocateInfo->descriptorPool, pDescriptorSets[i]);
653     }
654 }
655 
PreCallValidateFreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)656 bool ObjectLifetimes::PreCallValidateFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
657                                                         const VkCommandBuffer *pCommandBuffers) {
658     bool skip = false;
659     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkFreeCommandBuffers-device-parameter",
660                            kVUIDUndefined);
661     skip |= ValidateObject(device, commandPool, kVulkanObjectTypeCommandPool, false,
662                            "VUID-vkFreeCommandBuffers-commandPool-parameter", "VUID-vkFreeCommandBuffers-commandPool-parent");
663     for (uint32_t i = 0; i < commandBufferCount; i++) {
664         if (pCommandBuffers[i] != VK_NULL_HANDLE) {
665             skip |= ValidateCommandBuffer(device, commandPool, pCommandBuffers[i]);
666             skip |= ValidateDestroyObject(device, pCommandBuffers[i], kVulkanObjectTypeCommandBuffer, nullptr, kVUIDUndefined,
667                                           kVUIDUndefined);
668         }
669     }
670     return skip;
671 }
672 
PreCallRecordFreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)673 void ObjectLifetimes::PreCallRecordFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
674                                                       const VkCommandBuffer *pCommandBuffers) {
675     for (uint32_t i = 0; i < commandBufferCount; i++) {
676         RecordDestroyObject(device, pCommandBuffers[i], kVulkanObjectTypeCommandBuffer);
677     }
678 }
679 
PreCallValidateDestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)680 bool ObjectLifetimes::PreCallValidateDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
681                                                          const VkAllocationCallbacks *pAllocator) {
682     return ValidateDestroyObject(device, swapchain, kVulkanObjectTypeSwapchainKHR, pAllocator,
683                                  "VUID-vkDestroySwapchainKHR-swapchain-01283", "VUID-vkDestroySwapchainKHR-swapchain-01284");
684 }
685 
PreCallRecordDestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)686 void ObjectLifetimes::PreCallRecordDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
687                                                        const VkAllocationCallbacks *pAllocator) {
688     RecordDestroyObject(device, swapchain, kVulkanObjectTypeSwapchainKHR);
689     std::unordered_map<uint64_t, ObjTrackState *>::iterator itr = swapchainImageMap.begin();
690     while (itr != swapchainImageMap.end()) {
691         ObjTrackState *pNode = (*itr).second;
692         if (pNode->parent_object == HandleToUint64(swapchain)) {
693             delete pNode;
694             auto delete_item = itr++;
695             swapchainImageMap.erase(delete_item);
696         } else {
697             ++itr;
698         }
699     }
700 }
701 
PreCallValidateFreeDescriptorSets(VkDevice device,VkDescriptorPool descriptorPool,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets)702 bool ObjectLifetimes::PreCallValidateFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
703                                                         uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets) {
704     bool skip = false;
705     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkFreeDescriptorSets-device-parameter",
706                            kVUIDUndefined);
707     skip |= ValidateObject(device, descriptorPool, kVulkanObjectTypeDescriptorPool, false,
708                            "VUID-vkFreeDescriptorSets-descriptorPool-parameter", "VUID-vkFreeDescriptorSets-descriptorPool-parent");
709     for (uint32_t i = 0; i < descriptorSetCount; i++) {
710         if (pDescriptorSets[i] != VK_NULL_HANDLE) {
711             skip |= ValidateDescriptorSet(device, descriptorPool, pDescriptorSets[i]);
712             skip |= ValidateDestroyObject(device, pDescriptorSets[i], kVulkanObjectTypeDescriptorSet, nullptr, kVUIDUndefined,
713                                           kVUIDUndefined);
714         }
715     }
716     return skip;
717 }
PreCallRecordFreeDescriptorSets(VkDevice device,VkDescriptorPool descriptorPool,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets)718 void ObjectLifetimes::PreCallRecordFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount,
719                                                       const VkDescriptorSet *pDescriptorSets) {
720     ObjTrackState *pPoolNode = nullptr;
721     auto itr = object_map[kVulkanObjectTypeDescriptorPool].find(HandleToUint64(descriptorPool));
722     if (itr != object_map[kVulkanObjectTypeDescriptorPool].end()) {
723         pPoolNode = itr->second;
724     }
725     for (uint32_t i = 0; i < descriptorSetCount; i++) {
726         RecordDestroyObject(device, pDescriptorSets[i], kVulkanObjectTypeDescriptorSet);
727         if (pPoolNode) {
728             pPoolNode->child_objects->erase(HandleToUint64(pDescriptorSets[i]));
729         }
730     }
731 }
732 
PreCallValidateDestroyDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,const VkAllocationCallbacks * pAllocator)733 bool ObjectLifetimes::PreCallValidateDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
734                                                            const VkAllocationCallbacks *pAllocator) {
735     bool skip = false;
736     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkDestroyDescriptorPool-device-parameter",
737                            kVUIDUndefined);
738     skip |= ValidateObject(device, descriptorPool, kVulkanObjectTypeDescriptorPool, true,
739                            "VUID-vkDestroyDescriptorPool-descriptorPool-parameter",
740                            "VUID-vkDestroyDescriptorPool-descriptorPool-parent");
741 
742     auto itr = object_map[kVulkanObjectTypeDescriptorPool].find(HandleToUint64(descriptorPool));
743     if (itr != object_map[kVulkanObjectTypeDescriptorPool].end()) {
744         ObjTrackState *pPoolNode = itr->second;
745         for (auto set : *pPoolNode->child_objects) {
746             skip |= ValidateDestroyObject(device, (VkDescriptorSet)set, kVulkanObjectTypeDescriptorSet, nullptr, kVUIDUndefined,
747                                           kVUIDUndefined);
748         }
749     }
750     skip |= ValidateDestroyObject(device, descriptorPool, kVulkanObjectTypeDescriptorPool, pAllocator,
751                                   "VUID-vkDestroyDescriptorPool-descriptorPool-00304",
752                                   "VUID-vkDestroyDescriptorPool-descriptorPool-00305");
753     return skip;
754 }
PreCallRecordDestroyDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,const VkAllocationCallbacks * pAllocator)755 void ObjectLifetimes::PreCallRecordDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
756                                                          const VkAllocationCallbacks *pAllocator) {
757     auto itr = object_map[kVulkanObjectTypeDescriptorPool].find(HandleToUint64(descriptorPool));
758     if (itr != object_map[kVulkanObjectTypeDescriptorPool].end()) {
759         ObjTrackState *pPoolNode = itr->second;
760         for (auto set : *pPoolNode->child_objects) {
761             RecordDestroyObject(device, (VkDescriptorSet)set, kVulkanObjectTypeDescriptorSet);
762         }
763         pPoolNode->child_objects->clear();
764     }
765     RecordDestroyObject(device, descriptorPool, kVulkanObjectTypeDescriptorPool);
766 }
767 
PreCallValidateDestroyCommandPool(VkDevice device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)768 bool ObjectLifetimes::PreCallValidateDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
769                                                         const VkAllocationCallbacks *pAllocator) {
770     bool skip = false;
771     skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, "VUID-vkDestroyCommandPool-device-parameter",
772                            kVUIDUndefined);
773     skip |= ValidateObject(device, commandPool, kVulkanObjectTypeCommandPool, true,
774                            "VUID-vkDestroyCommandPool-commandPool-parameter", "VUID-vkDestroyCommandPool-commandPool-parent");
775     auto itr = object_map[kVulkanObjectTypeCommandBuffer].begin();
776     auto del_itr = itr;
777     while (itr != object_map[kVulkanObjectTypeCommandBuffer].end()) {
778         ObjTrackState *pNode = (*itr).second;
779         del_itr = itr++;
780         if (pNode->parent_object == HandleToUint64(commandPool)) {
781             skip |= ValidateCommandBuffer(device, commandPool, reinterpret_cast<VkCommandBuffer>((*del_itr).first));
782             skip |= ValidateDestroyObject(device, reinterpret_cast<VkCommandBuffer>((*del_itr).first),
783                                           kVulkanObjectTypeCommandBuffer, nullptr, kVUIDUndefined, kVUIDUndefined);
784         }
785     }
786     skip |= ValidateDestroyObject(device, commandPool, kVulkanObjectTypeCommandPool, pAllocator,
787                                   "VUID-vkDestroyCommandPool-commandPool-00042", "VUID-vkDestroyCommandPool-commandPool-00043");
788     return skip;
789 }
790 
PreCallRecordDestroyCommandPool(VkDevice device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)791 void ObjectLifetimes::PreCallRecordDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
792                                                       const VkAllocationCallbacks *pAllocator) {
793     auto itr = object_map[kVulkanObjectTypeCommandBuffer].begin();
794     auto del_itr = itr;
795     // A CommandPool's cmd buffers are implicitly deleted when pool is deleted. Remove this pool's cmdBuffers from cmd buffer map.
796     while (itr != object_map[kVulkanObjectTypeCommandBuffer].end()) {
797         ObjTrackState *pNode = (*itr).second;
798         del_itr = itr++;
799         if (pNode->parent_object == HandleToUint64(commandPool)) {
800             RecordDestroyObject(device, reinterpret_cast<VkCommandBuffer>((*del_itr).first), kVulkanObjectTypeCommandBuffer);
801         }
802     }
803     RecordDestroyObject(device, commandPool, kVulkanObjectTypeCommandPool);
804 }
805 
PreCallValidateGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2KHR * pQueueFamilyProperties)806 bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
807                                                                              uint32_t *pQueueFamilyPropertyCount,
808                                                                              VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
809     return ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
810                           "VUID-vkGetPhysicalDeviceQueueFamilyProperties2-physicalDevice-parameter", kVUIDUndefined);
811 }
812 
PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2 * pQueueFamilyProperties)813 bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
814                                                                                 uint32_t *pQueueFamilyPropertyCount,
815                                                                                 VkQueueFamilyProperties2 *pQueueFamilyProperties) {
816     return ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
817                           "VUID-vkGetPhysicalDeviceQueueFamilyProperties2-physicalDevice-parameter", kVUIDUndefined);
818 }
819 
PostCallRecordGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2KHR * pQueueFamilyProperties)820 void ObjectLifetimes::PostCallRecordGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
821                                                                             uint32_t *pQueueFamilyPropertyCount,
822                                                                             VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
823     if (pQueueFamilyProperties != NULL) {
824         if (queue_family_properties.size() < *pQueueFamilyPropertyCount) {
825             queue_family_properties.resize(*pQueueFamilyPropertyCount);
826         }
827         for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; i++) {
828             queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties;
829         }
830     }
831 }
832 
PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2KHR * pQueueFamilyProperties)833 void ObjectLifetimes::PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(
834     VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
835     if (pQueueFamilyProperties != NULL) {
836         if (queue_family_properties.size() < *pQueueFamilyPropertyCount) {
837             queue_family_properties.resize(*pQueueFamilyPropertyCount);
838         }
839         for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; i++) {
840             queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties;
841         }
842     }
843 }
844 
PreCallValidateGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPropertiesKHR * pProperties)845 bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
846                                                                            uint32_t *pPropertyCount,
847                                                                            VkDisplayPropertiesKHR *pProperties) {
848     return ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
849                           "VUID-vkGetPhysicalDeviceDisplayPropertiesKHR-physicalDevice-parameter", kVUIDUndefined);
850 }
851 
PostCallRecordGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPropertiesKHR * pProperties,VkResult result)852 void ObjectLifetimes::PostCallRecordGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
853                                                                           VkDisplayPropertiesKHR *pProperties, VkResult result) {
854     if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) return;
855     if (pProperties) {
856         for (uint32_t i = 0; i < *pPropertyCount; ++i) {
857             CreateObject(physicalDevice, pProperties[i].display, kVulkanObjectTypeDisplayKHR, nullptr);
858         }
859     }
860 }
861 
PreCallValidateGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModePropertiesKHR * pProperties)862 bool ObjectLifetimes::PreCallValidateGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
863                                                                  uint32_t *pPropertyCount,
864                                                                  VkDisplayModePropertiesKHR *pProperties) {
865     bool skip = false;
866     skip |= ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
867                            "VUID-vkGetDisplayModePropertiesKHR-physicalDevice-parameter", kVUIDUndefined);
868     skip |= ValidateObject(physicalDevice, display, kVulkanObjectTypeDisplayKHR, false,
869                            "VUID-vkGetDisplayModePropertiesKHR-display-parameter", kVUIDUndefined);
870 
871     return skip;
872 }
873 
PostCallRecordGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModePropertiesKHR * pProperties,VkResult result)874 void ObjectLifetimes::PostCallRecordGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
875                                                                 uint32_t *pPropertyCount, VkDisplayModePropertiesKHR *pProperties,
876                                                                 VkResult result) {
877     if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) return;
878     if (pProperties) {
879         for (uint32_t i = 0; i < *pPropertyCount; ++i) {
880             CreateObject(physicalDevice, pProperties[i].displayMode, kVulkanObjectTypeDisplayModeKHR, nullptr);
881         }
882     }
883 }
884 
PreCallValidateGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayProperties2KHR * pProperties)885 bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
886                                                                             uint32_t *pPropertyCount,
887                                                                             VkDisplayProperties2KHR *pProperties) {
888     return ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
889                           "VUID-vkGetPhysicalDeviceDisplayProperties2KHR-physicalDevice-parameter", kVUIDUndefined);
890 }
891 
PostCallRecordGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayProperties2KHR * pProperties,VkResult result)892 void ObjectLifetimes::PostCallRecordGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
893                                                                            uint32_t *pPropertyCount,
894                                                                            VkDisplayProperties2KHR *pProperties, VkResult result) {
895     if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) return;
896     for (uint32_t index = 0; index < *pPropertyCount; ++index) {
897         CreateObject(physicalDevice, pProperties[index].displayProperties.display, kVulkanObjectTypeDisplayKHR, nullptr);
898     }
899 }
900 
PreCallValidateGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModeProperties2KHR * pProperties)901 bool ObjectLifetimes::PreCallValidateGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
902                                                                   uint32_t *pPropertyCount,
903                                                                   VkDisplayModeProperties2KHR *pProperties) {
904     bool skip = false;
905     skip |= ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
906                            "VUID-vkGetDisplayModeProperties2KHR-physicalDevice-parameter", kVUIDUndefined);
907     skip |= ValidateObject(physicalDevice, display, kVulkanObjectTypeDisplayKHR, false,
908                            "VUID-vkGetDisplayModeProperties2KHR-display-parameter", kVUIDUndefined);
909 
910     return skip;
911 }
912 
PostCallRecordGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModeProperties2KHR * pProperties,VkResult result)913 void ObjectLifetimes::PostCallRecordGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
914                                                                  uint32_t *pPropertyCount, VkDisplayModeProperties2KHR *pProperties,
915                                                                  VkResult result) {
916     if ((result != VK_SUCCESS) && (result != VK_INCOMPLETE)) return;
917     for (uint32_t index = 0; index < *pPropertyCount; ++index) {
918         CreateObject(physicalDevice, pProperties[index].displayModeProperties.displayMode, kVulkanObjectTypeDisplayModeKHR,
919                      nullptr);
920     }
921 }
922