layers:Check all memory bindings

There are a few places in the code where we assume that an image or
buffer doesn't have a sparse binding. These cases break with sparse
bindings.

To fix I added a function to BINDING class to retrieve all memory
bindings and then updated a few spots with bad assumption to make use
of this new GetBoundMemory() function.
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index a4f0d5a..7ccd4b3 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -619,11 +619,13 @@
     // Skip validation if this image was created through WSI
     if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
         // First update CB binding in MemObj mini CB list
-        DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, image_state->binding.mem);
-        if (pMemInfo) {
-            pMemInfo->cb_bindings.insert(cb_node);
-            // Now update CBInfo's Mem reference list
-            cb_node->memObjs.insert(image_state->binding.mem);
+        for (auto mem_binding : image_state->GetBoundMemory()) {
+            DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem_binding);
+            if (pMemInfo) {
+                pMemInfo->cb_bindings.insert(cb_node);
+                // Now update CBInfo's Mem reference list
+                cb_node->memObjs.insert(mem_binding);
+            }
         }
         // Now update cb binding for image
         cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT});
@@ -647,11 +649,13 @@
 // Create binding link between given buffer node and command buffer node
 void AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_NODE *buff_node) {
     // First update CB binding in MemObj mini CB list
-    DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, buff_node->binding.mem);
-    if (pMemInfo) {
-        pMemInfo->cb_bindings.insert(cb_node);
-        // Now update CBInfo's Mem reference list
-        cb_node->memObjs.insert(buff_node->binding.mem);
+    for (auto mem_binding : buff_node->GetBoundMemory()) {
+        DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem_binding);
+        if (pMemInfo) {
+            pMemInfo->cb_bindings.insert(cb_node);
+            // Now update CBInfo's Mem reference list
+            cb_node->memObjs.insert(mem_binding);
+        }
     }
     // Now update cb binding for buffer
     cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(buff_node->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT});
@@ -5769,9 +5773,11 @@
             // Any bound cmd buffers are now invalid
             invalidateCommandBuffers(buff_node->cb_bindings,
                                      {reinterpret_cast<uint64_t &>(buff_node->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT});
-            auto mem_info = getMemObjInfo(dev_data, buff_node->binding.mem);
-            if (mem_info) {
-                RemoveBufferMemoryRange(reinterpret_cast<uint64_t &>(buffer), mem_info);
+            for (auto mem_binding : buff_node->GetBoundMemory()) {
+                auto mem_info = getMemObjInfo(dev_data, mem_binding);
+                if (mem_info) {
+                    RemoveBufferMemoryRange(reinterpret_cast<uint64_t &>(buffer), mem_info);
+                }
             }
             ClearMemoryObjectBindings(dev_data, reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
             dev_data->bufferMap.erase(buff_node->buffer);
@@ -5833,9 +5839,11 @@
 static void PostCallRecordDestroyImage(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) {
     invalidateCommandBuffers(image_state->cb_bindings, obj_struct);
     // Clean up memory mapping, bindings and range references for image
-    auto mem_info = getMemObjInfo(dev_data, image_state->binding.mem);
-    if (mem_info) {
-        RemoveImageMemoryRange(obj_struct.handle, mem_info);
+    for (auto mem_binding : image_state->GetBoundMemory()) {
+        auto mem_info = getMemObjInfo(dev_data, mem_binding);
+        if (mem_info) {
+            RemoveImageMemoryRange(obj_struct.handle, mem_info);
+        }
     }
     ClearMemoryObjectBindings(dev_data, obj_struct.handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
     // Remove image from imageMap
diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h
index 92401f8..cfc034c 100644
--- a/layers/core_validation_types.h
+++ b/layers/core_validation_types.h
@@ -177,6 +177,18 @@
     // TODO : Need to update solution to track all sparse binding data
     std::unordered_set<MEM_BINDING> sparse_bindings;
     BINDABLE() : sparse(false), binding{}, requirements{}, sparse_bindings{} {};
+    // Return unordered set of memory objects that are bound
+    std::unordered_set<VkDeviceMemory> GetBoundMemory() {
+        std::unordered_set<VkDeviceMemory> mem_set;
+        if (!sparse) {
+            mem_set.insert(binding.mem);
+        } else {
+            for (auto sb : sparse_bindings) {
+                mem_set.insert(sb.mem);
+            }
+        }
+        return mem_set;
+    }
 };
 
 class BUFFER_NODE : public BINDABLE {
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp
index d231543..4d06845 100644
--- a/layers/descriptor_sets.cpp
+++ b/layers/descriptor_sets.cpp
@@ -406,14 +406,15 @@
                             *error = error_str.str();
                             return false;
                         } else {
-                            auto mem_entry = getMemObjInfo(device_data_, buffer_node->binding.mem);
-                            if (!mem_entry) {
-                                std::stringstream error_str;
-                                error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
-                                          << " uses buffer " << buffer << " that references invalid memory "
-                                          << buffer_node->binding.mem << ".";
-                                *error = error_str.str();
-                                return false;
+                            for (auto mem_binding : buffer_node->GetBoundMemory()) {
+                                if (!getMemObjInfo(device_data_, mem_binding)) {
+                                    std::stringstream error_str;
+                                    error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
+                                              << " uses buffer " << buffer << " that references invalid memory " << mem_binding
+                                              << ".";
+                                    *error = error_str.str();
+                                    return false;
+                                }
                             }
                         }
                         if (descriptors_[i]->IsDynamic()) {