diff options
| -rw-r--r-- | layers/object_tracker.h | 208 | ||||
| -rwxr-xr-x | vk-layer-generate.py | 260 |
2 files changed, 227 insertions, 241 deletions
diff --git a/layers/object_tracker.h b/layers/object_tracker.h index 54f42351..c5a2452b 100644 --- a/layers/object_tracker.h +++ b/layers/object_tracker.h @@ -450,21 +450,19 @@ static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDev static void create_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType); static void create_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType); static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType); -static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object); -static VkBool32 validate_image(VkCommandBuffer dispatchable_object, VkImage object); -static VkBool32 validate_command_buffer(VkQueue dispatchable_object, VkCommandBuffer object); -static VkBool32 validate_descriptor_set(VkCommandBuffer dispatchable_object, VkDescriptorSet object); -static VkBool32 validate_instance(VkInstance dispatchable_object, VkInstance object); -static VkBool32 validate_device(VkDevice dispatchable_object, VkDevice object); -static VkBool32 validate_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object); -static VkBool32 validate_descriptor_set_layout(VkDevice dispatchable_object, VkDescriptorSetLayout object); -static VkBool32 validate_command_pool(VkDevice dispatchable_object, VkCommandPool object); +static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object, VkDebugReportObjectTypeEXT objType, bool null_allowed); +static VkBool32 validate_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType, bool null_allowed); +static VkBool32 validate_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType, bool null_allowed); +static VkBool32 validate_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object, VkDebugReportObjectTypeEXT objType, bool null_allowed); +static VkBool32 validate_descriptor_set_layout(VkDevice dispatchable_object, VkDescriptorSetLayout object, VkDebugReportObjectTypeEXT objType, bool null_allowed); +static VkBool32 validate_command_pool(VkDevice dispatchable_object, VkCommandPool object, VkDebugReportObjectTypeEXT objType, bool null_allowed); +static VkBool32 validate_buffer(VkQueue dispatchable_object, VkBuffer object, VkDebugReportObjectTypeEXT objType, bool null_allowed); static void destroy_command_pool(VkDevice dispatchable_object, VkCommandPool object); static void destroy_command_buffer(VkCommandBuffer dispatchable_object, VkCommandBuffer object); static void destroy_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object); static void destroy_descriptor_set(VkDevice dispatchable_object, VkDescriptorSet object); -static void destroy_instance(VkInstance dispatchable_object, VkInstance object); static void destroy_device_memory(VkDevice dispatchable_object, VkDeviceMemory object); +static void destroy_swapchain_khr(VkDevice dispatchable_object, VkSwapchainKHR object); static VkBool32 set_device_memory_status(VkDevice dispatchable_object, VkDeviceMemory object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag); static VkBool32 reset_device_memory_status(VkDevice dispatchable_object, VkDeviceMemory object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag); #if 0 @@ -482,53 +480,7 @@ extern unordered_map<uint64_t, OBJTRACK_NODE*> VkSemaphoreMap; extern unordered_map<uint64_t, OBJTRACK_NODE*> VkCommandPoolMap; extern unordered_map<uint64_t, OBJTRACK_NODE*> VkCommandBufferMap; extern unordered_map<uint64_t, OBJTRACK_NODE*> VkSwapchainKHRMap; - -static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object) -{ - if ((VkImageMap.find(reinterpret_cast<uint64_t>(object)) == VkImageMap.end()) && - (swapchainImageMap.find(reinterpret_cast<uint64_t>(object)) == swapchainImageMap.end())) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkImage Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} - -static VkBool32 validate_image(VkCommandBuffer dispatchable_object, VkImage object) -{ - if ((VkImageMap.find(reinterpret_cast<uint64_t>(object)) == VkImageMap.end()) && - (swapchainImageMap.find(reinterpret_cast<uint64_t>(object)) == swapchainImageMap.end())) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkImage Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} - -static VkBool32 validate_command_buffer(VkQueue dispatchable_object, VkCommandBuffer object) -{ - if (VkCommandBufferMap.find(reinterpret_cast<uint64_t>(object)) == VkCommandBufferMap.end()) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkCommandBuffer Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} - -static VkBool32 validate_descriptor_set(VkCommandBuffer dispatchable_object, VkDescriptorSet object) -{ - if (VkDescriptorSetMap.find(reinterpret_cast<uint64_t>(object)) == VkDescriptorSetMap.end()) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkDescriptorSet Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} - -static VkBool32 validate_buffer(VkQueue dispatchable_object, VkBuffer object) -{ - if (VkBufferMap.find(reinterpret_cast<uint64_t>(object)) != VkBufferMap.end()) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkBuffer Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} +extern unordered_map<uint64_t, OBJTRACK_NODE*> VkSurfaceKHRMap; static VkBool32 set_status(VkQueue dispatchable_object, VkFence object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag) { @@ -548,24 +500,6 @@ static VkBool32 set_status(VkQueue dispatchable_object, VkFence object, VkDebugR return skipCall; } -static VkBool32 validate_semaphore(VkQueue dispatchable_object, VkSemaphore object) -{ - if (VkSemaphoreMap.find(reinterpret_cast<uint64_t>(object)) == VkSemaphoreMap.end()) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkSemaphore Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} - -static VkBool32 validate_command_buffer(VkDevice dispatchable_object, VkCommandBuffer object) -{ - if (VkCommandBufferMap.find(reinterpret_cast<uint64_t>(object)) == VkCommandBufferMap.end()) { - return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK", - "Invalid VkCommandBuffer Object %" PRIu64, reinterpret_cast<uint64_t>(object)); - } - return VK_FALSE; -} - static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDevice vkObj, VkDebugReportObjectTypeEXT objType) { log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK", @@ -582,14 +516,44 @@ static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDev numTotalObjs++; } -static void create_surface_khr(VkInstance instance, VkSurfaceKHR surface, VkDebugReportObjectTypeEXT objType) +static void create_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR vkObj, VkDebugReportObjectTypeEXT objType) { // TODO: Add tracking of surface objects + log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK", + "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType), + reinterpret_cast<uint64_t>(vkObj)); + + OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; + pNewObjNode->objType = objType; + pNewObjNode->status = OBJSTATUS_NONE; + pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj); + VkSurfaceKHRMap[(uint64_t)vkObj] = pNewObjNode; + uint32_t objIndex = objTypeToIndex(objType); + numObjs[objIndex]++; + numTotalObjs++; } -static void destroy_surface_khr(VkInstance instance, VkSurfaceKHR surface) +static void destroy_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR object) { - // TODO: Add tracking of surface objects + uint64_t object_handle = reinterpret_cast<uint64_t>(object); + if (VkSurfaceKHRMap.find(object_handle) != VkSurfaceKHRMap.end()) { + OBJTRACK_NODE* pNode = VkSurfaceKHRMap[(uint64_t)object]; + uint32_t objIndex = objTypeToIndex(pNode->objType); + assert(numTotalObjs > 0); + numTotalObjs--; + assert(numObjs[objIndex] > 0); + numObjs[objIndex]--; + log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK", + "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).", + string_VkDebugReportObjectTypeEXT(pNode->objType), reinterpret_cast<uint64_t>(object), numTotalObjs, numObjs[objIndex], + string_VkDebugReportObjectTypeEXT(pNode->objType)); + delete pNode; + VkSurfaceKHRMap.erase(object_handle); + } else { + log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK", + "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?", + object_handle); + } } static void alloc_command_buffer(VkDevice device, VkCommandPool commandPool, VkCommandBuffer vkObj, VkDebugReportObjectTypeEXT objType) @@ -687,21 +651,6 @@ static void free_descriptor_set(VkDevice device, VkDescriptorPool descriptorPool } } -static void create_swapchain_khr(VkDevice dispatchable_object, VkSwapchainKHR vkObj, VkDebugReportObjectTypeEXT objType) -{ - log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, (uint64_t) vkObj, __LINE__, OBJTRACK_NONE, "OBJTRACK", - "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType), - reinterpret_cast<uint64_t>(vkObj)); - - OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; - pNewObjNode->objType = objType; - pNewObjNode->status = OBJSTATUS_NONE; - pNewObjNode->vkObj = (uint64_t) vkObj; - VkSwapchainKHRMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode; - uint32_t objIndex = objTypeToIndex(objType); - numObjs[objIndex]++; - numTotalObjs++; -} static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType) { log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK", @@ -731,35 +680,14 @@ static void create_swapchain_image_obj(VkDevice dispatchable_object, VkImage vkO swapchainImageMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode; } -static void destroy_swapchain(VkDevice dispatchable_object, VkSwapchainKHR object) -{ - if (VkSwapchainKHRMap.find(reinterpret_cast<uint64_t>(object)) != VkSwapchainKHRMap.end()) { - OBJTRACK_NODE* pNode = VkSwapchainKHRMap[reinterpret_cast<uint64_t>(object)]; - uint32_t objIndex = objTypeToIndex(pNode->objType); - assert(numTotalObjs > 0); - numTotalObjs--; - assert(numObjs[objIndex] > 0); - numObjs[objIndex]--; - log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, pNode->objType, (uint64_t) object, __LINE__, OBJTRACK_NONE, "OBJTRACK", - "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).", - string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t) object, numTotalObjs, numObjs[objIndex], - string_VkDebugReportObjectTypeEXT(pNode->objType)); - delete pNode; - VkSwapchainKHRMap.erase(reinterpret_cast<uint64_t>(object)); - } else { - log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_NONE, "OBJTRACK", - "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?", - reinterpret_cast<uint64_t>(object)); - } -} // // Non-auto-generated API functions called by generated code // VkResult explicit_CreateInstance( - const VkInstanceCreateInfo *pCreateInfo, - const VkAllocationCallbacks * pAllocator, - VkInstance * pInstance) + const VkInstanceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkInstance *pInstance) { VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, *pInstance); @@ -820,7 +748,7 @@ VkResult explicit_EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysi { VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); - skipCall |= validate_instance(instance, instance); + skipCall |= validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall) return VK_ERROR_VALIDATION_FAILED_EXT; @@ -845,7 +773,7 @@ explicit_GetDeviceQueue( VkQueue *pQueue) { loader_platform_thread_lock_mutex(&objLock); - validate_device(device, device); + validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); get_dispatch_table(object_tracker_device_table_map, device)->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue); @@ -868,7 +796,7 @@ explicit_MapMemory( VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); skipCall |= set_device_memory_status(device, mem, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, OBJSTATUS_GPU_MEM_MAPPED); - skipCall |= validate_device(device, device); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall == VK_TRUE) return VK_ERROR_VALIDATION_FAILED_EXT; @@ -886,7 +814,7 @@ explicit_UnmapMemory( VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); skipCall |= reset_device_memory_status(device, mem, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, OBJSTATUS_GPU_MEM_MAPPED); - skipCall |= validate_device(device, device); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall == VK_TRUE) return; @@ -906,11 +834,11 @@ explicit_QueueBindSparse( for (uint32_t i = 0; i < bindInfoCount; i++) { for (uint32_t j = 0; j < pBindInfo[i].bufferBindCount; j++) - validate_buffer(queue, pBindInfo[i].pBufferBinds[j].buffer); + validate_buffer(queue, pBindInfo[i].pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, false); for (uint32_t j = 0; j < pBindInfo[i].imageOpaqueBindCount; j++) - validate_image(queue, pBindInfo[i].pImageOpaqueBinds[j].image); + validate_image(queue, pBindInfo[i].pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, false); for (uint32_t j = 0; j < pBindInfo[i].imageBindCount; j++) - validate_image(queue, pBindInfo[i].pImageBinds[j].image); + validate_image(queue, pBindInfo[i].pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, false); } loader_platform_thread_unlock_mutex(&objLock); @@ -927,8 +855,8 @@ explicit_AllocateCommandBuffers( { VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); - skipCall |= validate_device(device, device); - skipCall |= validate_command_pool(device, pAllocateInfo->commandPool); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); + skipCall |= validate_command_pool(device, pAllocateInfo->commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall) { @@ -955,10 +883,10 @@ explicit_AllocateDescriptorSets( { VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); - skipCall |= validate_device(device, device); - skipCall |= validate_descriptor_pool(device, pAllocateInfo->descriptorPool); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); + skipCall |= validate_descriptor_pool(device, pAllocateInfo->descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false); for (uint32_t i = 0; i < pAllocateInfo->setLayoutCount; i++) { - skipCall |= validate_descriptor_set_layout(device, pAllocateInfo->pSetLayouts[i]); + skipCall |= validate_descriptor_set_layout(device, pAllocateInfo->pSetLayouts[i], VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, false); } loader_platform_thread_unlock_mutex(&objLock); if (skipCall) @@ -984,8 +912,8 @@ explicit_FreeCommandBuffers( const VkCommandBuffer *pCommandBuffers) { loader_platform_thread_lock_mutex(&objLock); - validate_command_pool(device, commandPool); - validate_device(device, device); + validate_command_pool(device, commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false); + validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); get_dispatch_table(object_tracker_device_table_map, device)->FreeCommandBuffers(device, @@ -1018,7 +946,7 @@ explicit_DestroySwapchainKHR( ++itr; } } - destroy_swapchain(device, swapchain); + destroy_swapchain_khr(device, swapchain); loader_platform_thread_unlock_mutex(&objLock); get_dispatch_table(object_tracker_device_table_map, device)->DestroySwapchainKHR(device, swapchain, pAllocator); @@ -1031,7 +959,7 @@ explicit_FreeMemory( const VkAllocationCallbacks* pAllocator) { loader_platform_thread_lock_mutex(&objLock); - validate_device(device, device); + validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); get_dispatch_table(object_tracker_device_table_map, device)->FreeMemory(device, mem, pAllocator); @@ -1049,8 +977,8 @@ explicit_FreeDescriptorSets( const VkDescriptorSet *pDescriptorSets) { loader_platform_thread_lock_mutex(&objLock); - validate_descriptor_pool(device, descriptorPool); - validate_device(device, device); + validate_descriptor_pool(device, descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false); + validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); VkResult result = get_dispatch_table(object_tracker_device_table_map, device)->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); @@ -1071,8 +999,8 @@ explicit_DestroyDescriptorPool( { VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); - skipCall |= validate_device(device, device); - skipCall |= validate_descriptor_pool(device, descriptorPool); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); + skipCall |= validate_descriptor_pool(device, descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall) { return; @@ -1101,8 +1029,8 @@ explicit_DestroyCommandPool( { VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); - skipCall |= validate_device(device, device); - skipCall |= validate_command_pool(device, commandPool); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); + skipCall |= validate_command_pool(device, commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall) { return; @@ -1134,7 +1062,7 @@ explicit_GetSwapchainImagesKHR( { VkBool32 skipCall = VK_FALSE; loader_platform_thread_lock_mutex(&objLock); - skipCall |= validate_device(device, device); + skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false); loader_platform_thread_unlock_mutex(&objLock); if (skipCall) return VK_ERROR_VALIDATION_FAILED_EXT; diff --git a/vk-layer-generate.py b/vk-layer-generate.py index 54df0a55..2f93a80a 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -1402,14 +1402,41 @@ class ObjectTrackerSubcommand(Subcommand): def generate_maps(self): maps_txt = [] - for o in vulkan.core.objects: + for o in vulkan.object_type_list: maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o)) - maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> VkSwapchainKHRMap;') return "\n".join(maps_txt) + def _gather_object_uses(self, obj_list, struct_type, obj_set): + # for each member of struct_type + # add objs in obj_list to obj_set + # call self for structs + for m in vk_helper.struct_dict[struct_type]: + if vk_helper.struct_dict[struct_type][m]['type'] in obj_list: + obj_set.add(vk_helper.struct_dict[struct_type][m]['type']) + elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'): + obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set)) + return obj_set + def generate_procs(self): procs_txt = [] - for o in vulkan.core.objects: + # First parse through funcs and gather dict of all objects seen by each call + obj_use_dict = {} + proto_list = vulkan.core.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_win32_surface.protos + vulkan.ext_khr_device_swapchain.protos + for proto in proto_list: + disp_obj = proto.params[0].ty.strip('*').replace('const ', '') + if disp_obj in vulkan.object_dispatch_list: + if disp_obj not in obj_use_dict: + obj_use_dict[disp_obj] = set() + for p in proto.params[1:]: + base_type = p.ty.strip('*').replace('const ', '') + if base_type in vulkan.object_type_list: + obj_use_dict[disp_obj].add(base_type) + if vk_helper.is_type(base_type, 'struct'): + obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj]) + #for do in obj_use_dict: + # print "Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do])) + + for o in vulkan.object_type_list:# vulkan.core.objects: procs_txt.append('%s' % self.lineinfo.get()) name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o) name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] @@ -1433,40 +1460,6 @@ class ObjectTrackerSubcommand(Subcommand): procs_txt.append('}') procs_txt.append('') procs_txt.append('%s' % self.lineinfo.get()) - # TODO : This is not complete and currently requires some hand-coded function in the header - # Really we want to capture the set of all objects and their associated dispatchable objects - # that are bound by the API calls: - # foreach API Call - # foreach object type seen by call - # create validate_object(disp_obj, object) - if o in vulkan.object_dispatch_list: - procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object)' % (name, o, o)) - else: - procs_txt.append('static VkBool32 validate_%s(VkDevice dispatchable_object, %s object)' % (name, o)) - procs_txt.append('{') - if o in vulkan.object_dispatch_list: - procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o)) - procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",') - procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % o) - else: - if o == "VkPipelineCache": - procs_txt.append(' // VkPipelineCache object can be NULL if not caching') - procs_txt.append(' if (object == VK_NULL_HANDLE) return VK_TRUE;') - procs_txt.append('') - if o == "VkImage": - procs_txt.append(' // We need to validate normal image objects and those from the swapchain') - procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o)) - procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {') - else: - procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o)) - procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",') - procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o) - procs_txt.append(' }') - procs_txt.append(' return VK_FALSE;') - procs_txt.append('}') - procs_txt.append('') - procs_txt.append('') - procs_txt.append('%s' % self.lineinfo.get()) if o in vulkan.object_dispatch_list: procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o)) else: @@ -1568,6 +1561,51 @@ class ObjectTrackerSubcommand(Subcommand): procs_txt.append(' return VK_FALSE;') procs_txt.append('}') procs_txt.append('') + procs_txt.append('%s' % self.lineinfo.get()) + # Generate the permutations of validate_* functions where for each + # dispatchable object type, we have a corresponding validate_* function + # for that object and all non-dispatchable objects that are used in API + # calls with that dispatchable object. + procs_txt.append('//%s' % str(obj_use_dict)) + for do in obj_use_dict: + name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do) + name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] + # First create validate_* func for disp obj + procs_txt.append('%s' % self.lineinfo.get()) + procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do)) + procs_txt.append('{') + procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))') + procs_txt.append(' return VK_FALSE;') + procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do)) + procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",') + procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % do) + procs_txt.append(' }') + procs_txt.append(' return VK_FALSE;') + procs_txt.append('}') + procs_txt.append('') + for o in obj_use_dict[do]: + if o == do: # We already generated this case above so skip here + continue + name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o) + name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] + procs_txt.append('%s' % self.lineinfo.get()) + procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o)) + procs_txt.append('{') + procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))') + procs_txt.append(' return VK_FALSE;') + if o == "VkImage": + procs_txt.append(' // We need to validate normal image objects and those from the swapchain') + procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o)) + procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {') + else: + procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o)) + procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",') + procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o) + procs_txt.append(' }') + procs_txt.append(' return VK_FALSE;') + procs_txt.append('}') + procs_txt.append('') + procs_txt.append('') return "\n".join(procs_txt) def generate_destroy_instance(self): @@ -1578,7 +1616,7 @@ class ObjectTrackerSubcommand(Subcommand): gedi_txt.append('const VkAllocationCallbacks* pAllocator)') gedi_txt.append('{') gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);') - gedi_txt.append(' validate_instance(instance, instance);') + gedi_txt.append(' validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);') gedi_txt.append('') gedi_txt.append(' destroy_instance(instance, instance);') gedi_txt.append(' // Report any remaining objects in LL') @@ -1627,7 +1665,7 @@ class ObjectTrackerSubcommand(Subcommand): gedd_txt.append('const VkAllocationCallbacks* pAllocator)') gedd_txt.append('{') gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);') - gedd_txt.append(' validate_device(device, device);') + gedd_txt.append(' validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);') gedd_txt.append('') gedd_txt.append(' destroy_device(device, device);') gedd_txt.append(' // Report any remaining objects in LL') @@ -1658,24 +1696,71 @@ class ObjectTrackerSubcommand(Subcommand): gedd_txt.append('') return "\n".join(gedd_txt) - def generate_command_buffer_validates(self): - cbv_txt = [] - cbv_txt.append('%s' % self.lineinfo.get()) - for o in ['VkPipeline', - 'VkPipelineLayout', 'VkBuffer', 'VkEvent', 'VkQueryPool', 'VkRenderPass', 'VkFramebuffer']: - name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o) - name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] - cbv_txt.append('static VkBool32 validate_%s(VkCommandBuffer dispatchable_object, %s object)' % (name, o)) - cbv_txt.append('{') - cbv_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);') - cbv_txt.append(' if (%sMap.find(object_handle) == %sMap.end()) {' % (o, o)) - cbv_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",') - cbv_txt.append(' "Invalid %s Object 0x%%" PRIx64, object_handle);' % (o)) - cbv_txt.append(' }') - cbv_txt.append(' return VK_FALSE;') - cbv_txt.append('}') - cbv_txt.append('') - return "\n".join(cbv_txt) + def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index): + pre_code = '' + for obj in sorted(struct_uses): + name = obj + array = '' + if '[' in obj: + (name, array) = obj.split('[') + array = array.strip(']') + if isinstance(struct_uses[obj], dict): + local_prefix = '' + name = '%s%s' % (prefix, name) + ptr_type = False + if 'p' == obj[0]: + ptr_type = True + pre_code += '%sif (%s) {\n' % (indent, name) + indent += ' ' + if array != '': + idx = 'idx%s' % str(array_index) + array_index += 1 + pre_code += '%s\n' % self.lineinfo.get() + pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx) + indent += ' ' + local_prefix = '%s[%s].' % (name, idx) + elif ptr_type: + local_prefix = '%s->' % (name) + else: + local_prefix = '%s.' % (name) + tmp_pre = self._gen_obj_validate_code(struct_uses[obj], obj_type_mapping, func_name, valid_null_dict, param0_name, indent, local_prefix, array_index) + pre_code += tmp_pre + if array != '': + indent = indent[4:] + pre_code += '%s}\n' % (indent) + if ptr_type: + indent = indent[4:] + pre_code += '%s}\n' % (indent) + else: + ptype = struct_uses[obj] + dbg_obj_type = obj_type_mapping[ptype] + fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype) + fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:] + full_name = '%s%s' % (prefix, name) + null_obj_ok = 'false' + # If a valid null param is defined for this func and we have a match, allow NULL + if func_name in valid_null_dict and True in [name in pn for pn in valid_null_dict[func_name]]: + null_obj_ok = 'true' + if (array_index > 0) or '' != array: + pre_code += '%sif (%s) {\n' %(indent, full_name) + indent += ' ' + if array != '': + idx = 'idx%s' % str(array_index) + array_index += 1 + pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx) + indent += ' ' + full_name = '%s[%s]' % (full_name, idx) + pre_code += '%s\n' % self.lineinfo.get() + pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok) + if array != '': + indent = indent[4:] + pre_code += '%s}\n' % (indent) + indent = indent[4:] + pre_code += '%s}\n' % (indent) + else: + pre_code += '%s\n' % self.lineinfo.get() + pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok) + return pre_code def generate_intercept(self, proto, qual): if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]: @@ -1727,7 +1812,9 @@ class ObjectTrackerSubcommand(Subcommand): 'CreateComputePipelines' : ['basePipelineHandle'], 'BeginCommandBuffer' : ['renderPass', 'framebuffer'], 'QueueSubmit' : ['fence'], + 'AcquireNextImageKHR' : ['fence'], 'UpdateDescriptorSets' : ['pTexelBufferView'], + 'CreateSwapchainKHR' : ['oldSwapchain'], } param_count = 'NONE' # keep track of arrays passed directly into API functions for p in proto.params: @@ -1778,6 +1865,12 @@ class ObjectTrackerSubcommand(Subcommand): else: loop_params[0].append(param_name) loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type'])) + last_param_index = None + create_func = False + if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]: + create_func = True + last_param_index = -1 # For create funcs don't validate last object + struct_uses = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index]) funcs = [] mutex_unlock = False funcs.append('%s\n' % self.lineinfo.get()) @@ -1791,7 +1884,7 @@ class ObjectTrackerSubcommand(Subcommand): elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name: return "" else: - if 'Create' in proto.name or 'Alloc' in proto.name: + if create_func: typ = proto.params[-1].ty.strip('*').replace('const ', ''); name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ) name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] @@ -1816,53 +1909,19 @@ class ObjectTrackerSubcommand(Subcommand): name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] funcs.append('%s\n' % self.lineinfo.get()) destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n' -# destroy_line += ' if (result == VK_SUCCESS) {\n' destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name) -# destroy_line += ' }\n' destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n' - if len(loop_params) > 0: - using_line += ' VkBool32 skipCall = VK_FALSE;\n' + indent = ' ' + if len(struct_uses) > 0: + using_line += '%sVkBool32 skipCall = VK_FALSE;\n' % (indent) if not mutex_unlock: - using_line += ' loader_platform_thread_lock_mutex(&objLock);\n' + using_line += '%sloader_platform_thread_lock_mutex(&objLock);\n' % (indent) mutex_unlock = True - for lc,lt in zip(loop_params,loop_types): - if 0 == lc: # No looping required for these params - for opn,typ in zip(loop_params[lc],loop_types[lt]): - name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ) - name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] - if '->' in opn: - using_line += ' if (%s)\n' % (opn.split('-')[0]) - using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn) - else: - if 'AcquireNext' in proto.name and 'fence' == name: - using_line += ' if (fence != VK_NULL_HANDLE) {\n' - using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn) - using_line += ' }\n' - else: - using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn) - else: - base_param = loop_params[lc][0].split('-')[0].split('[')[0] - using_line += ' if (%s) {\n' % base_param - using_line += ' for (uint32_t i=0; i<%s; i++) {\n' % lc - for opn,typ in zip(loop_params[lc],loop_types[lt]): - name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ) - name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:] - if ',' in opn: # double-embedded loop - (inner_lc, inner_param) = opn.split(',') - using_line += ' if (%s) {\n' % inner_param - using_line += ' for (uint32_t j=0; j<%s; j++) {\n' % inner_lc - using_line += ' skipCall |= validate_%s(%s, %s[j]);\n' % (name, param0_name, inner_param) - using_line += ' }\n' - using_line += ' }\n' - elif '[' in opn: # API func param is array - using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn) - else: # struct element is array - using_line += ' skipCall |= validate_%s(%s, %s[i]);\n' % (name, param0_name, opn) - using_line += ' }\n' - using_line += ' }\n' + using_line += '// objects to validate: %s\n' % str(struct_uses) + using_line += self._gen_obj_validate_code(struct_uses, obj_type_mapping, proto.name, valid_null_object_names, param0_name, ' ', '', 0) if mutex_unlock: - using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n' - if len(loop_params) > 0: + using_line += '%sloader_platform_thread_unlock_mutex(&objLock);\n' % (indent) + if len(struct_uses) > 0: using_line += ' if (skipCall)\n' if proto.ret != "void": using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n' @@ -1934,7 +1993,6 @@ class ObjectTrackerSubcommand(Subcommand): self.generate_procs(), self.generate_destroy_instance(), self.generate_destroy_device(), - self.generate_command_buffer_validates(), self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"), self._generate_extensions(), self._generate_layer_gpa_function(extensions, |
