From b5fb36d28a5d0401ab90b839b21cb46e8af5acad Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Tue, 8 Mar 2016 15:10:00 -0700 Subject: [PATCH] layers: LX430, Modfiy object_tracker to handle multiple instances Upon DestroyInstance, OT indicated that all objects in all maps were not properly destroyed. Made this reporting work on a per-instance basis. Change-Id: I9b4eae4364a24597cb449610a31bf9b872c45225 --- layers/object_tracker.h | 33 ++++++++++++++++++++++++-- vk-layer-generate.py | 51 +++++++++++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/layers/object_tracker.h b/layers/object_tracker.h index 179d4bd4..4d570686 100644 --- a/layers/object_tracker.h +++ b/layers/object_tracker.h @@ -65,6 +65,7 @@ typedef struct _OBJTRACK_NODE { VkDebugReportObjectTypeEXT objType; // Object type identifier ObjectStatusFlags status; // Object state uint64_t parentObj; // Parent object + uint64_t belongsTo; // Object Scope -- owning device/instance } OBJTRACK_NODE; // prototype for extension functions @@ -385,12 +386,13 @@ initObjectTracker( } // -// Forward declares of generated routines +// Forward declarations // static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDevice vkObj, VkDebugReportObjectTypeEXT objType); 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_device(VkPhysicalDevice 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, VkDebugReportObjectTypeEXT objType, bool null_allowed); static VkBool32 validate_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType, bool null_allowed); @@ -419,6 +421,7 @@ static VkBool32 validate_status(VkDevice dispatchable_object, VkFence object, Vk const char *fail_msg); #endif extern unordered_map VkPhysicalDeviceMap; +extern unordered_map VkDeviceMap; extern unordered_map VkImageMap; extern unordered_map VkQueueMap; extern unordered_map VkDescriptorSetMap; @@ -438,6 +441,7 @@ static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDev OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; pNewObjNode->objType = objType; + pNewObjNode->belongsTo = (uint64_t)dispatchable_object; pNewObjNode->status = OBJSTATUS_NONE; pNewObjNode->vkObj = reinterpret_cast(vkObj); VkPhysicalDeviceMap[reinterpret_cast(vkObj)] = pNewObjNode; @@ -455,6 +459,7 @@ static void create_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR vkOb OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; pNewObjNode->objType = objType; + pNewObjNode->belongsTo = (uint64_t)dispatchable_object; pNewObjNode->status = OBJSTATUS_NONE; pNewObjNode->vkObj = (uint64_t)(vkObj); VkSurfaceKHRMap[(uint64_t)vkObj] = pNewObjNode; @@ -494,6 +499,7 @@ static void alloc_command_buffer(VkDevice device, VkCommandPool commandPool, VkC OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; pNewObjNode->objType = objType; + pNewObjNode->belongsTo = (uint64_t)device; pNewObjNode->vkObj = reinterpret_cast(vkObj); pNewObjNode->parentObj = (uint64_t) commandPool; if (level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { @@ -546,6 +552,7 @@ static void alloc_descriptor_set(VkDevice device, VkDescriptorPool descriptorPoo OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; pNewObjNode->objType = objType; + pNewObjNode->belongsTo = (uint64_t)device; pNewObjNode->status = OBJSTATUS_NONE; pNewObjNode->vkObj = (uint64_t)(vkObj); pNewObjNode->parentObj = (uint64_t) descriptorPool; @@ -593,6 +600,7 @@ static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugRep OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; pNewObjNode->objType = objType; + pNewObjNode->belongsTo = (uint64_t)dispatchable_object; pNewObjNode->status = OBJSTATUS_NONE; pNewObjNode->vkObj = reinterpret_cast(vkObj); VkQueueMap[reinterpret_cast(vkObj)] = pNewObjNode; @@ -607,6 +615,7 @@ static void create_swapchain_image_obj(VkDevice dispatchable_object, VkImage vkO (uint64_t)(vkObj)); OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; + pNewObjNode->belongsTo = (uint64_t)dispatchable_object; pNewObjNode->objType = VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; pNewObjNode->status = OBJSTATUS_NONE; pNewObjNode->vkObj = (uint64_t) vkObj; @@ -614,6 +623,23 @@ static void create_swapchain_image_obj(VkDevice dispatchable_object, VkImage vkO swapchainImageMap[(uint64_t)(vkObj)] = pNewObjNode; } +static void create_device(VkInstance dispatchable_object, VkDevice vkObj, VkDebugReportObjectTypeEXT objType) +{ + log_msg(mid(dispatchable_object), VK_DEBUG_REPORT_INFORMATION_BIT_EXT, objType, (uint64_t)(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK", + "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++, string_VkDebugReportObjectTypeEXT(objType), + (uint64_t)(vkObj)); + + OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE; + pNewObjNode->belongsTo = (uint64_t)dispatchable_object; + pNewObjNode->objType = objType; + pNewObjNode->status = OBJSTATUS_NONE; + pNewObjNode->vkObj = (uint64_t)(vkObj); + VkDeviceMap[(uint64_t)vkObj] = pNewObjNode; + uint32_t objIndex = objTypeToIndex(objType); + numObjs[objIndex]++; + numTotalObjs++; +} + // // Non-auto-generated API functions called by generated code // @@ -708,7 +734,10 @@ explicit_CreateDevice( createDeviceRegisterExtensions(pCreateInfo, *pDevice); - create_device(*pDevice, *pDevice, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT); + if (VkPhysicalDeviceMap.find((uint64_t)gpu) != VkPhysicalDeviceMap.end()) { + OBJTRACK_NODE* pNewObjNode = VkPhysicalDeviceMap[(uint64_t)gpu]; + create_device((VkInstance)pNewObjNode->belongsTo, *pDevice, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT); + } loader_platform_thread_unlock_mutex(&objLock); return result; diff --git a/vk-layer-generate.py b/vk-layer-generate.py index 6e4fb4bd..d9ed3157 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -856,6 +856,7 @@ class ObjectTrackerSubcommand(Subcommand): procs_txt.append(' (uint64_t)(vkObj));') procs_txt.append('') procs_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;') + procs_txt.append(' pNewObjNode->belongsTo = (uint64_t)dispatchable_object;') procs_txt.append(' pNewObjNode->objType = objType;') procs_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;') procs_txt.append(' pNewObjNode->vkObj = (uint64_t)(vkObj);') @@ -1026,17 +1027,33 @@ class ObjectTrackerSubcommand(Subcommand): gedi_txt.append('') gedi_txt.append(' destroy_instance(instance, instance);') gedi_txt.append(' // Report any remaining objects in LL') + gedi_txt.append('') + gedi_txt.append(' for (auto iit = VkDeviceMap.begin(); iit != VkDeviceMap.end();) {') + gedi_txt.append(' OBJTRACK_NODE* pNode = iit->second;') + gedi_txt.append(' if (pNode->belongsTo == (uint64_t)instance) {') + gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",') + gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),') + gedi_txt.append(' pNode->vkObj);') for o in vulkan.core.objects: - if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue']: + if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice']: continue - gedi_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o)) - gedi_txt.append(' OBJTRACK_NODE* pNode = it->second;') - gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",') - gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),') - gedi_txt.append(' pNode->vkObj);') - gedi_txt.append(' }') - gedi_txt.append(' %sMap.clear();' % (o)) - gedi_txt.append('') + gedi_txt.append(' for (auto idt = %sMap.begin(); idt != %sMap.end();) {' % (o, o)) + gedi_txt.append(' OBJTRACK_NODE* pNode = idt->second;') + gedi_txt.append(' if (pNode->belongsTo == iit->first) {') + gedi_txt.append(' log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",') + gedi_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),') + gedi_txt.append(' pNode->vkObj);') + gedi_txt.append(' %sMap.erase(idt++);' % o ) + gedi_txt.append(' } else {') + gedi_txt.append(' ++idt;') + gedi_txt.append(' }') + gedi_txt.append(' }') + gedi_txt.append(' VkDeviceMap.erase(iit++);') + gedi_txt.append(' } else {') + gedi_txt.append(' ++iit;') + gedi_txt.append(' }') + gedi_txt.append(' }') + gedi_txt.append('') gedi_txt.append(' dispatch_key key = get_dispatch_key(instance);') gedi_txt.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, instance);') gedi_txt.append(' pInstanceTable->DestroyInstance(instance, pAllocator);') @@ -1074,18 +1091,22 @@ class ObjectTrackerSubcommand(Subcommand): 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') + gedd_txt.append(' // Report any remaining objects associated with this VkDevice object in LL') for o in vulkan.core.objects: # DescriptorSets and Command Buffers are destroyed through their pools, not explicitly if o in ['VkInstance', 'VkPhysicalDevice', 'VkQueue', 'VkDevice', 'VkDescriptorSet', 'VkCommandBuffer']: continue - gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end(); ++it) {' % (o, o)) + gedd_txt.append(' for (auto it = %sMap.begin(); it != %sMap.end();) {' % (o, o)) gedd_txt.append(' OBJTRACK_NODE* pNode = it->second;') - gedd_txt.append(' log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",') - gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),') - gedd_txt.append(' pNode->vkObj);') + gedd_txt.append(' if (pNode->belongsTo == (uint64_t)device) {') + gedd_txt.append(' log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, pNode->objType, pNode->vkObj, __LINE__, OBJTRACK_OBJECT_LEAK, "OBJTRACK",') + gedd_txt.append(' "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkDebugReportObjectTypeEXT(pNode->objType),') + gedd_txt.append(' pNode->vkObj);') + gedd_txt.append(' %sMap.erase(it++);' % o ) + gedd_txt.append(' } else {') + gedd_txt.append(' ++it;') + gedd_txt.append(' }') gedd_txt.append(' }') - gedd_txt.append(' %sMap.clear();' % (o)) gedd_txt.append('') gedd_txt.append(" // Clean up Queue's MemRef Linked Lists") gedd_txt.append(' destroyQueueMemRefLists();') -- 2.34.1