Home | History | Annotate | Download | only in layers
      1 /*
      2  * Copyright (c) 2015-2016 The Khronos Group Inc.
      3  * Copyright (c) 2015-2016 Valve Corporation
      4  * Copyright (c) 2015-2016 LunarG, Inc.
      5  * Copyright (c) 2015-2016 Google, Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *     http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  * Author: Tobin Ehlis <tobine (at) google.com>
     20  * Author: Mark Lobodzinski <mark (at) lunarg.com>
     21  */
     22 
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <unordered_map>
     27 #include <vector>
     28 #include <list>
     29 #include <memory>
     30 
     31 #include "vk_loader_platform.h"
     32 #include "vulkan/vk_layer.h"
     33 #include "vk_layer_config.h"
     34 #include "vk_layer_extension_utils.h"
     35 #include "vk_layer_utils.h"
     36 #include "vk_layer_table.h"
     37 #include "vk_layer_logging.h"
     38 #include "unique_objects.h"
     39 #include "vk_dispatch_table_helper.h"
     40 #include "vk_struct_string_helper_cpp.h"
     41 #include "vk_layer_data.h"
     42 #include "vk_layer_utils.h"
     43 
     44 #include "unique_objects_wrappers.h"
     45 
     46 namespace unique_objects {
     47 
     48 static void initUniqueObjects(layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
     49     layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "google_unique_objects");
     50 }
     51 
     52 // Handle CreateInstance Extensions
     53 static void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
     54     uint32_t i;
     55     layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     56     VkLayerInstanceDispatchTable *disp_table = instance_data->instance_dispatch_table;
     57     instance_ext_map[disp_table] = {};
     58 
     59     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
     60         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
     61             instance_ext_map[disp_table].wsi_enabled = true;
     62         }
     63         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
     64             instance_ext_map[disp_table].display_enabled = true;
     65         }
     66 #ifdef VK_USE_PLATFORM_XLIB_KHR
     67         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
     68             instance_ext_map[disp_table].xlib_enabled = true;
     69         }
     70 #endif
     71 #ifdef VK_USE_PLATFORM_XCB_KHR
     72         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
     73             instance_ext_map[disp_table].xcb_enabled = true;
     74         }
     75 #endif
     76 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
     77         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
     78             instance_ext_map[disp_table].wayland_enabled = true;
     79         }
     80 #endif
     81 #ifdef VK_USE_PLATFORM_MIR_KHR
     82         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
     83             instance_ext_map[disp_table].mir_enabled = true;
     84         }
     85 #endif
     86 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     87         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
     88             instance_ext_map[disp_table].android_enabled = true;
     89         }
     90 #endif
     91 #ifdef VK_USE_PLATFORM_WIN32_KHR
     92         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
     93             instance_ext_map[disp_table].win32_enabled = true;
     94         }
     95 #endif
     96 
     97         // Check for recognized instance extensions
     98         layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     99         if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kUniqueObjectsSupportedInstanceExtensions)) {
    100             log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
    101                     0, "UniqueObjects",
    102                     "Instance Extension %s is not supported by this layer.  Using this extension may adversely affect "
    103                     "validation results and/or produce undefined behavior.",
    104                     pCreateInfo->ppEnabledExtensionNames[i]);
    105         }
    106     }
    107 }
    108 
    109 // Handle CreateDevice Extensions
    110 static void createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
    111     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    112     VkLayerDispatchTable *disp_table = device_data->device_dispatch_table;
    113     PFN_vkGetDeviceProcAddr gpa = disp_table->GetDeviceProcAddr;
    114 
    115     device_data->device_dispatch_table->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
    116     disp_table->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
    117     disp_table->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
    118     disp_table->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
    119     disp_table->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
    120     device_data->wsi_enabled = false;
    121 
    122     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
    123         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
    124             device_data->wsi_enabled = true;
    125         }
    126         // Check for recognized device extensions
    127         if (!white_list(pCreateInfo->ppEnabledExtensionNames[i], kUniqueObjectsSupportedDeviceExtensions)) {
    128             log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
    129                     0, "UniqueObjects",
    130                     "Device Extension %s is not supported by this layer.  Using this extension may adversely affect "
    131                     "validation results and/or produce undefined behavior.",
    132                     pCreateInfo->ppEnabledExtensionNames[i]);
    133         }
    134     }
    135 }
    136 
    137 VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
    138                                               VkInstance *pInstance) {
    139     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    140 
    141     assert(chain_info->u.pLayerInfo);
    142     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    143     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
    144     if (fpCreateInstance == NULL) {
    145         return VK_ERROR_INITIALIZATION_FAILED;
    146     }
    147 
    148     // Advance the link info for the next element on the chain
    149     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    150 
    151     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
    152     if (result != VK_SUCCESS) {
    153         return result;
    154     }
    155 
    156     layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
    157     instance_data->instance = *pInstance;
    158     instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
    159     layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr);
    160 
    161     instance_data->instance = *pInstance;
    162     instance_data->report_data =
    163         debug_report_create_instance(instance_data->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
    164                                      pCreateInfo->ppEnabledExtensionNames);
    165 
    166     // Set up temporary debug callbacks to output messages at CreateInstance-time
    167     if (!layer_copy_tmp_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_callbacks, &instance_data->tmp_dbg_create_infos,
    168                                   &instance_data->tmp_callbacks)) {
    169         if (instance_data->num_tmp_callbacks > 0) {
    170             if (layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks,
    171                                            instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) {
    172                 layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks);
    173                 instance_data->num_tmp_callbacks = 0;
    174             }
    175         }
    176     }
    177 
    178     initUniqueObjects(instance_data, pAllocator);
    179     checkInstanceRegisterExtensions(pCreateInfo, *pInstance);
    180 
    181     // Disable and free tmp callbacks, no longer necessary
    182     if (instance_data->num_tmp_callbacks > 0) {
    183         layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks);
    184         layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks);
    185         instance_data->num_tmp_callbacks = 0;
    186     }
    187 
    188     return result;
    189 }
    190 
    191 VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
    192     dispatch_key key = get_dispatch_key(instance);
    193     layer_data *instance_data = get_my_data_ptr(key, layer_data_map);
    194     VkLayerInstanceDispatchTable *disp_table = instance_data->instance_dispatch_table;
    195     instance_ext_map.erase(disp_table);
    196     disp_table->DestroyInstance(instance, pAllocator);
    197 
    198     // Clean up logging callback, if any
    199     while (instance_data->logging_callback.size() > 0) {
    200         VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
    201         layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
    202         instance_data->logging_callback.pop_back();
    203     }
    204 
    205     layer_debug_report_destroy_instance(instance_data->report_data);
    206     layer_data_map.erase(key);
    207 }
    208 
    209 VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
    210                                             const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
    211     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
    212     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    213 
    214     assert(chain_info->u.pLayerInfo);
    215     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    216     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
    217     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
    218     if (fpCreateDevice == NULL) {
    219         return VK_ERROR_INITIALIZATION_FAILED;
    220     }
    221 
    222     // Advance the link info for the next element on the chain
    223     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    224 
    225     VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
    226     if (result != VK_SUCCESS) {
    227         return result;
    228     }
    229 
    230     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
    231     my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
    232 
    233     // Setup layer's device dispatch table
    234     my_device_data->device_dispatch_table = new VkLayerDispatchTable;
    235     layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
    236 
    237     createDeviceRegisterExtensions(pCreateInfo, *pDevice);
    238     // Set gpu for this device in order to get at any objects mapped at instance level
    239 
    240     my_device_data->gpu = gpu;
    241 
    242     return result;
    243 }
    244 
    245 VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
    246     dispatch_key key = get_dispatch_key(device);
    247     layer_data *dev_data = get_my_data_ptr(key, layer_data_map);
    248 
    249     layer_debug_report_destroy_device(device);
    250     dev_data->device_dispatch_table->DestroyDevice(device, pAllocator);
    251     layer_data_map.erase(key);
    252 }
    253 
    254 static const VkLayerProperties globalLayerProps = {"VK_LAYER_GOOGLE_unique_objects",
    255                                                    VK_LAYER_API_VERSION, // specVersion
    256                                                    1,                    // implementationVersion
    257                                                    "Google Validation Layer"};
    258 
    259 static inline PFN_vkVoidFunction layer_intercept_proc(const char *name) {
    260     for (int i = 0; i < sizeof(procmap) / sizeof(procmap[0]); i++) {
    261         if (!strcmp(name, procmap[i].name))
    262             return procmap[i].pFunc;
    263     }
    264     return NULL;
    265 }
    266 
    267 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
    268     return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);
    269 }
    270 
    271 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
    272                                                               VkLayerProperties *pProperties) {
    273     return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);
    274 }
    275 
    276 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
    277                                                                     VkExtensionProperties *pProperties) {
    278     if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))
    279         return util_GetExtensionProperties(0, NULL, pCount, pProperties);
    280 
    281     return VK_ERROR_LAYER_NOT_PRESENT;
    282 }
    283 
    284 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
    285                                                                   uint32_t *pCount, VkExtensionProperties *pProperties) {
    286     if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))
    287         return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
    288 
    289     assert(physicalDevice);
    290 
    291     dispatch_key key = get_dispatch_key(physicalDevice);
    292     layer_data *instance_data = get_my_data_ptr(key, layer_data_map);
    293     return instance_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
    294 }
    295 
    296 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
    297     PFN_vkVoidFunction addr;
    298     assert(device);
    299     addr = layer_intercept_proc(funcName);
    300     if (addr) {
    301         return addr;
    302     }
    303 
    304     layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    305     VkLayerDispatchTable *disp_table = dev_data->device_dispatch_table;
    306     if (disp_table->GetDeviceProcAddr == NULL) {
    307         return NULL;
    308     }
    309     return disp_table->GetDeviceProcAddr(device, funcName);
    310 }
    311 
    312 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
    313     PFN_vkVoidFunction addr;
    314 
    315     addr = layer_intercept_proc(funcName);
    316     if (addr) {
    317         return addr;
    318     }
    319     assert(instance);
    320 
    321     layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    322     addr = debug_report_get_instance_proc_addr(instance_data->report_data, funcName);
    323     if (addr) {
    324         return addr;
    325     }
    326 
    327     VkLayerInstanceDispatchTable *disp_table = instance_data->instance_dispatch_table;
    328     if (disp_table->GetInstanceProcAddr == NULL) {
    329         return NULL;
    330     }
    331     return disp_table->GetInstanceProcAddr(instance, funcName);
    332 }
    333 
    334 VKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
    335                                               const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
    336     const VkMemoryAllocateInfo *input_allocate_info = pAllocateInfo;
    337     std::unique_ptr<safe_VkMemoryAllocateInfo> safe_allocate_info;
    338     std::unique_ptr<safe_VkDedicatedAllocationMemoryAllocateInfoNV> safe_dedicated_allocate_info;
    339     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    340 
    341     if ((pAllocateInfo != nullptr) &&
    342         ContainsExtStruct(pAllocateInfo, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV)) {
    343         // Assuming there is only one extension struct of this type in the list for now
    344         safe_dedicated_allocate_info =
    345             std::unique_ptr<safe_VkDedicatedAllocationMemoryAllocateInfoNV>(new safe_VkDedicatedAllocationMemoryAllocateInfoNV);
    346         safe_allocate_info = std::unique_ptr<safe_VkMemoryAllocateInfo>(new safe_VkMemoryAllocateInfo(pAllocateInfo));
    347         input_allocate_info = reinterpret_cast<const VkMemoryAllocateInfo *>(safe_allocate_info.get());
    348 
    349         const GenericHeader *orig_pnext = reinterpret_cast<const GenericHeader *>(pAllocateInfo->pNext);
    350         GenericHeader *input_pnext = reinterpret_cast<GenericHeader *>(safe_allocate_info.get());
    351         while (orig_pnext != nullptr) {
    352             if (orig_pnext->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV) {
    353                 safe_dedicated_allocate_info->initialize(
    354                     reinterpret_cast<const VkDedicatedAllocationMemoryAllocateInfoNV *>(orig_pnext));
    355 
    356                 std::unique_lock<std::mutex> lock(global_lock);
    357 
    358                 if (safe_dedicated_allocate_info->buffer != VK_NULL_HANDLE) {
    359                     uint64_t local_buffer = reinterpret_cast<uint64_t &>(safe_dedicated_allocate_info->buffer);
    360                     safe_dedicated_allocate_info->buffer =
    361                         reinterpret_cast<VkBuffer &>(device_data->unique_id_mapping[local_buffer]);
    362                 }
    363 
    364                 if (safe_dedicated_allocate_info->image != VK_NULL_HANDLE) {
    365                     uint64_t local_image = reinterpret_cast<uint64_t &>(safe_dedicated_allocate_info->image);
    366                     safe_dedicated_allocate_info->image = reinterpret_cast<VkImage &>(device_data->unique_id_mapping[local_image]);
    367                 }
    368 
    369                 lock.unlock();
    370 
    371                 input_pnext->pNext = reinterpret_cast<GenericHeader *>(safe_dedicated_allocate_info.get());
    372                 input_pnext = reinterpret_cast<GenericHeader *>(input_pnext->pNext);
    373             } else {
    374                 // TODO: generic handling of pNext copies
    375             }
    376 
    377             orig_pnext = reinterpret_cast<const GenericHeader *>(orig_pnext->pNext);
    378         }
    379     }
    380 
    381     VkResult result = device_data->device_dispatch_table->AllocateMemory(device, input_allocate_info, pAllocator, pMemory);
    382 
    383     if (VK_SUCCESS == result) {
    384         std::lock_guard<std::mutex> lock(global_lock);
    385         uint64_t unique_id = global_unique_id++;
    386         device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*pMemory);
    387         *pMemory = reinterpret_cast<VkDeviceMemory &>(unique_id);
    388     }
    389 
    390     return result;
    391 }
    392 
    393 VKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
    394                                                       const VkComputePipelineCreateInfo *pCreateInfos,
    395                                                       const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
    396     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    397     safe_VkComputePipelineCreateInfo *local_pCreateInfos = NULL;
    398     if (pCreateInfos) {
    399         std::lock_guard<std::mutex> lock(global_lock);
    400         local_pCreateInfos = new safe_VkComputePipelineCreateInfo[createInfoCount];
    401         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
    402             local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
    403             if (pCreateInfos[idx0].basePipelineHandle) {
    404                 local_pCreateInfos[idx0].basePipelineHandle =
    405                     (VkPipeline)my_device_data
    406                         ->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].basePipelineHandle)];
    407             }
    408             if (pCreateInfos[idx0].layout) {
    409                 local_pCreateInfos[idx0].layout =
    410                     (VkPipelineLayout)
    411                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].layout)];
    412             }
    413             if (pCreateInfos[idx0].stage.module) {
    414                 local_pCreateInfos[idx0].stage.module =
    415                     (VkShaderModule)
    416                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].stage.module)];
    417             }
    418         }
    419     }
    420     if (pipelineCache) {
    421         std::lock_guard<std::mutex> lock(global_lock);
    422         pipelineCache = (VkPipelineCache)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t &>(pipelineCache)];
    423     }
    424 
    425     VkResult result = my_device_data->device_dispatch_table->CreateComputePipelines(
    426         device, pipelineCache, createInfoCount, (const VkComputePipelineCreateInfo *)local_pCreateInfos, pAllocator, pPipelines);
    427     delete[] local_pCreateInfos;
    428     if (VK_SUCCESS == result) {
    429         uint64_t unique_id = 0;
    430         std::lock_guard<std::mutex> lock(global_lock);
    431         for (uint32_t i = 0; i < createInfoCount; ++i) {
    432             unique_id = global_unique_id++;
    433             my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(pPipelines[i]);
    434             pPipelines[i] = reinterpret_cast<VkPipeline &>(unique_id);
    435         }
    436     }
    437     return result;
    438 }
    439 
    440 VKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
    441                                                        const VkGraphicsPipelineCreateInfo *pCreateInfos,
    442                                                        const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
    443     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    444     safe_VkGraphicsPipelineCreateInfo *local_pCreateInfos = NULL;
    445     if (pCreateInfos) {
    446         local_pCreateInfos = new safe_VkGraphicsPipelineCreateInfo[createInfoCount];
    447         std::lock_guard<std::mutex> lock(global_lock);
    448         for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
    449             local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
    450             if (pCreateInfos[idx0].basePipelineHandle) {
    451                 local_pCreateInfos[idx0].basePipelineHandle =
    452                     (VkPipeline)my_device_data
    453                         ->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].basePipelineHandle)];
    454             }
    455             if (pCreateInfos[idx0].layout) {
    456                 local_pCreateInfos[idx0].layout =
    457                     (VkPipelineLayout)
    458                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].layout)];
    459             }
    460             if (pCreateInfos[idx0].pStages) {
    461                 for (uint32_t idx1 = 0; idx1 < pCreateInfos[idx0].stageCount; ++idx1) {
    462                     if (pCreateInfos[idx0].pStages[idx1].module) {
    463                         local_pCreateInfos[idx0].pStages[idx1].module =
    464                             (VkShaderModule)my_device_data
    465                                 ->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].pStages[idx1].module)];
    466                     }
    467                 }
    468             }
    469             if (pCreateInfos[idx0].renderPass) {
    470                 local_pCreateInfos[idx0].renderPass =
    471                     (VkRenderPass)
    472                         my_device_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfos[idx0].renderPass)];
    473             }
    474         }
    475     }
    476     if (pipelineCache) {
    477         std::lock_guard<std::mutex> lock(global_lock);
    478         pipelineCache = (VkPipelineCache)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t &>(pipelineCache)];
    479     }
    480 
    481     VkResult result = my_device_data->device_dispatch_table->CreateGraphicsPipelines(
    482         device, pipelineCache, createInfoCount, (const VkGraphicsPipelineCreateInfo *)local_pCreateInfos, pAllocator, pPipelines);
    483     delete[] local_pCreateInfos;
    484     if (VK_SUCCESS == result) {
    485         uint64_t unique_id = 0;
    486         std::lock_guard<std::mutex> lock(global_lock);
    487         for (uint32_t i = 0; i < createInfoCount; ++i) {
    488             unique_id = global_unique_id++;
    489             my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(pPipelines[i]);
    490             pPipelines[i] = reinterpret_cast<VkPipeline &>(unique_id);
    491         }
    492     }
    493     return result;
    494 }
    495 
    496 VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
    497                                                             const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
    498                                                             const VkAllocationCallbacks *pAllocator,
    499                                                             VkDebugReportCallbackEXT *pMsgCallback) {
    500     layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    501     VkResult result =
    502         instance_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
    503 
    504     if (VK_SUCCESS == result) {
    505         result = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
    506     }
    507     return result;
    508 }
    509 
    510 VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
    511                                                          const VkAllocationCallbacks *pAllocator) {
    512     layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    513     instance_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
    514     layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
    515 }
    516 
    517 VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
    518                                                  VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
    519                                                  int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
    520     layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    521     instance_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
    522                                                                   pMsg);
    523 }
    524 
    525 VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
    526                                                   const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
    527     layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    528     safe_VkSwapchainCreateInfoKHR *local_pCreateInfo = NULL;
    529     if (pCreateInfo) {
    530         std::lock_guard<std::mutex> lock(global_lock);
    531         local_pCreateInfo = new safe_VkSwapchainCreateInfoKHR(pCreateInfo);
    532         local_pCreateInfo->oldSwapchain =
    533             (VkSwapchainKHR)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfo->oldSwapchain)];
    534         // Need to pull surface mapping from the instance-level map
    535         layer_data *instance_data = get_my_data_ptr(get_dispatch_key(my_map_data->gpu), layer_data_map);
    536         local_pCreateInfo->surface =
    537             (VkSurfaceKHR)instance_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pCreateInfo->surface)];
    538     }
    539 
    540     VkResult result = my_map_data->device_dispatch_table->CreateSwapchainKHR(
    541         device, (const VkSwapchainCreateInfoKHR *)local_pCreateInfo, pAllocator, pSwapchain);
    542     if (local_pCreateInfo) {
    543         delete local_pCreateInfo;
    544     }
    545     if (VK_SUCCESS == result) {
    546         std::lock_guard<std::mutex> lock(global_lock);
    547         uint64_t unique_id = global_unique_id++;
    548         my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*pSwapchain);
    549         *pSwapchain = reinterpret_cast<VkSwapchainKHR &>(unique_id);
    550     }
    551     return result;
    552 }
    553 
    554 VKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
    555                                                      VkImage *pSwapchainImages) {
    556     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    557     if (VK_NULL_HANDLE != swapchain) {
    558         std::lock_guard<std::mutex> lock(global_lock);
    559         swapchain = (VkSwapchainKHR)my_device_data->unique_id_mapping[reinterpret_cast<uint64_t &>(swapchain)];
    560     }
    561     VkResult result =
    562         my_device_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
    563     // TODO : Need to add corresponding code to delete these images
    564     if (VK_SUCCESS == result) {
    565         if ((*pSwapchainImageCount > 0) && pSwapchainImages) {
    566             uint64_t unique_id = 0;
    567             std::lock_guard<std::mutex> lock(global_lock);
    568             for (uint32_t i = 0; i < *pSwapchainImageCount; ++i) {
    569                 unique_id = global_unique_id++;
    570                 my_device_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(pSwapchainImages[i]);
    571                 pSwapchainImages[i] = reinterpret_cast<VkImage &>(unique_id);
    572             }
    573         }
    574     }
    575     return result;
    576 }
    577 
    578 #ifndef __ANDROID__
    579 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
    580                                                                      VkDisplayPropertiesKHR *pProperties) {
    581     layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    582     safe_VkDisplayPropertiesKHR *local_pProperties = NULL;
    583     {
    584         std::lock_guard<std::mutex> lock(global_lock);
    585         if (pProperties) {
    586             local_pProperties = new safe_VkDisplayPropertiesKHR[*pPropertyCount];
    587             for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) {
    588                 local_pProperties[idx0].initialize(&pProperties[idx0]);
    589                 if (pProperties[idx0].display) {
    590                     local_pProperties[idx0].display =
    591                         (VkDisplayKHR)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(pProperties[idx0].display)];
    592                 }
    593             }
    594         }
    595     }
    596 
    597     VkResult result = my_map_data->instance_dispatch_table->GetPhysicalDeviceDisplayPropertiesKHR(
    598         physicalDevice, pPropertyCount, (VkDisplayPropertiesKHR *)local_pProperties);
    599     if (result == VK_SUCCESS && pProperties) {
    600         for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) {
    601             std::lock_guard<std::mutex> lock(global_lock);
    602 
    603             uint64_t unique_id = global_unique_id++;
    604             my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(local_pProperties[idx0].display);
    605             pProperties[idx0].display = reinterpret_cast<VkDisplayKHR &>(unique_id);
    606             pProperties[idx0].displayName = local_pProperties[idx0].displayName;
    607             pProperties[idx0].physicalDimensions = local_pProperties[idx0].physicalDimensions;
    608             pProperties[idx0].physicalResolution = local_pProperties[idx0].physicalResolution;
    609             pProperties[idx0].supportedTransforms = local_pProperties[idx0].supportedTransforms;
    610             pProperties[idx0].planeReorderPossible = local_pProperties[idx0].planeReorderPossible;
    611             pProperties[idx0].persistentContent = local_pProperties[idx0].persistentContent;
    612         }
    613     }
    614     if (local_pProperties) {
    615         delete[] local_pProperties;
    616     }
    617     return result;
    618 }
    619 
    620 VKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
    621                                                                    uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
    622     layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    623     VkResult result = my_map_data->instance_dispatch_table->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex,
    624                                                                                                 pDisplayCount, pDisplays);
    625     if (VK_SUCCESS == result) {
    626         if ((*pDisplayCount > 0) && pDisplays) {
    627             std::lock_guard<std::mutex> lock(global_lock);
    628             for (uint32_t i = 0; i < *pDisplayCount; i++) {
    629                 auto it = my_map_data->unique_id_mapping.find(reinterpret_cast<const uint64_t &>(pDisplays[i]));
    630                 assert(it != my_map_data->unique_id_mapping.end());
    631                 pDisplays[i] = reinterpret_cast<VkDisplayKHR &>(it->second);
    632             }
    633         }
    634     }
    635     return result;
    636 }
    637 
    638 VKAPI_ATTR VkResult VKAPI_CALL GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
    639                                                            uint32_t *pPropertyCount, VkDisplayModePropertiesKHR *pProperties) {
    640     layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    641     safe_VkDisplayModePropertiesKHR *local_pProperties = NULL;
    642     {
    643         std::lock_guard<std::mutex> lock(global_lock);
    644         display = (VkDisplayKHR)my_map_data->unique_id_mapping[reinterpret_cast<uint64_t &>(display)];
    645         if (pProperties) {
    646             local_pProperties = new safe_VkDisplayModePropertiesKHR[*pPropertyCount];
    647             for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) {
    648                 local_pProperties[idx0].initialize(&pProperties[idx0]);
    649             }
    650         }
    651     }
    652 
    653     VkResult result = my_map_data->instance_dispatch_table->GetDisplayModePropertiesKHR(
    654         physicalDevice, display, pPropertyCount, (VkDisplayModePropertiesKHR *)local_pProperties);
    655     if (result == VK_SUCCESS && pProperties) {
    656         for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) {
    657             std::lock_guard<std::mutex> lock(global_lock);
    658 
    659             uint64_t unique_id = global_unique_id++;
    660             my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(local_pProperties[idx0].displayMode);
    661             pProperties[idx0].displayMode = reinterpret_cast<VkDisplayModeKHR &>(unique_id);
    662             pProperties[idx0].parameters.visibleRegion.width = local_pProperties[idx0].parameters.visibleRegion.width;
    663             pProperties[idx0].parameters.visibleRegion.height = local_pProperties[idx0].parameters.visibleRegion.height;
    664             pProperties[idx0].parameters.refreshRate = local_pProperties[idx0].parameters.refreshRate;
    665         }
    666     }
    667     if (local_pProperties) {
    668         delete[] local_pProperties;
    669     }
    670     return result;
    671 }
    672 #endif
    673 
    674 } // namespace unique_objects
    675 
    676 // vk_layer_logging.h expects these to be defined
    677 VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance,
    678                                                               const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
    679                                                               const VkAllocationCallbacks *pAllocator,
    680                                                               VkDebugReportCallbackEXT *pMsgCallback) {
    681     return unique_objects::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
    682 }
    683 
    684 VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback,
    685                                                            const VkAllocationCallbacks *pAllocator) {
    686     unique_objects::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
    687 }
    688 
    689 VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
    690                                                    VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
    691                                                    int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
    692     unique_objects::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
    693 }
    694 
    695 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
    696                                                                                       VkExtensionProperties *pProperties) {
    697     return unique_objects::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
    698 }
    699 
    700 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
    701                                                                                   VkLayerProperties *pProperties) {
    702     return unique_objects::EnumerateInstanceLayerProperties(pCount, pProperties);
    703 }
    704 
    705 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
    706                                                                                 VkLayerProperties *pProperties) {
    707     assert(physicalDevice == VK_NULL_HANDLE);
    708     return unique_objects::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
    709 }
    710 
    711 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
    712     return unique_objects::GetDeviceProcAddr(dev, funcName);
    713 }
    714 
    715 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
    716     return unique_objects::GetInstanceProcAddr(instance, funcName);
    717 }
    718 
    719 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
    720                                                                                     const char *pLayerName, uint32_t *pCount,
    721                                                                                     VkExtensionProperties *pProperties) {
    722     assert(physicalDevice == VK_NULL_HANDLE);
    723     return unique_objects::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
    724 }
    725