layers: Migrate Fence checks from ObjectTracker to MemTracker
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 6042f8e..1373419 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -2049,10 +2049,30 @@
     return result;
 }
 
+static inline VkBool32 verifyFenceStatus(VkDevice device, VkFence fence, const char* apiCall)
+{
+    VkBool32 skipCall = VK_FALSE;
+    auto pFenceInfo = fenceMap.find(fence.handle);
+    if (pFenceInfo != fenceMap.end()) {
+        if (pFenceInfo->second.createInfo.flags & VK_FENCE_CREATE_SIGNALED_BIT) {
+            skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_FENCE, fence.handle, 0, MEMTRACK_INVALID_FENCE_STATE, "MEM",
+                "%s specified fence %#" PRIxLEAST64 " already in SIGNALED state.", apiCall, fence.handle);
+        }
+        if (!pFenceInfo->second.queue) { // Checking status of unsubmitted fence
+            skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_FENCE, fence.handle, 0, MEMTRACK_INVALID_FENCE_STATE, "MEM",
+                "%s called for fence %#" PRIxLEAST64 " which has not been submitted on a Queue.", apiCall, fence.handle);
+        }
+    }
+    return skipCall;
+}
+
 VK_LAYER_EXPORT VkResult VKAPI vkGetFenceStatus(
     VkDevice device,
     VkFence  fence)
 {
+    VkBool32 skipCall = verifyFenceStatus(device, fence, "vkGetFenceStatus");
+    if (skipCall)
+        return VK_ERROR_VALIDATION_FAILED;
     VkResult result = get_dispatch_table(mem_tracker_device_table_map, device)->GetFenceStatus(device, fence);
     if (VK_SUCCESS == result) {
         loader_platform_thread_lock_mutex(&globalLock);
@@ -2069,16 +2089,13 @@
     VkBool32       waitAll,
     uint64_t       timeout)
 {
+    VkBool32 skipCall = VK_FALSE;
     // Verify fence status of submitted fences
     for(uint32_t i = 0; i < fenceCount; i++) {
-        auto pFenceInfo = fenceMap.find(pFences[i].handle);
-        if (pFenceInfo != fenceMap.end()) {
-            if (pFenceInfo->second.createInfo.flags & VK_FENCE_CREATE_SIGNALED_BIT) {
-                log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_FENCE, pFences[i].handle, 0, MEMTRACK_INVALID_FENCE_STATE, "MEM",
-                        "VkWaitForFences specified fence %#" PRIxLEAST64 " already in SIGNALED state.", pFences[i].handle);
-            }
-        }
+        skipCall |= verifyFenceStatus(device, pFences[i], "vkWaitForFences");
     }
+    if (skipCall)
+        return VK_ERROR_VALIDATION_FAILED;
     VkResult result = get_dispatch_table(mem_tracker_device_table_map, device)->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
     loader_platform_thread_lock_mutex(&globalLock);
 
diff --git a/layers/object_track.h b/layers/object_track.h
index 141d0d9..bfb9cd4 100644
--- a/layers/object_track.h
+++ b/layers/object_track.h
@@ -35,7 +35,6 @@
     OBJTRACK_DESTROY_OBJECT_FAILED,             // Couldn't find object to be destroyed
     OBJTRACK_OBJECT_LEAK,                       // OBJECT was not correctly freed/destroyed
     OBJTRACK_OBJCOUNT_MAX_EXCEEDED,             // Request for Object data in excess of max obj count
-    OBJTRACK_INVALID_FENCE,                     // Requested status of unsubmitted fence object
     OBJTRACK_INVALID_OBJECT,                    // Object used that has never been created
 } OBJECT_TRACK_ERROR;
 
@@ -590,25 +589,6 @@
 }
 
 VkResult
-explicit_QueueSubmit(
-    VkQueue            queue,
-    uint32_t           cmdBufferCount,
-    const VkCmdBuffer *pCmdBuffers,
-    VkFence            fence)
-{
-    loader_platform_thread_lock_mutex(&objLock);
-    set_status(queue, fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);
-    // TODO: Fix for updated memory reference mechanism
-    // validate_memory_mapping_status(pMemRefs, memRefCount);
-    // validate_mem_ref_count(memRefCount);
-    loader_platform_thread_unlock_mutex(&objLock);
-
-    VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueSubmit(queue, cmdBufferCount, pCmdBuffers, fence);
-
-    return result;
-}
-
-VkResult
 explicit_MapMemory(
     VkDevice         device,
     VkDeviceMemory   mem,
@@ -693,49 +673,6 @@
 }
 
 VkResult
-explicit_GetFenceStatus(
-    VkDevice device,
-    VkFence  fence)
-{
-    loader_platform_thread_lock_mutex(&objLock);
-    // Warn if submitted_flag is not set
-#if 0
-    validate_status(device, fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED,
-        VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");
-#endif
-    validate_object(device, device);
-    loader_platform_thread_unlock_mutex(&objLock);
-
-    VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetFenceStatus(device, fence);
-
-    return result;
-}
-
-VkResult
-explicit_WaitForFences(
-    VkDevice       device,
-    uint32_t       fenceCount,
-    const VkFence *pFences,
-    VkBool32       waitAll,
-    uint64_t       timeout)
-{
-    loader_platform_thread_lock_mutex(&objLock);
-#if 0
-    // Warn if waiting on unsubmitted fence
-    for (uint32_t i = 0; i < fenceCount; i++) {
-        validate_status(device, pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED,
-            VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");
-    }
-#endif
-    validate_object(device, device);
-    loader_platform_thread_unlock_mutex(&objLock);
-
-    VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
-
-    return result;
-}
-
-VkResult
 explicit_AllocDescriptorSets(
     VkDevice                     device,
     VkDescriptorPool             descriptorPool,
diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md
index 82f8a45..a297f14 100644
--- a/layers/vk_validation_layer_details.md
+++ b/layers/vk_validation_layer_details.md
@@ -136,7 +136,7 @@
 | Objects Not Destroyed | Verify all objects destroyed at DestroyDevice time | MEMORY_LEAK | vkDestroyDevice | NA | NA |
 | Memory Mapping State | Verifies that mapped memory is CPU-visible | INVALID_STATE | vkMapMemory | MapMemWithoutHostVisibleBit | NA |
 | Command Buffer Synchronization | Command Buffer must be complete before BeginCommandBuffer or ResetCommandBuffer can be called | RESET_CB_WHILE_IN_FLIGHT | vkBeginCommandBuffer vkResetCommandBuffer | CallBeginCmdBufferBeforeCompletion CallBeginCmdBufferBeforeCompletion | NA |
-| Submitted Fence Status | Verifies that: The fence is not submitted in an already signaled state, and that ResetFences is not called with a fence in an unsignaled state | INVALID_FENCE_STATE | vkResetFences vkWaitForFences vkQueueSubmit | SubmitSignaledFence ResetUnsignaledFence | NA |
+| Submitted Fence Status | Verifies that: The fence is not submitted in an already signaled state, that ResetFences is not called with a fence in an unsignaled state, and that fences being checked have been submitted | INVALID_FENCE_STATE | vkResetFences vkWaitForFences vkQueueSubmit vkGetFenceStatus | SubmitSignaledFence ResetUnsignaledFence | Create test(s) for case where an unsubmitted fence is having its status checked |
 | Immutable Memory Binding | Validates that non-sparse memory bindings are immutable, so objects are not re-boundt | REBIND_OBJECT | vkBindBufferMemory, vkBindImageMemory | RebindMemory | NA |
 | Image/Buffer Usage bits | Verify correct USAGE bits set based on how Images and Buffers are used | INVALID_USAGE_FLAG | vkCreateImage, vkCreateBuffer, vkCreateBufferView, vkCmdCopyBuffer, vkCmdCopyImage, vkCmdBlitImage, vkCmdCopyBufferToImage, vkCmdCopyImageToBuffer, vkCmdUpdateBuffer, vkCmdFillBuffer  | InvalidUsageBits | NA |
 | Objects Not Destroyed Warning | Warns if any memory objects have not been freed before their objects are destroyed | MEM_OBJ_CLEAR_EMPTY_BINDINGS | vkDestroyDevice | TBD | NA |
@@ -202,7 +202,6 @@
 | Object Cleanup | Verify that object properly destroyed | DESTROY_OBJECT_FAILED | vkDestroyInstance, vkDestroyDevice, vkFreeMemory | ? | NA |
 | Objects Leak | When an Instance or Device object is destroyed, validates that all objects belonging to that device/instance have previously been destroyed | OBJECT_LEAK | vkDestroyDevice vkDestroyInstance | ? | NA |
 | Object Count | Flag error if number of objects requested from extenstion functions exceeds max number of actual objects | OBJCOUNT_MAX_EXCEEDED | objTrackGetObjects objTrackGetObjectsOfType | ? | NA |
-| Valid Fence for Wait | Flag error if waiting on unsubmitted fence object | INVALID_FENCE | vkGetFenceStatus | WaitForUnsubmittedFence | NA |
 | Valid Destroy Object | Validates that an object pass into a destroy function was properly created and is currently valid | NONE | vkDestroyInstance vkDestroyDevice vkDestroyFence vkDestroySemaphore vkDestroyEvent vkDestroyQueryPool vkDestroyBuffer vkDestroyBufferView vkDestroyImage vkDestroyImageView vkDestroyShaderModule vkDestroyShader vkDestroyPipelineCache vkDestroyPipeline vkDestroyPipelineLayout vkDestroySampler vkDestroyDescriptorSetLayout vkDestroyDescriptorPool vkDestroyDynamicViewportState vkDestroyDynamicBlendState vkDestroyDynamicLineWidthState vkDestroyDynamicDepthBiasState vkDestroyDynamicDepthBoundsState vkDestroyDynamicStencilState vkDestroyCommandPool vkDestroyCommandBuffer vkDestroyFramebuffer vkDestroyRenderPass vkDestroySwapchainKHR | TBD | These cases need to be moved to a more appropriate error enum |
 | Unknown object  | Internal layer errors when it attempts to update use count for an object that's not in its internal tracking datastructures. | UNKNOWN_OBJECT | | NA | This may be irrelevant due to INVALID_OBJECT error, need to look closely and merge this with that error as appropriate. |
 | NA | Enum used for informational messages | NONE | | NA | None |