layers: LX430, Modfiy object_tracker to handle multiple instances
authorMark Lobodzinski <mark@lunarg.com>
Tue, 8 Mar 2016 22:10:00 +0000 (15:10 -0700)
committerMark Lobodzinski <mark@lunarg.com>
Tue, 8 Mar 2016 23:56:22 +0000 (16:56 -0700)
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
vk-layer-generate.py

index 179d4bd4e7ea7944689e8ab2ed632c1777f62c3f..4d570686c95eee818d4167327e27e728e321eaf9 100644 (file)
@@ -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<uint64_t, OBJTRACK_NODE*> VkPhysicalDeviceMap;
+extern unordered_map<uint64_t, OBJTRACK_NODE*> VkDeviceMap;
 extern unordered_map<uint64_t, OBJTRACK_NODE*> VkImageMap;
 extern unordered_map<uint64_t, OBJTRACK_NODE*> VkQueueMap;
 extern unordered_map<uint64_t, OBJTRACK_NODE*> 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<uint64_t>(vkObj);
     VkPhysicalDeviceMap[reinterpret_cast<uint64_t>(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<uint64_t>(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<uint64_t>(vkObj);
     VkQueueMap[reinterpret_cast<uint64_t>(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;
index 6e4fb4bdafd62e60a77d012d0834a2272427ae8b..d9ed31573bc8742cfdbd883b5ba3a82e9df874ad 100755 (executable)
@@ -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();')