layers: Remove cb_bindings when CB is reset
authorTobin Ehlis <tobine@google.com>
Fri, 8 Jul 2016 18:33:45 +0000 (12:33 -0600)
committerTobin Ehlis <tobine@google.com>
Fri, 8 Jul 2016 18:33:45 +0000 (12:33 -0600)
When a CB is reset (or freed) make sure to remove it from any image/buffer
cb_bindings that it was tied to.

layers/core_validation.cpp
layers/core_validation_types.h

index bcf86eb..9c1e679 100644 (file)
@@ -505,6 +505,7 @@ static bool addCommandBufferBindingImage(layer_data *dev_data, GLOBAL_CB_NODE *c
             // Now update CBInfo's Mem reference list
             cb_node->memObjs.insert(img_node->mem);
         }
+        cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(img_node->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT});
     }
     // Now update cb binding for image
     img_node->cb_bindings.insert(cb_node);
@@ -522,6 +523,7 @@ static bool addCommandBufferBindingBuffer(layer_data *dev_data, GLOBAL_CB_NODE *
         pMemInfo->commandBufferBindings.insert(cb_node->commandBuffer);
         // Now update CBInfo's Mem reference list
         cb_node->memObjs.insert(buff_node->mem);
+        cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(buff_node->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT});
     }
     // Now update cb binding for buffer
     buff_node->cb_bindings.insert(cb_node);
@@ -3717,6 +3719,25 @@ static bool addCmd(layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd,
     }
     return skip_call;
 }
+// For a given object, if cb_node is in that objects cb_bindings, remove cb_node
+static void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) {
+    switch (object->type) {
+    case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: {
+        auto img_node = getImageNode(dev_data, reinterpret_cast<VkImage>(object->handle));
+        if (img_node)
+            img_node->cb_bindings.erase(cb_node);
+        break;
+    }
+    case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: {
+        auto buf_node = getBufferNode(dev_data, reinterpret_cast<VkBuffer>(object->handle));
+        if (buf_node)
+            buf_node->cb_bindings.erase(cb_node);
+        break;
+    }
+    default:
+        assert(0); // unhandled object type
+    }
+}
 // Reset the command buffer state
 //  Maintain the createInfo and set state to CB_NEW, but clear all other state
 static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
@@ -3773,6 +3794,10 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
         pCB->eventUpdates.clear();
         pCB->queryUpdates.clear();
 
+        // Remove object bindings
+        for (auto obj : pCB->object_bindings) {
+            removeCommandBufferBinding(dev_data, &obj, pCB);
+        }
         // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list
         for (auto framebuffer : pCB->framebuffers) {
             auto fb_node = getFramebuffer(dev_data, framebuffer);
index 78f098e..69b3f2a 100644 (file)
@@ -77,6 +77,14 @@ struct VK_OBJECT {
     VkDebugReportObjectTypeEXT type;
 };
 
+inline bool operator==(VK_OBJECT a, VK_OBJECT b) NOEXCEPT { return a.handle == b.handle && a.type == b.type; }
+
+namespace std {
+template <> struct hash<VK_OBJECT> {
+    size_t operator()(VK_OBJECT obj) const NOEXCEPT { return hash<uint64_t>()(obj.handle) ^ hash<uint32_t>()(obj.type); }
+};
+}
+
 struct DESCRIPTOR_POOL_NODE {
     VkDescriptorPool pool;
     uint32_t maxSets;       // Max descriptor sets allowed in this pool
@@ -162,6 +170,7 @@ class IMAGE_NODE : public BASE_NODE {
 };
 
 // Simple struct to hold handle and type of object so they can be uniquely identified and looked up in appropriate map
+// TODO : Unify this with VK_OBJECT above
 struct MT_OBJ_HANDLE_TYPE {
     uint64_t handle;
     VkDebugReportObjectTypeEXT type;
@@ -488,9 +497,11 @@ struct GLOBAL_CB_NODE : public BASE_NODE {
     uint32_t activeSubpass;
     VkFramebuffer activeFramebuffer;
     std::unordered_set<VkFramebuffer> framebuffers;
-    // Unified data struct to track dependencies that have been broken
-    //  These are either destroyed objects, or updated descriptor sets
+    // Unified data structs to track objects bound to this command buffer as well as object
+    //  dependencies that have been broken : either destroyed objects, or updated descriptor sets
+    std::unordered_set<VK_OBJECT> object_bindings;
     std::vector<VK_OBJECT> broken_bindings;
+
     std::unordered_set<VkEvent> waitedEvents;
     std::vector<VkEvent> writeEventsBeforeWait;
     std::vector<VkEvent> events;