layers: Validate that fence is not in use when submitted.
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 06d76f1..5952625 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -3312,6 +3312,7 @@
         auto fence_data = my_data->fenceMap.find(pFences[i]);
         if (fence_data == my_data->fenceMap.end() || !fence_data->second.needsSignaled) return;
         fence_data->second.needsSignaled = false;
+        fence_data->second.in_use.fetch_sub(1);
         if (fence_data->second.priorFence != VK_NULL_HANDLE) {
             decrementResources(my_data, 1, &fence_data->second.priorFence);
         }
@@ -3336,23 +3337,31 @@
     auto queue_data = my_data->queueMap.find(queue);
     if (fence != VK_NULL_HANDLE) {
         VkFence priorFence = VK_NULL_HANDLE;
+        auto fence_data = my_data->fenceMap.find(fence);
+        if (fence_data == my_data->fenceMap.end()) {
+            return;
+        }
         if (queue_data != my_data->queueMap.end()) {
             priorFence = queue_data->second.priorFence;
             queue_data->second.priorFence = fence;
             for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) {
-                my_data->fenceMap[fence].cmdBuffers.push_back(cmdBuffer);
+                fence_data->second.cmdBuffers.push_back(cmdBuffer);
             }
             queue_data->second.untrackedCmdBuffers.clear();
         }
-        my_data->fenceMap[fence].cmdBuffers.clear();
-        my_data->fenceMap[fence].priorFence = priorFence;
-        my_data->fenceMap[fence].needsSignaled = true;
-        my_data->fenceMap[fence].queue = queue;
+        fence_data->second.cmdBuffers.clear();
+        fence_data->second.priorFence = priorFence;
+        fence_data->second.needsSignaled = true;
+        fence_data->second.queue = queue;
+        fence_data->second.in_use.fetch_add(1);
         for (uint32_t i = 0; i < cmdBufferCount; ++i) {
-            for (auto secondaryCmdBuffer : my_data->commandBufferMap[pCmdBuffers[i]]->secondaryCommandBuffers) {
-                my_data->fenceMap[fence].cmdBuffers.push_back(secondaryCmdBuffer);
+            for (auto secondaryCmdBuffer :
+                 my_data->commandBufferMap[pCmdBuffers[i]]
+                     ->secondaryCommandBuffers) {
+                fence_data->second.cmdBuffers.push_back(
+                    secondaryCmdBuffer);
             }
-            my_data->fenceMap[fence].cmdBuffers.push_back(pCmdBuffers[i]);
+            fence_data->second.cmdBuffers.push_back(pCmdBuffers[i]);
         }
     } else {
         if (queue_data != my_data->queueMap.end()) {
@@ -3457,7 +3466,17 @@
             skipCall |= validateCommandBufferState(dev_data, pCB);
             loader_platform_thread_unlock_mutex(&globalLock);
         }
-        trackCommandBuffers(dev_data, queue, submit->commandBufferCount, submit->pCommandBuffers, fence);
+        if (dev_data->fenceMap[fence].in_use.load()) {
+            skipCall |= log_msg(
+                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+                VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
+                reinterpret_cast<uint64_t>(fence), __LINE__,
+                DRAWSTATE_INVALID_FENCE, "DS",
+                "Fence %#" PRIx64 " is already in use by another submission.",
+                reinterpret_cast<uint64_t>(fence));
+        }
+        trackCommandBuffers(dev_data, queue, submit->commandBufferCount,
+                            submit->pCommandBuffers, fence);
     }
     if (VK_FALSE == skipCall)
         return dev_data->device_dispatch_table->QueueSubmit(queue, submitCount, pSubmits, fence);
@@ -3937,15 +3956,31 @@
     return result;
 }
 
-//TODO handle pipeline caches
-VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(
-    VkDevice                                    device,
-    const VkPipelineCacheCreateInfo*            pCreateInfo,
-    const VkAllocationCallbacks*                     pAllocator,
-    VkPipelineCache*                            pPipelineCache)
-{
-    layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-    VkResult result = dev_data->device_dispatch_table->CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo,
+                  const VkAllocationCallbacks* pAllocator, VkFence* pFence) {
+    layer_data *dev_data =
+        get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+    VkResult result = dev_data->device_dispatch_table->CreateFence(
+        device, pCreateInfo, pAllocator, pFence);
+    if (VK_SUCCESS == result) {
+        loader_platform_thread_lock_mutex(&globalLock);
+        dev_data->fenceMap[*pFence].in_use.store(0);
+        loader_platform_thread_unlock_mutex(&globalLock);
+    }
+    return result;
+}
+
+// TODO handle pipeline caches
+VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreatePipelineCache(VkDevice device,
+                          const VkPipelineCacheCreateInfo *pCreateInfo,
+                          const VkAllocationCallbacks *pAllocator,
+                          VkPipelineCache *pPipelineCache) {
+    layer_data *dev_data =
+        get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+    VkResult result = dev_data->device_dispatch_table->CreatePipelineCache(
+        device, pCreateInfo, pAllocator, pPipelineCache);
     return result;
 }
 
@@ -6743,6 +6778,8 @@
         return (PFN_vkVoidFunction) vkCreateImage;
     if (!strcmp(funcName, "vkCreateImageView"))
         return (PFN_vkVoidFunction) vkCreateImageView;
+    if (!strcmp(funcName, "vkCreateFence"))
+        return (PFN_vkVoidFunction) vkCreateFence;
     if (!strcmp(funcName, "CreatePipelineCache"))
         return (PFN_vkVoidFunction) vkCreatePipelineCache;
     if (!strcmp(funcName, "DestroyPipelineCache"))