layers: Bug #14850, enforce validation for semaphore states

Added creation of driver-side semaphore objects.
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index bfd8532..a16b08a 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -78,6 +78,7 @@
 unordered_map<uint64_t,       MT_FENCE_INFO>        fenceMap;    // Map fence to fence info
 unordered_map<VkQueue,        MT_QUEUE_INFO>        queueMap;
 unordered_map<uint64_t,       MT_SWAP_CHAIN_INFO*>  swapchainMap;
+unordered_map<uint64_t,       MtSemaphoreState>     semaphoreMap;
 
 // Images and Buffers are 2 objects that can have memory bound to them so they get special treatment
 unordered_map<uint64_t, MT_OBJ_BINDING_INFO> imageMap;
@@ -2394,9 +2395,116 @@
     return result;
 }
 
+VK_LAYER_EXPORT VkResult VKAPI vkAcquireNextImageKHR(
+    VkDevice        device,
+    VkSwapchainKHR  swapchain,
+    uint64_t        timeout,
+    VkSemaphore     semaphore,
+    uint32_t       *pImageIndex)
+{
+    VkResult result   = VK_ERROR_VALIDATION_FAILED;
+    VkBool32 skipCall = VK_FALSE;
+
+    loader_platform_thread_lock_mutex(&globalLock);
+    if (semaphoreMap.find(semaphore.handle) != semaphoreMap.end()) {
+        if (semaphoreMap[semaphore.handle] != MEMTRACK_SEMAPHORE_STATE_UNSET) {
+            skipCall = log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_SEMAPHORE, semaphore.handle,
+                               0, MEMTRACK_NONE, "SEMAPHORE",
+                               "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state");
+        }
+        semaphoreMap[semaphore.handle] = MEMTRACK_SEMAPHORE_STATE_SIGNALLED;
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+    if (VK_FALSE == skipCall) {
+        result = get_dispatch_table(mem_tracker_device_table_map, device)->AcquireNextImageKHR(device,
+                                    swapchain, timeout, semaphore, pImageIndex);
+    }
+    return result;
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkCreateSemaphore(
+    VkDevice                     device,
+    const VkSemaphoreCreateInfo *pCreateInfo,
+    VkSemaphore                 *pSemaphore)
+{
+    VkResult result = get_dispatch_table(mem_tracker_device_table_map, device)->CreateSemaphore(device, pCreateInfo, pSemaphore);
+    loader_platform_thread_lock_mutex(&globalLock);
+    if (pSemaphore->handle != 0) {
+        semaphoreMap[pSemaphore->handle] = MEMTRACK_SEMAPHORE_STATE_UNSET;
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+    return result;
+}
+
+VK_LAYER_EXPORT void VKAPI vkDestroySemaphore(
+    VkDevice    device,
+    VkSemaphore semaphore)
+{
+    loader_platform_thread_lock_mutex(&globalLock);
+    auto item = semaphoreMap.find(semaphore.handle);
+    if (item != semaphoreMap.end()) {
+        semaphoreMap.erase(item);
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+    get_dispatch_table(mem_tracker_device_table_map, device)->DestroySemaphore(device, semaphore);
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkQueueSignalSemaphore(
+    VkQueue     queue,
+    VkSemaphore semaphore)
+{
+    VkResult result   = VK_ERROR_VALIDATION_FAILED;
+    VkBool32 skipCall = VK_FALSE;
+
+    loader_platform_thread_lock_mutex(&globalLock);
+    if (semaphoreMap.find(semaphore.handle) != semaphoreMap.end()) {
+        if (semaphoreMap[semaphore.handle] != MEMTRACK_SEMAPHORE_STATE_UNSET) {
+            skipCall = log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_SEMAPHORE, semaphore.handle,
+                               0, MEMTRACK_NONE, "SEMAPHORE",
+                               "vkQueueSignalSemaphore: Semaphore must not be currently signaled or in a wait state");
+        }
+        semaphoreMap[semaphore.handle] = MEMTRACK_SEMAPHORE_STATE_SIGNALLED;
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+    if (VK_FALSE == skipCall) {
+        VkResult result = get_dispatch_table(mem_tracker_device_table_map, queue)->QueueSignalSemaphore(queue, semaphore);
+    }
+    return result;
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkQueueWaitSemaphore(
+    VkQueue     queue,
+    VkSemaphore semaphore)
+{
+    VkBool32 skipCall = VK_FALSE;
+    VkBool32 found    = VK_FALSE;
+    VkResult result   = VK_ERROR_VALIDATION_FAILED;
+
+    loader_platform_thread_lock_mutex(&globalLock);
+    if (semaphoreMap.find(semaphore.handle) != semaphoreMap.end()) {
+        found = VK_TRUE;
+        if (semaphoreMap[semaphore.handle] != MEMTRACK_SEMAPHORE_STATE_SIGNALLED) {
+            skipCall = log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_SEMAPHORE, semaphore.handle,
+                               0, MEMTRACK_NONE, "SEMAPHORE",
+                               "vkQueueWaitSemaphore: Semaphore must be in signaled state before passing to vkQueueWaitSemaphore");
+        }
+        semaphoreMap[semaphore.handle] = MEMTRACK_SEMAPHORE_STATE_WAIT;
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+    if (VK_FALSE == skipCall) {
+        result = get_dispatch_table(mem_tracker_device_table_map, queue)->QueueWaitSemaphore(queue, semaphore);
+    }
+    loader_platform_thread_lock_mutex(&globalLock);
+    if (found) {
+        semaphoreMap[semaphore.handle] = MEMTRACK_SEMAPHORE_STATE_UNSET;
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+    return result;
+}
+
 VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(
     VkDevice         dev,
-    const char       *funcName)
+    const char      *funcName)
 {
     if (dev == NULL) {
         return NULL;
@@ -2449,6 +2557,14 @@
         return (PFN_vkVoidFunction) vkResetFences;
     if (!strcmp(funcName, "vkWaitForFences"))
         return (PFN_vkVoidFunction) vkWaitForFences;
+    if (!strcmp(funcName, "vkCreateSemaphore"))
+        return (PFN_vkVoidFunction) vkCreateSemaphore;
+    if (!strcmp(funcName, "vkDestroySemaphore"))
+        return (PFN_vkVoidFunction) vkDestroySemaphore;
+    if (!strcmp(funcName, "vkQueueSignalSemaphore"))
+        return (PFN_vkVoidFunction) vkQueueSignalSemaphore;
+    if (!strcmp(funcName, "vkQueueWaitSemaphore"))
+        return (PFN_vkVoidFunction) vkQueueWaitSemaphore;
     if (!strcmp(funcName, "vkQueueWaitIdle"))
         return (PFN_vkVoidFunction) vkQueueWaitIdle;
     if (!strcmp(funcName, "vkDeviceWaitIdle"))
@@ -2549,6 +2665,8 @@
             return (PFN_vkVoidFunction) vkDestroySwapchainKHR;
         if (!strcmp(funcName, "vkGetSwapchainImagesKHR"))
             return (PFN_vkVoidFunction) vkGetSwapchainImagesKHR;
+        if (!strcmp(funcName, "vkAcquireNextImageKHR"))
+            return (PFN_vkVoidFunction)vkAcquireNextImageKHR;
     }
 
     VkLayerDispatchTable *pDisp  = get_dispatch_table(mem_tracker_device_table_map, dev);