layers: Overhaul unique_objects

Unique objects now uses a 64-bit counter as the unique handle returned
to the app. It stores an internal mapping of handles to actual object
ptrs that are used for all non-dispatchable objects. This virtually
eliminates the possibility of having a repeat handle as objects
are created and destroyed.

All counter increments and map accesses are protected by a mutex.
diff --git a/layers/unique_objects.h b/layers/unique_objects.h
index 3fbf54e..b4376a5 100644
--- a/layers/unique_objects.h
+++ b/layers/unique_objects.h
@@ -33,8 +33,9 @@
 #include <string.h>
 #include <inttypes.h>
 
-#include <vector>
 #include <unordered_map>
+#include <vector>
+#include <mutex>
 
 #include "vulkan/vk_layer.h"
 #include "vk_layer_config.h"
@@ -47,8 +48,11 @@
 
 struct layer_data {
     bool wsi_enabled;
+    uint64_t unique_id; // All increments are guarded by global_lock
+    std::unordered_map<uint64_t, uint64_t> unique_id_mapping; // Map uniqueID to actual object handle
+    VkPhysicalDevice gpu;
 
-    layer_data() : wsi_enabled(false){};
+    layer_data() : wsi_enabled(false), unique_id(1), gpu(VK_NULL_HANDLE){};
 };
 
 struct instExts {
@@ -65,11 +69,7 @@
 static std::unordered_map<void *, layer_data *> layer_data_map;
 static device_table_map unique_objects_device_table_map;
 static instance_table_map unique_objects_instance_table_map;
-// Structure to wrap returned non-dispatchable objects to guarantee they have unique handles
-//  address of struct will be used as the unique handle
-struct VkUniqueObject {
-    uint64_t actualObject;
-};
+static std::mutex global_lock; // Protect map accesses and unique_id increments
 
 // Handle CreateInstance
 static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
@@ -172,6 +172,11 @@
     return result;
 }
 
+void explicit_DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
+    get_dispatch_table(unique_objects_instance_table_map, instance)->DestroyInstance(instance, pAllocator);
+    layer_data_map.erase(get_dispatch_key(instance));
+}
+
 // Handle CreateDevice
 static void createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -213,233 +218,16 @@
     initDeviceTable(*pDevice, fpGetDeviceProcAddr, unique_objects_device_table_map);
 
     createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+    // Set gpu for this device in order to get at any objects mapped at instance level
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+    my_device_data->gpu = gpu;
 
     return result;
 }
 
-VkResult explicit_QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
-    // UNWRAP USES:
-    //  0 : fence,VkFence
-    if (VK_NULL_HANDLE != fence) {
-        fence = (VkFence)((VkUniqueObject *)fence)->actualObject;
-    }
-    //  waitSemaphoreCount : pSubmits[submitCount]->pWaitSemaphores,VkSemaphore
-    std::vector<VkSemaphore> original_pWaitSemaphores = {};
-    //  signalSemaphoreCount : pSubmits[submitCount]->pSignalSemaphores,VkSemaphore
-    std::vector<VkSemaphore> original_pSignalSemaphores = {};
-    if (pSubmits) {
-        for (uint32_t index0 = 0; index0 < submitCount; ++index0) {
-            if (pSubmits[index0].pWaitSemaphores) {
-                for (uint32_t index1 = 0; index1 < pSubmits[index0].waitSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pSubmits[index0].pWaitSemaphores);
-                    original_pWaitSemaphores.push_back(pSubmits[index0].pWaitSemaphores[index1]);
-                    *(ppSemaphore[index1]) =
-                        (VkSemaphore)((VkUniqueObject *)pSubmits[index0].pWaitSemaphores[index1])->actualObject;
-                }
-            }
-            if (pSubmits[index0].pSignalSemaphores) {
-                for (uint32_t index1 = 0; index1 < pSubmits[index0].signalSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pSubmits[index0].pSignalSemaphores);
-                    original_pSignalSemaphores.push_back(pSubmits[index0].pSignalSemaphores[index1]);
-                    *(ppSemaphore[index1]) =
-                        (VkSemaphore)((VkUniqueObject *)pSubmits[index0].pSignalSemaphores[index1])->actualObject;
-                }
-            }
-        }
-    }
-    VkResult result = get_dispatch_table(unique_objects_device_table_map, queue)->QueueSubmit(queue, submitCount, pSubmits, fence);
-    if (pSubmits) {
-        for (uint32_t index0 = 0; index0 < submitCount; ++index0) {
-            if (pSubmits[index0].pWaitSemaphores) {
-                for (uint32_t index1 = 0; index1 < pSubmits[index0].waitSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pSubmits[index0].pWaitSemaphores);
-                    *(ppSemaphore[index1]) = original_pWaitSemaphores[index1];
-                }
-            }
-            if (pSubmits[index0].pSignalSemaphores) {
-                for (uint32_t index1 = 0; index1 < pSubmits[index0].signalSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pSubmits[index0].pSignalSemaphores);
-                    *(ppSemaphore[index1]) = original_pSignalSemaphores[index1];
-                }
-            }
-        }
-    }
-    return result;
-}
-
-VkResult explicit_QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) {
-    // UNWRAP USES:
-    //  0 : pBindInfo[bindInfoCount]->pBufferBinds[bufferBindCount]->buffer,VkBuffer,
-    //  pBindInfo[bindInfoCount]->pBufferBinds[bufferBindCount]->pBinds[bindCount]->memory,VkDeviceMemory,
-    //  pBindInfo[bindInfoCount]->pImageOpaqueBinds[imageOpaqueBindCount]->image,VkImage,
-    //  pBindInfo[bindInfoCount]->pImageOpaqueBinds[imageOpaqueBindCount]->pBinds[bindCount]->memory,VkDeviceMemory,
-    //  pBindInfo[bindInfoCount]->pImageBinds[imageBindCount]->image,VkImage,
-    //  pBindInfo[bindInfoCount]->pImageBinds[imageBindCount]->pBinds[bindCount]->memory,VkDeviceMemory
-    std::vector<VkBuffer> original_buffer = {};
-    std::vector<VkDeviceMemory> original_memory1 = {};
-    std::vector<VkImage> original_image1 = {};
-    std::vector<VkDeviceMemory> original_memory2 = {};
-    std::vector<VkImage> original_image2 = {};
-    std::vector<VkDeviceMemory> original_memory3 = {};
-    std::vector<VkSemaphore> original_pWaitSemaphores = {};
-    std::vector<VkSemaphore> original_pSignalSemaphores = {};
-    if (pBindInfo) {
-        for (uint32_t index0 = 0; index0 < bindInfoCount; ++index0) {
-            if (pBindInfo[index0].pBufferBinds) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].bufferBindCount; ++index1) {
-                    if (pBindInfo[index0].pBufferBinds[index1].buffer) {
-                        VkBuffer *pBuffer = (VkBuffer *)&(pBindInfo[index0].pBufferBinds[index1].buffer);
-                        original_buffer.push_back(pBindInfo[index0].pBufferBinds[index1].buffer);
-                        *(pBuffer) = (VkBuffer)((VkUniqueObject *)pBindInfo[index0].pBufferBinds[index1].buffer)->actualObject;
-                    }
-                    if (pBindInfo[index0].pBufferBinds[index1].pBinds) {
-                        for (uint32_t index2 = 0; index2 < pBindInfo[index0].pBufferBinds[index1].bindCount; ++index2) {
-                            if (pBindInfo[index0].pBufferBinds[index1].pBinds[index2].memory) {
-                                VkDeviceMemory *pDeviceMemory =
-                                    (VkDeviceMemory *)&(pBindInfo[index0].pBufferBinds[index1].pBinds[index2].memory);
-                                original_memory1.push_back(pBindInfo[index0].pBufferBinds[index1].pBinds[index2].memory);
-                                *(pDeviceMemory) =
-                                    (VkDeviceMemory)((VkUniqueObject *)pBindInfo[index0].pBufferBinds[index1].pBinds[index2].memory)
-                                        ->actualObject;
-                            }
-                        }
-                    }
-                }
-            }
-            if (pBindInfo[index0].pImageOpaqueBinds) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].imageOpaqueBindCount; ++index1) {
-                    if (pBindInfo[index0].pImageOpaqueBinds[index1].image) {
-                        VkImage *pImage = (VkImage *)&(pBindInfo[index0].pImageOpaqueBinds[index1].image);
-                        original_image1.push_back(pBindInfo[index0].pImageOpaqueBinds[index1].image);
-                        *(pImage) = (VkImage)((VkUniqueObject *)pBindInfo[index0].pImageOpaqueBinds[index1].image)->actualObject;
-                    }
-                    if (pBindInfo[index0].pImageOpaqueBinds[index1].pBinds) {
-                        for (uint32_t index2 = 0; index2 < pBindInfo[index0].pImageOpaqueBinds[index1].bindCount; ++index2) {
-                            if (pBindInfo[index0].pImageOpaqueBinds[index1].pBinds[index2].memory) {
-                                VkDeviceMemory *pDeviceMemory =
-                                    (VkDeviceMemory *)&(pBindInfo[index0].pImageOpaqueBinds[index1].pBinds[index2].memory);
-                                original_memory2.push_back(pBindInfo[index0].pImageOpaqueBinds[index1].pBinds[index2].memory);
-                                *(pDeviceMemory) =
-                                    (VkDeviceMemory)(
-                                        (VkUniqueObject *)pBindInfo[index0].pImageOpaqueBinds[index1].pBinds[index2].memory)
-                                        ->actualObject;
-                            }
-                        }
-                    }
-                }
-            }
-            if (pBindInfo[index0].pImageBinds) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].imageBindCount; ++index1) {
-                    if (pBindInfo[index0].pImageBinds[index1].image) {
-                        VkImage *pImage = (VkImage *)&(pBindInfo[index0].pImageBinds[index1].image);
-                        original_image2.push_back(pBindInfo[index0].pImageBinds[index1].image);
-                        *(pImage) = (VkImage)((VkUniqueObject *)pBindInfo[index0].pImageBinds[index1].image)->actualObject;
-                    }
-                    if (pBindInfo[index0].pImageBinds[index1].pBinds) {
-                        for (uint32_t index2 = 0; index2 < pBindInfo[index0].pImageBinds[index1].bindCount; ++index2) {
-                            if (pBindInfo[index0].pImageBinds[index1].pBinds[index2].memory) {
-                                VkDeviceMemory *pDeviceMemory =
-                                    (VkDeviceMemory *)&(pBindInfo[index0].pImageBinds[index1].pBinds[index2].memory);
-                                original_memory3.push_back(pBindInfo[index0].pImageBinds[index1].pBinds[index2].memory);
-                                *(pDeviceMemory) =
-                                    (VkDeviceMemory)((VkUniqueObject *)pBindInfo[index0].pImageBinds[index1].pBinds[index2].memory)
-                                        ->actualObject;
-                            }
-                        }
-                    }
-                }
-            }
-            if (pBindInfo[index0].pWaitSemaphores) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].waitSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pBindInfo[index0].pWaitSemaphores);
-                    original_pWaitSemaphores.push_back(pBindInfo[index0].pWaitSemaphores[index1]);
-                    *(ppSemaphore[index1]) =
-                        (VkSemaphore)((VkUniqueObject *)pBindInfo[index0].pWaitSemaphores[index1])->actualObject;
-                }
-            }
-            if (pBindInfo[index0].pSignalSemaphores) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].signalSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pBindInfo[index0].pSignalSemaphores);
-                    original_pSignalSemaphores.push_back(pBindInfo[index0].pSignalSemaphores[index1]);
-                    *(ppSemaphore[index1]) =
-                        (VkSemaphore)((VkUniqueObject *)pBindInfo[index0].pSignalSemaphores[index1])->actualObject;
-                }
-            }
-        }
-    }
-    if (VK_NULL_HANDLE != fence) {
-        fence = (VkFence)((VkUniqueObject *)fence)->actualObject;
-    }
-    VkResult result =
-        get_dispatch_table(unique_objects_device_table_map, queue)->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
-    if (pBindInfo) {
-        for (uint32_t index0 = 0; index0 < bindInfoCount; ++index0) {
-            if (pBindInfo[index0].pBufferBinds) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].bufferBindCount; ++index1) {
-                    if (pBindInfo[index0].pBufferBinds[index1].buffer) {
-                        VkBuffer *pBuffer = (VkBuffer *)&(pBindInfo[index0].pBufferBinds[index1].buffer);
-                        *(pBuffer) = original_buffer[index1];
-                    }
-                    if (pBindInfo[index0].pBufferBinds[index1].pBinds) {
-                        for (uint32_t index2 = 0; index2 < pBindInfo[index0].pBufferBinds[index1].bindCount; ++index2) {
-                            if (pBindInfo[index0].pBufferBinds[index1].pBinds[index2].memory) {
-                                VkDeviceMemory *pDeviceMemory =
-                                    (VkDeviceMemory *)&(pBindInfo[index0].pBufferBinds[index1].pBinds[index2].memory);
-                                *(pDeviceMemory) = original_memory1[index2];
-                            }
-                        }
-                    }
-                }
-            }
-            if (pBindInfo[index0].pImageOpaqueBinds) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].imageOpaqueBindCount; ++index1) {
-                    if (pBindInfo[index0].pImageOpaqueBinds[index1].image) {
-                        VkImage *pImage = (VkImage *)&(pBindInfo[index0].pImageOpaqueBinds[index1].image);
-                        *(pImage) = original_image1[index1];
-                    }
-                    if (pBindInfo[index0].pImageOpaqueBinds[index1].pBinds) {
-                        for (uint32_t index2 = 0; index2 < pBindInfo[index0].pImageOpaqueBinds[index1].bindCount; ++index2) {
-                            if (pBindInfo[index0].pImageOpaqueBinds[index1].pBinds[index2].memory) {
-                                VkDeviceMemory *pDeviceMemory =
-                                    (VkDeviceMemory *)&(pBindInfo[index0].pImageOpaqueBinds[index1].pBinds[index2].memory);
-                                *(pDeviceMemory) = original_memory2[index2];
-                            }
-                        }
-                    }
-                }
-            }
-            if (pBindInfo[index0].pImageBinds) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].imageBindCount; ++index1) {
-                    if (pBindInfo[index0].pImageBinds[index1].image) {
-                        VkImage *pImage = (VkImage *)&(pBindInfo[index0].pImageBinds[index1].image);
-                        *(pImage) = original_image2[index1];
-                    }
-                    if (pBindInfo[index0].pImageBinds[index1].pBinds) {
-                        for (uint32_t index2 = 0; index2 < pBindInfo[index0].pImageBinds[index1].bindCount; ++index2) {
-                            if (pBindInfo[index0].pImageBinds[index1].pBinds[index2].memory) {
-                                VkDeviceMemory *pDeviceMemory =
-                                    (VkDeviceMemory *)&(pBindInfo[index0].pImageBinds[index1].pBinds[index2].memory);
-                                *(pDeviceMemory) = original_memory3[index2];
-                            }
-                        }
-                    }
-                }
-            }
-            if (pBindInfo[index0].pWaitSemaphores) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].waitSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pBindInfo[index0].pWaitSemaphores);
-                    *(ppSemaphore[index1]) = original_pWaitSemaphores[index1];
-                }
-            }
-            if (pBindInfo[index0].pSignalSemaphores) {
-                for (uint32_t index1 = 0; index1 < pBindInfo[index0].signalSemaphoreCount; ++index1) {
-                    VkSemaphore **ppSemaphore = (VkSemaphore **)&(pBindInfo[index0].pSignalSemaphores);
-                    *(ppSemaphore[index1]) = original_pSignalSemaphores[index1];
-                }
-            }
-        }
-    }
-    return result;
+void explicit_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
+    get_dispatch_table(unique_objects_device_table_map, device)->DestroyDevice(device, pAllocator);
+    layer_data_map.erase(get_dispatch_key(device));
 }
 
 VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
@@ -448,38 +236,44 @@
     // STRUCT USES:{'pipelineCache': 'VkPipelineCache', 'pCreateInfos[createInfoCount]': {'stage': {'module': 'VkShaderModule'},
     // 'layout': 'VkPipelineLayout', 'basePipelineHandle': 'VkPipeline'}}
     // LOCAL DECLS:{'pCreateInfos': 'VkComputePipelineCreateInfo*'}
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     safe_VkComputePipelineCreateInfo *local_pCreateInfos = NULL;
     if (pCreateInfos) {
+        std::lock_guard<std::mutex> lock(global_lock);
         local_pCreateInfos = new safe_VkComputePipelineCreateInfo[createInfoCount];
         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
             local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
             if (pCreateInfos[idx0].basePipelineHandle) {
                 local_pCreateInfos[idx0].basePipelineHandle =
-                    (VkPipeline)((VkUniqueObject *)pCreateInfos[idx0].basePipelineHandle)->actualObject;
+                    (VkPipeline)
+                        my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].basePipelineHandle)];
             }
             if (pCreateInfos[idx0].layout) {
-                local_pCreateInfos[idx0].layout = (VkPipelineLayout)((VkUniqueObject *)pCreateInfos[idx0].layout)->actualObject;
+                local_pCreateInfos[idx0].layout =
+                    (VkPipelineLayout)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].layout)];
             }
             if (pCreateInfos[idx0].stage.module) {
                 local_pCreateInfos[idx0].stage.module =
-                    (VkShaderModule)((VkUniqueObject *)pCreateInfos[idx0].stage.module)->actualObject;
+                    (VkShaderModule)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].stage.module)];
             }
         }
     }
     if (pipelineCache) {
-        pipelineCache = (VkPipelineCache)((VkUniqueObject *)pipelineCache)->actualObject;
+        std::lock_guard<std::mutex> lock(global_lock);
+        pipelineCache = (VkPipelineCache)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pipelineCache)];
     }
-    // CODEGEN : file /usr/local/google/home/tobine/vulkan_work/LoaderAndTools/vk-layer-generate.py line #1671
+
     VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
                           ->CreateComputePipelines(device, pipelineCache, createInfoCount,
                                                    (const VkComputePipelineCreateInfo *)local_pCreateInfos, pAllocator, pPipelines);
     delete[] local_pCreateInfos;
     if (VK_SUCCESS == result) {
-        VkUniqueObject *pUO = NULL;
+        uint64_t unique_id = 0;
+        std::lock_guard<std::mutex> lock(global_lock);
         for (uint32_t i = 0; i < createInfoCount; ++i) {
-            pUO = new VkUniqueObject();
-            pUO->actualObject = (uint64_t)pPipelines[i];
-            pPipelines[i] = (VkPipeline)pUO;
+            unique_id = my_device_data->unique_id++;
+            my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t>(pPipelines[i]);
+            pPipelines[i] = reinterpret_cast<VkPipeline>(unique_id);
         }
     }
     return result;
@@ -491,68 +285,108 @@
     // STRUCT USES:{'pipelineCache': 'VkPipelineCache', 'pCreateInfos[createInfoCount]': {'layout': 'VkPipelineLayout',
     // 'pStages[stageCount]': {'module': 'VkShaderModule'}, 'renderPass': 'VkRenderPass', 'basePipelineHandle': 'VkPipeline'}}
     // LOCAL DECLS:{'pCreateInfos': 'VkGraphicsPipelineCreateInfo*'}
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     safe_VkGraphicsPipelineCreateInfo *local_pCreateInfos = NULL;
     if (pCreateInfos) {
         local_pCreateInfos = new safe_VkGraphicsPipelineCreateInfo[createInfoCount];
+        std::lock_guard<std::mutex> lock(global_lock);
         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
             local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
             if (pCreateInfos[idx0].basePipelineHandle) {
                 local_pCreateInfos[idx0].basePipelineHandle =
-                    (VkPipeline)((VkUniqueObject *)pCreateInfos[idx0].basePipelineHandle)->actualObject;
+                    (VkPipeline)
+                        my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].basePipelineHandle)];
             }
             if (pCreateInfos[idx0].layout) {
-                local_pCreateInfos[idx0].layout = (VkPipelineLayout)((VkUniqueObject *)pCreateInfos[idx0].layout)->actualObject;
+                local_pCreateInfos[idx0].layout =
+                    (VkPipelineLayout)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].layout)];
             }
             if (pCreateInfos[idx0].pStages) {
                 for (uint32_t idx1 = 0; idx1 < pCreateInfos[idx0].stageCount; ++idx1) {
                     if (pCreateInfos[idx0].pStages[idx1].module) {
                         local_pCreateInfos[idx0].pStages[idx1].module =
-                            (VkShaderModule)((VkUniqueObject *)pCreateInfos[idx0].pStages[idx1].module)->actualObject;
+                            (VkShaderModule)my_device_data
+                                ->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].pStages[idx1].module)];
                     }
                 }
             }
             if (pCreateInfos[idx0].renderPass) {
-                local_pCreateInfos[idx0].renderPass = (VkRenderPass)((VkUniqueObject *)pCreateInfos[idx0].renderPass)->actualObject;
+                local_pCreateInfos[idx0].renderPass =
+                    (VkRenderPass)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfos[idx0].renderPass)];
             }
         }
     }
     if (pipelineCache) {
-        pipelineCache = (VkPipelineCache)((VkUniqueObject *)pipelineCache)->actualObject;
+        std::lock_guard<std::mutex> lock(global_lock);
+        pipelineCache = (VkPipelineCache)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(pipelineCache)];
     }
-    // CODEGEN : file /usr/local/google/home/tobine/vulkan_work/LoaderAndTools/vk-layer-generate.py line #1671
+
     VkResult result =
         get_dispatch_table(unique_objects_device_table_map, device)
             ->CreateGraphicsPipelines(device, pipelineCache, createInfoCount,
                                       (const VkGraphicsPipelineCreateInfo *)local_pCreateInfos, pAllocator, pPipelines);
     delete[] local_pCreateInfos;
     if (VK_SUCCESS == result) {
-        VkUniqueObject *pUO = NULL;
+        uint64_t unique_id = 0;
+        std::lock_guard<std::mutex> lock(global_lock);
         for (uint32_t i = 0; i < createInfoCount; ++i) {
-            pUO = new VkUniqueObject();
-            pUO->actualObject = (uint64_t)pPipelines[i];
-            pPipelines[i] = (VkPipeline)pUO;
+            unique_id = my_device_data->unique_id++;
+            my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t>(pPipelines[i]);
+            pPipelines[i] = reinterpret_cast<VkPipeline>(unique_id);
         }
     }
     return result;
 }
 
+VkResult explicit_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
+                                     const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
+    layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+    safe_VkSwapchainCreateInfoKHR *local_pCreateInfo = NULL;
+    if (pCreateInfo) {
+        std::lock_guard<std::mutex> lock(global_lock);
+        local_pCreateInfo = new safe_VkSwapchainCreateInfoKHR(pCreateInfo);
+        local_pCreateInfo->oldSwapchain =
+            (VkSwapchainKHR)my_map_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfo->oldSwapchain)];
+        // Need to pull surface mapping from the instance-level map
+        layer_data *instance_data = get_my_data_ptr(get_dispatch_key(my_map_data->gpu), layer_data_map);
+        local_pCreateInfo->surface =
+            (VkSurfaceKHR)instance_data->unique_id_mapping[reinterpret_cast<uint64_t>(pCreateInfo->surface)];
+    }
+
+    VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
+                          ->CreateSwapchainKHR(device, (const VkSwapchainCreateInfoKHR *)local_pCreateInfo, pAllocator, pSwapchain);
+    if (local_pCreateInfo)
+        delete local_pCreateInfo;
+    if (VK_SUCCESS == result) {
+        std::lock_guard<std::mutex> lock(global_lock);
+        uint64_t unique_id = my_map_data->unique_id++;
+        my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t>(*pSwapchain);
+        *pSwapchain = reinterpret_cast<VkSwapchainKHR>(unique_id);
+    }
+    return result;
+}
+
 VkResult explicit_GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
                                         VkImage *pSwapchainImages) {
     // UNWRAP USES:
     //  0 : swapchain,VkSwapchainKHR, pSwapchainImages,VkImage
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     if (VK_NULL_HANDLE != swapchain) {
-        swapchain = (VkSwapchainKHR)((VkUniqueObject *)swapchain)->actualObject;
+        std::lock_guard<std::mutex> lock(global_lock);
+        swapchain = (VkSwapchainKHR)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t>(swapchain)];
     }
     VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
                           ->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
     // TODO : Need to add corresponding code to delete these images
     if (VK_SUCCESS == result) {
         if ((*pSwapchainImageCount > 0) && pSwapchainImages) {
-            std::vector<VkUniqueObject *> uniqueImages = {};
+            uint64_t unique_id = 0;
+            std::lock_guard<std::mutex> lock(global_lock);
             for (uint32_t i = 0; i < *pSwapchainImageCount; ++i) {
-                uniqueImages.push_back(new VkUniqueObject());
-                uniqueImages[i]->actualObject = (uint64_t)pSwapchainImages[i];
-                pSwapchainImages[i] = (VkImage)uniqueImages[i];
+                unique_id = my_device_data->unique_id++;
+                my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t>(pSwapchainImages[i]);
+                pSwapchainImages[i] = reinterpret_cast<VkImage>(unique_id);
             }
         }
     }