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