Home | History | Annotate | Download | only in layers
      1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
      2  * Copyright (c) 2015-2016 Valve Corporation
      3  * Copyright (c) 2015-2016 LunarG, Inc.
      4  * Copyright (C) 2015-2016 Google Inc.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Tobin Ehlis <tobine (at) google.com>
     19  */
     20 
     21 #include "vk_loader_platform.h"
     22 #include "vulkan/vulkan.h"
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <cinttypes>
     28 
     29 #include <unordered_map>
     30 #include <vector>
     31 #include <mutex>
     32 
     33 #include "vulkan/vk_layer.h"
     34 #include "vk_layer_config.h"
     35 #include "vk_layer_table.h"
     36 #include "vk_layer_data.h"
     37 #include "vk_layer_logging.h"
     38 #include "vk_layer_extension_utils.h"
     39 #include "vk_safe_struct.h"
     40 #include "vk_layer_utils.h"
     41 
     42 namespace unique_objects {
     43 
     44 // All increments must be guarded by global_lock
     45 static uint64_t global_unique_id = 1;
     46 
     47 struct layer_data {
     48     VkInstance instance;
     49 
     50     bool wsi_enabled;
     51     std::unordered_map<uint64_t, uint64_t> unique_id_mapping; // Map uniqueID to actual object handle
     52     VkPhysicalDevice gpu;
     53 
     54     layer_data() : wsi_enabled(false), gpu(VK_NULL_HANDLE){};
     55 };
     56 
     57 struct instExts {
     58     bool wsi_enabled;
     59     bool xlib_enabled;
     60     bool xcb_enabled;
     61     bool wayland_enabled;
     62     bool mir_enabled;
     63     bool android_enabled;
     64     bool win32_enabled;
     65 };
     66 
     67 static std::unordered_map<void *, struct instExts> instanceExtMap;
     68 static std::unordered_map<void *, layer_data *> layer_data_map;
     69 static device_table_map unique_objects_device_table_map;
     70 static instance_table_map unique_objects_instance_table_map;
     71 static std::mutex global_lock; // Protect map accesses and unique_id increments
     72 
     73 // Handle CreateInstance
     74 static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
     75     uint32_t i;
     76     VkLayerInstanceDispatchTable *pDisp = get_dispatch_table(unique_objects_instance_table_map, instance);
     77     PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
     78 
     79     pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR");
     80     pDisp->GetPhysicalDeviceSurfaceSupportKHR =
     81         (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
     82     pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR =
     83         (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
     84     pDisp->GetPhysicalDeviceSurfaceFormatsKHR =
     85         (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
     86     pDisp->GetPhysicalDeviceSurfacePresentModesKHR =
     87         (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
     88 #ifdef VK_USE_PLATFORM_WIN32_KHR
     89     pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR");
     90     pDisp->GetPhysicalDeviceWin32PresentationSupportKHR =
     91         (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
     92 #endif // VK_USE_PLATFORM_WIN32_KHR
     93 #ifdef VK_USE_PLATFORM_XCB_KHR
     94     pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(instance, "vkCreateXcbSurfaceKHR");
     95     pDisp->GetPhysicalDeviceXcbPresentationSupportKHR =
     96         (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
     97 #endif // VK_USE_PLATFORM_XCB_KHR
     98 #ifdef VK_USE_PLATFORM_XLIB_KHR
     99     pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(instance, "vkCreateXlibSurfaceKHR");
    100     pDisp->GetPhysicalDeviceXlibPresentationSupportKHR =
    101         (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
    102 #endif // VK_USE_PLATFORM_XLIB_KHR
    103 #ifdef VK_USE_PLATFORM_MIR_KHR
    104     pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)gpa(instance, "vkCreateMirSurfaceKHR");
    105     pDisp->GetPhysicalDeviceMirPresentationSupportKHR =
    106         (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
    107 #endif // VK_USE_PLATFORM_MIR_KHR
    108 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
    109     pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(instance, "vkCreateWaylandSurfaceKHR");
    110     pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR =
    111         (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
    112 #endif //  VK_USE_PLATFORM_WAYLAND_KHR
    113 #ifdef VK_USE_PLATFORM_ANDROID_KHR
    114     pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(instance, "vkCreateAndroidSurfaceKHR");
    115 #endif // VK_USE_PLATFORM_ANDROID_KHR
    116 
    117     instanceExtMap[pDisp] = {};
    118     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
    119         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0)
    120             instanceExtMap[pDisp].wsi_enabled = true;
    121 #ifdef VK_USE_PLATFORM_XLIB_KHR
    122         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0)
    123             instanceExtMap[pDisp].xlib_enabled = true;
    124 #endif
    125 #ifdef VK_USE_PLATFORM_XCB_KHR
    126         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0)
    127             instanceExtMap[pDisp].xcb_enabled = true;
    128 #endif
    129 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
    130         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0)
    131             instanceExtMap[pDisp].wayland_enabled = true;
    132 #endif
    133 #ifdef VK_USE_PLATFORM_MIR_KHR
    134         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0)
    135             instanceExtMap[pDisp].mir_enabled = true;
    136 #endif
    137 #ifdef VK_USE_PLATFORM_ANDROID_KHR
    138         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0)
    139             instanceExtMap[pDisp].android_enabled = true;
    140 #endif
    141 #ifdef VK_USE_PLATFORM_WIN32_KHR
    142         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0)
    143             instanceExtMap[pDisp].win32_enabled = true;
    144 #endif
    145     }
    146 }
    147 
    148 VkResult explicit_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
    149                                  VkInstance *pInstance) {
    150     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    151 
    152     assert(chain_info->u.pLayerInfo);
    153     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    154     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
    155     if (fpCreateInstance == NULL) {
    156         return VK_ERROR_INITIALIZATION_FAILED;
    157     }
    158 
    159     // Advance the link info for the next element on the chain
    160     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    161 
    162     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
    163     if (result != VK_SUCCESS) {
    164         return result;
    165     }
    166 
    167     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
    168     my_data->instance = *pInstance;
    169     initInstanceTable(*pInstance, fpGetInstanceProcAddr, unique_objects_instance_table_map);
    170 
    171     createInstanceRegisterExtensions(pCreateInfo, *pInstance);
    172 
    173     return result;
    174 }
    175 
    176 void explicit_DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
    177     dispatch_key key = get_dispatch_key(instance);
    178     get_dispatch_table(unique_objects_instance_table_map, instance)->DestroyInstance(instance, pAllocator);
    179     layer_data_map.erase(key);
    180 }
    181 
    182 // Handle CreateDevice
    183 static void createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
    184     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    185     VkLayerDispatchTable *pDisp = get_dispatch_table(unique_objects_device_table_map, device);
    186     PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
    187     pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
    188     pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
    189     pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
    190     pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
    191     pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
    192     my_device_data->wsi_enabled = false;
    193     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
    194         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
    195             my_device_data->wsi_enabled = true;
    196     }
    197 }
    198 
    199 VkResult explicit_CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
    200                                VkDevice *pDevice) {
    201     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
    202     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    203 
    204     assert(chain_info->u.pLayerInfo);
    205     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    206     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
    207     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
    208     if (fpCreateDevice == NULL) {
    209         return VK_ERROR_INITIALIZATION_FAILED;
    210     }
    211 
    212     // Advance the link info for the next element on the chain
    213     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    214 
    215     VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
    216     if (result != VK_SUCCESS) {
    217         return result;
    218     }
    219 
    220     // Setup layer's device dispatch table
    221     initDeviceTable(*pDevice, fpGetDeviceProcAddr, unique_objects_device_table_map);
    222 
    223     createDeviceRegisterExtensions(pCreateInfo, *pDevice);
    224     // Set gpu for this device in order to get at any objects mapped at instance level
    225     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
    226     my_device_data->gpu = gpu;
    227 
    228     return result;
    229 }
    230 
    231 void explicit_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
    232     dispatch_key key = get_dispatch_key(device);
    233     get_dispatch_table(unique_objects_device_table_map, device)->DestroyDevice(device, pAllocator);
    234     layer_data_map.erase(key);
    235 }
    236 
    237 VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
    238                                          const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
    239                                          VkPipeline *pPipelines) {
    240     // STRUCT USES:{'pipelineCache': 'VkPipelineCache', 'pCreateInfos[createInfoCount]': {'stage': {'module': 'VkShaderModule'},
    241     // 'layout': 'VkPipelineLayout', 'basePipelineHandle': 'VkPipeline'}}
    242     // LOCAL DECLS:{'pCreateInfos': 'VkComputePipelineCreateInfo*'}
    243     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    244     safe_VkComputePipelineCreateInfo *local_pCreateInfos = NULL;
    245     if (pCreateInfos) {
    246         std::lock_guard<std::mutex> lock(global_lock);
    247         local_pCreateInfos = new safe_VkComputePipelineCreateInfo[createInfoCount];
    248         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
    249             local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
    250             if (pCreateInfos[idx0].basePipelineHandle) {
    251                 local_pCreateInfos[idx0].basePipelineHandle =
    252                     (VkPipeline)my_device_data
    253                         ->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].basePipelineHandle)];
    254             }
    255             if (pCreateInfos[idx0].layout) {
    256                 local_pCreateInfos[idx0].layout =
    257                     (VkPipelineLayout)
    258                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].layout)];
    259             }
    260             if (pCreateInfos[idx0].stage.module) {
    261                 local_pCreateInfos[idx0].stage.module =
    262                     (VkShaderModule)
    263                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].stage.module)];
    264             }
    265         }
    266     }
    267     if (pipelineCache) {
    268         std::lock_guard<std::mutex> lock(global_lock);
    269         pipelineCache = (VkPipelineCache)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t &>(pipelineCache)];
    270     }
    271 
    272     VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
    273                           ->CreateComputePipelines(device, pipelineCache, createInfoCount,
    274                                                    (const VkComputePipelineCreateInfo *)local_pCreateInfos, pAllocator, pPipelines);
    275     delete[] local_pCreateInfos;
    276     if (VK_SUCCESS == result) {
    277         uint64_t unique_id = 0;
    278         std::lock_guard<std::mutex> lock(global_lock);
    279         for (uint32_t i = 0; i < createInfoCount; ++i) {
    280             unique_id = global_unique_id++;
    281             my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(pPipelines[i]);
    282             pPipelines[i] = reinterpret_cast<VkPipeline &>(unique_id);
    283         }
    284     }
    285     return result;
    286 }
    287 
    288 VkResult explicit_CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
    289                                           const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
    290                                           VkPipeline *pPipelines) {
    291     // STRUCT USES:{'pipelineCache': 'VkPipelineCache', 'pCreateInfos[createInfoCount]': {'layout': 'VkPipelineLayout',
    292     // 'pStages[stageCount]': {'module': 'VkShaderModule'}, 'renderPass': 'VkRenderPass', 'basePipelineHandle': 'VkPipeline'}}
    293     // LOCAL DECLS:{'pCreateInfos': 'VkGraphicsPipelineCreateInfo*'}
    294     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    295     safe_VkGraphicsPipelineCreateInfo *local_pCreateInfos = NULL;
    296     if (pCreateInfos) {
    297         local_pCreateInfos = new safe_VkGraphicsPipelineCreateInfo[createInfoCount];
    298         std::lock_guard<std::mutex> lock(global_lock);
    299         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
    300             local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
    301             if (pCreateInfos[idx0].basePipelineHandle) {
    302                 local_pCreateInfos[idx0].basePipelineHandle =
    303                     (VkPipeline)my_device_data
    304                         ->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].basePipelineHandle)];
    305             }
    306             if (pCreateInfos[idx0].layout) {
    307                 local_pCreateInfos[idx0].layout =
    308                     (VkPipelineLayout)
    309                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].layout)];
    310             }
    311             if (pCreateInfos[idx0].pStages) {
    312                 for (uint32_t idx1 = 0; idx1 < pCreateInfos[idx0].stageCount; ++idx1) {
    313                     if (pCreateInfos[idx0].pStages[idx1].module) {
    314                         local_pCreateInfos[idx0].pStages[idx1].module =
    315                             (VkShaderModule)my_device_data
    316                                 ->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].pStages[idx1].module)];
    317                     }
    318                 }
    319             }
    320             if (pCreateInfos[idx0].renderPass) {
    321                 local_pCreateInfos[idx0].renderPass =
    322                     (VkRenderPass)
    323                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].renderPass)];
    324             }
    325         }
    326     }
    327     if (pipelineCache) {
    328         std::lock_guard<std::mutex> lock(global_lock);
    329         pipelineCache = (VkPipelineCache)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t &>(pipelineCache)];
    330     }
    331 
    332     VkResult result =
    333         get_dispatch_table(unique_objects_device_table_map, device)
    334             ->CreateGraphicsPipelines(device, pipelineCache, createInfoCount,
    335                                       (const VkGraphicsPipelineCreateInfo *)local_pCreateInfos, pAllocator, pPipelines);
    336     delete[] local_pCreateInfos;
    337     if (VK_SUCCESS == result) {
    338         uint64_t unique_id = 0;
    339         std::lock_guard<std::mutex> lock(global_lock);
    340         for (uint32_t i = 0; i < createInfoCount; ++i) {
    341             unique_id = global_unique_id++;
    342             my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(pPipelines[i]);
    343             pPipelines[i] = reinterpret_cast<VkPipeline &>(unique_id);
    344         }
    345     }
    346     return result;
    347 }
    348 
    349 VkResult explicit_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
    350                                      const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
    351     layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    352 
    353     safe_VkSwapchainCreateInfoKHR *local_pCreateInfo = NULL;
    354     if (pCreateInfo) {
    355         std::lock_guard<std::mutex> lock(global_lock);
    356         local_pCreateInfo = new safe_VkSwapchainCreateInfoKHR(pCreateInfo);
    357         local_pCreateInfo->oldSwapchain =
    358             (VkSwapchainKHR)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfo->oldSwapchain)];
    359         // Need to pull surface mapping from the instance-level map
    360         layer_data *instance_data = get_my_data_ptr(get_dispatch_key(my_map_data->gpu), layer_data_map);
    361         local_pCreateInfo->surface =
    362             (VkSurfaceKHR)instance_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfo->surface)];
    363     }
    364 
    365     VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
    366                           ->CreateSwapchainKHR(device, (const VkSwapchainCreateInfoKHR *)local_pCreateInfo, pAllocator, pSwapchain);
    367     if (local_pCreateInfo)
    368         delete local_pCreateInfo;
    369     if (VK_SUCCESS == result) {
    370         std::lock_guard<std::mutex> lock(global_lock);
    371         uint64_t unique_id =global_unique_id++;
    372         my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*pSwapchain);
    373         *pSwapchain = reinterpret_cast<VkSwapchainKHR &>(unique_id);
    374     }
    375     return result;
    376 }
    377 
    378 VkResult explicit_GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
    379                                         VkImage *pSwapchainImages) {
    380     // UNWRAP USES:
    381     //  0 : swapchain,VkSwapchainKHR, pSwapchainImages,VkImage
    382     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    383     if (VK_NULL_HANDLE != swapchain) {
    384         std::lock_guard<std::mutex> lock(global_lock);
    385         swapchain = (VkSwapchainKHR)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t &>(swapchain)];
    386     }
    387     VkResult result = get_dispatch_table(unique_objects_device_table_map, device)
    388                           ->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
    389     // TODO : Need to add corresponding code to delete these images
    390     if (VK_SUCCESS == result) {
    391         if ((*pSwapchainImageCount > 0) && pSwapchainImages) {
    392             uint64_t unique_id = 0;
    393             std::lock_guard<std::mutex> lock(global_lock);
    394             for (uint32_t i = 0; i < *pSwapchainImageCount; ++i) {
    395                 unique_id = global_unique_id++;
    396                 my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(pSwapchainImages[i]);
    397                 pSwapchainImages[i] = reinterpret_cast<VkImage &>(unique_id);
    398             }
    399         }
    400     }
    401     return result;
    402 }
    403 
    404 } // namespace unique_objects
    405