layers: MR105, Add aliasing check for buffer/image overlap
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 8627e29..fdd8cf2 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -59,6 +59,8 @@
     VkLayerInstanceDispatchTable      *instance_dispatch_table;
     VkBool32                           wsi_enabled;
     uint64_t                           currentFenceId;
+    VkPhysicalDeviceProperties         properties;
+    unordered_map<VkDeviceMemory, vector<MEMORY_RANGE>>          bufferRanges, imageRanges;
     // Maps for tracking key structs related to MemTracker state
     unordered_map<VkCommandBuffer,     MT_CB_INFO>               cbMap;
     unordered_map<VkCommandPool,       MT_CMD_POOL_INFO>         commandPoolMap;
@@ -1162,6 +1164,7 @@
         layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
         my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
         createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+        my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &my_device_data->properties);
     }
     return result;
 }
@@ -1391,6 +1394,8 @@
     const VkAllocationCallbacks *pAllocator)
 {
     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+    my_data->bufferRanges.erase(mem);
+    my_data->imageRanges.erase(mem);
 
     // From spec : A memory object is freed by calling vkFreeMemory() when it is no longer needed.
     // Before freeing a memory object, an application must ensure the memory object is no longer
@@ -1695,6 +1700,47 @@
     }
 }
 
+bool print_memory_range_error(layer_data *my_data, const uint64_t object_handle, const uint64_t other_handle, VkDebugReportObjectTypeEXT object_type) {
+    if (object_type == VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT) {
+        return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, 0, MEMTRACK_INVALID_ALIASING, "MEM",
+                       "Buffer %" PRIx64 " is alised with image %" PRIx64, object_handle, other_handle);
+    } else {
+        return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, 0, MEMTRACK_INVALID_ALIASING, "MEM",
+                       "Image %" PRIx64 " is alised with buffer %" PRIx64, object_handle, other_handle);
+    }
+}
+
+bool validate_memory_range(layer_data *my_data, const unordered_map<VkDeviceMemory, vector<MEMORY_RANGE>>& memory, const MEMORY_RANGE& new_range, VkDebugReportObjectTypeEXT object_type) {
+    bool skip_call = false;
+    if (!memory.count(new_range.memory)) return false;
+    const vector<MEMORY_RANGE>& ranges = memory.at(new_range.memory);
+    for (auto range : ranges) {
+        if ((range.end & ~(my_data->properties.limits.bufferImageGranularity - 1)) < new_range.start) continue;
+        if (range.start > (new_range.end & ~(my_data->properties.limits.bufferImageGranularity - 1))) continue;
+        skip_call |= print_memory_range_error(my_data, new_range.handle, range.handle, object_type);
+    }
+    return skip_call;
+}
+
+bool validate_buffer_image_aliasing(
+    layer_data *my_data,
+    uint64_t handle,
+    VkDeviceMemory mem,
+    VkDeviceSize memoryOffset,
+    VkMemoryRequirements memRequirements,
+    unordered_map<VkDeviceMemory, vector<MEMORY_RANGE>>& ranges,
+    const unordered_map<VkDeviceMemory, vector<MEMORY_RANGE>>& other_ranges,
+    VkDebugReportObjectTypeEXT object_type)
+{
+    MEMORY_RANGE range;
+    range.handle = handle;
+    range.memory = mem;
+    range.start = memoryOffset;
+    range.end = memoryOffset + memRequirements.size - 1;
+    ranges[mem].push_back(range);
+    return validate_memory_range(my_data, other_ranges, range, object_type);
+}
+
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(
     VkDevice       device,
     VkBuffer       buffer,
@@ -1705,8 +1751,14 @@
     VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
     loader_platform_thread_lock_mutex(&globalLock);
     // Track objects tied to memory
-    VkBool32 skipCall = set_mem_binding(my_data, device, mem, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory");
-    add_object_binding_info(my_data, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, mem);
+    uint64_t buffer_handle = reinterpret_cast<uint64_t>(buffer);
+    VkBool32 skipCall = set_mem_binding(my_data, device, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory");
+    add_object_binding_info(my_data, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, mem);
+    {
+        VkMemoryRequirements memRequirements;
+        vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
+        skipCall |= validate_buffer_image_aliasing(my_data, buffer_handle, mem, memoryOffset, memRequirements, my_data->bufferRanges, my_data->imageRanges, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
+    }
     print_mem_list(my_data, device);
     loader_platform_thread_unlock_mutex(&globalLock);
     if (VK_FALSE == skipCall) {
@@ -1725,8 +1777,14 @@
     VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
     loader_platform_thread_lock_mutex(&globalLock);
     // Track objects tied to memory
-    VkBool32 skipCall = set_mem_binding(my_data, device, mem, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory");
-    add_object_binding_info(my_data, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, mem);
+    uint64_t image_handle = reinterpret_cast<uint64_t>(image);
+    VkBool32 skipCall = set_mem_binding(my_data, device, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory");
+    add_object_binding_info(my_data, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, mem);
+    {
+        VkMemoryRequirements memRequirements;
+        vkGetImageMemoryRequirements(device, image, &memRequirements);
+        skipCall |= validate_buffer_image_aliasing(my_data, image_handle, mem, memoryOffset, memRequirements, my_data->imageRanges, my_data->bufferRanges, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
+    }
     print_mem_list(my_data, device);
     loader_platform_thread_unlock_mutex(&globalLock);
     if (VK_FALSE == skipCall) {
diff --git a/layers/mem_tracker.h b/layers/mem_tracker.h
index d153115..a43c400 100644
--- a/layers/mem_tracker.h
+++ b/layers/mem_tracker.h
@@ -39,6 +39,7 @@
     MEMTRACK_NONE,                          // Used for INFO & other non-error messages
     MEMTRACK_INVALID_CB,                    // Cmd Buffer invalid
     MEMTRACK_INVALID_MEM_OBJ,               // Invalid Memory Object
+    MEMTRACK_INVALID_ALIASING,              // Invalid Memory Aliasing
     MEMTRACK_INTERNAL_ERROR,                // Bug in Mem Track Layer internal data structures
     MEMTRACK_FREED_MEM_REF,                 // MEM Obj freed while it still has obj and/or CB refs
     MEMTRACK_MEM_OBJ_CLEAR_EMPTY_BINDINGS,  // Clearing bindings on mem obj that doesn't have any bindings
@@ -194,6 +195,13 @@
     std::vector<VkImage>        images;
 };
 
+struct MEMORY_RANGE {
+    uint64_t handle;
+    VkDeviceMemory memory;
+    VkDeviceSize start;
+    VkDeviceSize end;
+};
+
 #ifdef __cplusplus
 }
 #endif