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 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials 11 * are furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included 14 * in all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS 24 * 25 * Author: Ian Elliott <ian (at) lunarg.com> 26 * Author: Ian Elliott <ianelliott (at) google.com> 27 */ 28 29 #include <stdio.h> 30 #include <string.h> 31 #include <vk_loader_platform.h> 32 #include <vulkan/vk_icd.h> 33 #include "swapchain.h" 34 #include "vk_layer_extension_utils.h" 35 #include "vk_enum_string_helper.h" 36 #include "vk_layer_utils.h" 37 38 static int globalLockInitialized = 0; 39 static loader_platform_thread_mutex globalLock; 40 41 // The following is for logging error messages: 42 static std::unordered_map<void *, layer_data *> layer_data_map; 43 44 template layer_data *get_my_data_ptr<layer_data>(void *data_key, std::unordered_map<void *, layer_data *> &data_map); 45 46 static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 47 48 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 49 vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { 50 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties); 51 } 52 53 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 54 const char *pLayerName, uint32_t *pCount, 55 VkExtensionProperties *pProperties) { 56 if (pLayerName == NULL) { 57 dispatch_key key = get_dispatch_key(physicalDevice); 58 layer_data *my_data = get_my_data_ptr(key, layer_data_map); 59 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 60 } else { 61 return util_GetExtensionProperties(0, nullptr, pCount, pProperties); 62 } 63 } 64 65 static const VkLayerProperties swapchain_layers[] = {{ 66 "VK_LAYER_LUNARG_swapchain", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer", 67 }}; 68 69 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 70 vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 71 return util_GetLayerProperties(ARRAY_SIZE(swapchain_layers), swapchain_layers, pCount, pProperties); 72 } 73 74 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 75 vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { 76 return util_GetLayerProperties(ARRAY_SIZE(swapchain_layers), swapchain_layers, pCount, pProperties); 77 } 78 79 static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, 80 VkDevice device) { 81 uint32_t i; 82 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 83 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 84 85 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table; 86 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr; 87 88 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR"); 89 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR"); 90 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR"); 91 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR"); 92 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR"); 93 pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue)gpa(device, "vkGetDeviceQueue"); 94 95 SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice]; 96 if (pPhysicalDevice) { 97 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice; 98 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device]; 99 } else { 100 // TBD: Should we leave error in (since Swapchain really needs this 101 // link)? 102 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 103 (uint64_t)physicalDevice, __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain", 104 "vkCreateDevice() called with a non-valid VkPhysicalDevice."); 105 } 106 my_device_data->deviceMap[device].device = device; 107 my_device_data->deviceMap[device].swapchainExtensionEnabled = false; 108 109 // Record whether the WSI device extension was enabled for this VkDevice. 110 // No need to check if the extension was advertised by 111 // vkEnumerateDeviceExtensionProperties(), since the loader handles that. 112 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 113 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) { 114 115 my_device_data->deviceMap[device].swapchainExtensionEnabled = true; 116 } 117 } 118 } 119 120 static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) { 121 uint32_t i; 122 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 123 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table; 124 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr; 125 #ifdef VK_USE_PLATFORM_ANDROID_KHR 126 pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(instance, "vkCreateAndroidSurfaceKHR"); 127 #endif // VK_USE_PLATFORM_ANDROID_KHR 128 #ifdef VK_USE_PLATFORM_MIR_KHR 129 pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)gpa(instance, "vkCreateMirSurfaceKHR"); 130 pDisp->GetPhysicalDeviceMirPresentationSupportKHR = 131 (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR"); 132 #endif // VK_USE_PLATFORM_MIR_KHR 133 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 134 pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(instance, "vkCreateWaylandSurfaceKHR"); 135 pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR = 136 (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"); 137 #endif // VK_USE_PLATFORM_WAYLAND_KHR 138 #ifdef VK_USE_PLATFORM_WIN32_KHR 139 pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR"); 140 pDisp->GetPhysicalDeviceWin32PresentationSupportKHR = 141 (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR"); 142 #endif // VK_USE_PLATFORM_WIN32_KHR 143 #ifdef VK_USE_PLATFORM_XCB_KHR 144 pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(instance, "vkCreateXcbSurfaceKHR"); 145 pDisp->GetPhysicalDeviceXcbPresentationSupportKHR = 146 (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"); 147 #endif // VK_USE_PLATFORM_XCB_KHR 148 #ifdef VK_USE_PLATFORM_XLIB_KHR 149 pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(instance, "vkCreateXlibSurfaceKHR"); 150 pDisp->GetPhysicalDeviceXlibPresentationSupportKHR = 151 (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"); 152 #endif // VK_USE_PLATFORM_XLIB_KHR 153 pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR"); 154 pDisp->GetPhysicalDeviceSurfaceSupportKHR = 155 (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); 156 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = 157 (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); 158 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = 159 (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"); 160 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = 161 (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"); 162 163 // Remember this instance, and whether the VK_KHR_surface extension 164 // was enabled for it: 165 my_data->instanceMap[instance].instance = instance; 166 my_data->instanceMap[instance].surfaceExtensionEnabled = false; 167 #ifdef VK_USE_PLATFORM_ANDROID_KHR 168 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false; 169 #endif // VK_USE_PLATFORM_ANDROID_KHR 170 #ifdef VK_USE_PLATFORM_MIR_KHR 171 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false; 172 #endif // VK_USE_PLATFORM_MIR_KHR 173 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 174 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false; 175 #endif // VK_USE_PLATFORM_WAYLAND_KHR 176 #ifdef VK_USE_PLATFORM_WIN32_KHR 177 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false; 178 #endif // VK_USE_PLATFORM_WIN32_KHR 179 #ifdef VK_USE_PLATFORM_XCB_KHR 180 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false; 181 #endif // VK_USE_PLATFORM_XCB_KHR 182 #ifdef VK_USE_PLATFORM_XLIB_KHR 183 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false; 184 #endif // VK_USE_PLATFORM_XLIB_KHR 185 186 // Record whether the WSI instance extension was enabled for this 187 // VkInstance. No need to check if the extension was advertised by 188 // vkEnumerateInstanceExtensionProperties(), since the loader handles that. 189 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 190 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) { 191 192 my_data->instanceMap[instance].surfaceExtensionEnabled = true; 193 } 194 #ifdef VK_USE_PLATFORM_ANDROID_KHR 195 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) { 196 197 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true; 198 } 199 #endif // VK_USE_PLATFORM_ANDROID_KHR 200 #ifdef VK_USE_PLATFORM_MIR_KHR 201 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) { 202 203 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true; 204 } 205 #endif // VK_USE_PLATFORM_MIR_KHR 206 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 207 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) { 208 209 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true; 210 } 211 #endif // VK_USE_PLATFORM_WAYLAND_KHR 212 #ifdef VK_USE_PLATFORM_WIN32_KHR 213 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) { 214 215 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true; 216 } 217 #endif // VK_USE_PLATFORM_WIN32_KHR 218 #ifdef VK_USE_PLATFORM_XCB_KHR 219 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) { 220 221 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true; 222 } 223 #endif // VK_USE_PLATFORM_XCB_KHR 224 #ifdef VK_USE_PLATFORM_XLIB_KHR 225 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) { 226 227 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true; 228 } 229 #endif // VK_USE_PLATFORM_XLIB_KHR 230 } 231 } 232 233 #include "vk_dispatch_table_helper.h" 234 static void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) { 235 236 layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain"); 237 238 if (!globalLockInitialized) { 239 loader_platform_thread_create_mutex(&globalLock); 240 globalLockInitialized = 1; 241 } 242 } 243 244 static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) { 245 // Return a string corresponding to the value: 246 return string_VkSurfaceTransformFlagBitsKHR(value); 247 } 248 249 static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) { 250 // Return a string corresponding to the value: 251 return string_VkCompositeAlphaFlagBitsKHR(value); 252 } 253 254 static const char *presentModeStr(VkPresentModeKHR value) { 255 // Return a string corresponding to the value: 256 return string_VkPresentModeKHR(value); 257 } 258 259 static const char *sharingModeStr(VkSharingMode value) { 260 // Return a string corresponding to the value: 261 return string_VkSharingMode(value); 262 } 263 264 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 265 vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { 266 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 267 268 assert(chain_info->u.pLayerInfo); 269 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 270 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 271 if (fpCreateInstance == NULL) { 272 return VK_ERROR_INITIALIZATION_FAILED; 273 } 274 275 // Advance the link info for the next element on the chain 276 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 277 278 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 279 if (result != VK_SUCCESS) { 280 return result; 281 } 282 283 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); 284 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; 285 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr); 286 287 my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance, 288 pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); 289 290 // Call the following function after my_data is initialized: 291 createInstanceRegisterExtensions(pCreateInfo, *pInstance); 292 init_swapchain(my_data, pAllocator); 293 294 return result; 295 } 296 297 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 298 dispatch_key key = get_dispatch_key(instance); 299 layer_data *my_data = get_my_data_ptr(key, layer_data_map); 300 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 301 302 // Call down the call chain: 303 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator); 304 305 loader_platform_thread_lock_mutex(&globalLock); 306 307 // Do additional internal cleanup: 308 if (pInstance) { 309 // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the 310 // SwpInstance associated with this instance: 311 for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.end(); it++) { 312 313 // Free memory that was allocated for/by this SwpPhysicalDevice: 314 SwpPhysicalDevice *pPhysicalDevice = it->second; 315 if (pPhysicalDevice) { 316 if (pPhysicalDevice->pDevice) { 317 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, 318 "%s() called before all of its associated " 319 "VkDevices were destroyed.", 320 __FUNCTION__); 321 } 322 free(pPhysicalDevice->pSurfaceFormats); 323 free(pPhysicalDevice->pPresentModes); 324 } 325 326 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which 327 // are simply pointed to by the SwpInstance): 328 my_data->physicalDeviceMap.erase(it->second->physicalDevice); 329 } 330 for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) { 331 332 // Free memory that was allocated for/by this SwpPhysicalDevice: 333 SwpSurface *pSurface = it->second; 334 if (pSurface) { 335 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, 336 "%s() called before all of its associated " 337 "VkSurfaceKHRs were destroyed.", 338 __FUNCTION__); 339 } 340 } 341 my_data->instanceMap.erase(instance); 342 } 343 344 // Clean up logging callback, if any 345 while (my_data->logging_callback.size() > 0) { 346 VkDebugReportCallbackEXT callback = my_data->logging_callback.back(); 347 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator); 348 my_data->logging_callback.pop_back(); 349 } 350 layer_debug_report_destroy_instance(my_data->report_data); 351 352 delete my_data->instance_dispatch_table; 353 layer_data_map.erase(key); 354 if (layer_data_map.empty()) { 355 // Release mutex when destroying last instance 356 loader_platform_thread_unlock_mutex(&globalLock); 357 loader_platform_thread_delete_mutex(&globalLock); 358 globalLockInitialized = 0; 359 } else { 360 loader_platform_thread_unlock_mutex(&globalLock); 361 } 362 } 363 364 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL 365 vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, 366 VkQueueFamilyProperties *pQueueFamilyProperties) { 367 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 368 369 // Call down the call chain: 370 my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, 371 pQueueFamilyProperties); 372 373 // Record the result of this query: 374 loader_platform_thread_lock_mutex(&globalLock); 375 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 376 if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) { 377 pPhysicalDevice->gotQueueFamilyPropertyCount = true; 378 pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount; 379 } 380 loader_platform_thread_unlock_mutex(&globalLock); 381 } 382 383 #ifdef VK_USE_PLATFORM_ANDROID_KHR 384 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 385 vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, 386 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 387 VkResult result = VK_SUCCESS; 388 VkBool32 skipCall = VK_FALSE; 389 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 390 loader_platform_thread_lock_mutex(&globalLock); 391 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 392 393 // Validate that the platform extension was enabled: 394 if (pInstance && !pInstance->androidSurfaceExtensionEnabled) { 395 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 396 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 397 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); 398 } 399 400 if (!pCreateInfo) { 401 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 402 } else { 403 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) { 404 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 405 "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR"); 406 } 407 if (pCreateInfo->pNext != NULL) { 408 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 409 } 410 } 411 412 if (VK_FALSE == skipCall) { 413 // Call down the call chain: 414 loader_platform_thread_unlock_mutex(&globalLock); 415 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); 416 loader_platform_thread_lock_mutex(&globalLock); 417 418 // Obtain this pointer again after locking: 419 pInstance = &(my_data->instanceMap[instance]); 420 if ((result == VK_SUCCESS) && pInstance && pSurface) { 421 // Record the VkSurfaceKHR returned by the ICD: 422 my_data->surfaceMap[*pSurface].surface = *pSurface; 423 my_data->surfaceMap[*pSurface].pInstance = pInstance; 424 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); 425 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; 426 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; 427 // Point to the associated SwpInstance: 428 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; 429 } 430 loader_platform_thread_unlock_mutex(&globalLock); 431 return result; 432 } 433 loader_platform_thread_unlock_mutex(&globalLock); 434 return VK_ERROR_VALIDATION_FAILED_EXT; 435 } 436 #endif // VK_USE_PLATFORM_ANDROID_KHR 437 438 #ifdef VK_USE_PLATFORM_MIR_KHR 439 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 440 vkCreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, 441 VkSurfaceKHR *pSurface) { 442 VkResult result = VK_SUCCESS; 443 VkBool32 skipCall = VK_FALSE; 444 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 445 loader_platform_thread_lock_mutex(&globalLock); 446 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 447 448 // Validate that the platform extension was enabled: 449 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) { 450 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 451 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 452 VK_KHR_MIR_SURFACE_EXTENSION_NAME); 453 } 454 455 if (!pCreateInfo) { 456 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 457 } else { 458 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) { 459 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 460 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR"); 461 } 462 if (pCreateInfo->pNext != NULL) { 463 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 464 } 465 } 466 467 if (VK_FALSE == skipCall) { 468 // Call down the call chain: 469 loader_platform_thread_unlock_mutex(&globalLock); 470 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); 471 loader_platform_thread_lock_mutex(&globalLock); 472 473 // Obtain this pointer again after locking: 474 pInstance = &(my_data->instanceMap[instance]); 475 if ((result == VK_SUCCESS) && pInstance && pSurface) { 476 // Record the VkSurfaceKHR returned by the ICD: 477 my_data->surfaceMap[*pSurface].surface = *pSurface; 478 my_data->surfaceMap[*pSurface].pInstance = pInstance; 479 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); 480 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; 481 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; 482 // Point to the associated SwpInstance: 483 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; 484 } 485 loader_platform_thread_unlock_mutex(&globalLock); 486 return result; 487 } 488 loader_platform_thread_unlock_mutex(&globalLock); 489 return VK_ERROR_VALIDATION_FAILED_EXT; 490 } 491 492 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice, 493 uint32_t queueFamilyIndex, 494 MirConnection *connection) { 495 VkBool32 result = VK_FALSE; 496 VkBool32 skipCall = VK_FALSE; 497 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 498 loader_platform_thread_lock_mutex(&globalLock); 499 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 500 501 // Validate that the platform extension was enabled: 502 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) { 503 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 504 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 505 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 506 VK_KHR_MIR_SURFACE_EXTENSION_NAME); 507 } 508 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { 509 skipCall |= 510 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 511 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies); 512 } 513 loader_platform_thread_unlock_mutex(&globalLock); 514 515 if (VK_FALSE == skipCall) { 516 // Call down the call chain: 517 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex, 518 connection); 519 } 520 return result; 521 } 522 #endif // VK_USE_PLATFORM_MIR_KHR 523 524 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 525 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 526 vkCreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 527 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 528 VkResult result = VK_SUCCESS; 529 VkBool32 skipCall = VK_FALSE; 530 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 531 loader_platform_thread_lock_mutex(&globalLock); 532 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 533 534 // Validate that the platform extension was enabled: 535 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) { 536 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 537 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 538 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); 539 } 540 541 if (!pCreateInfo) { 542 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 543 } else { 544 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) { 545 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 546 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR"); 547 } 548 if (pCreateInfo->pNext != NULL) { 549 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 550 } 551 } 552 553 if (VK_FALSE == skipCall) { 554 // Call down the call chain: 555 loader_platform_thread_unlock_mutex(&globalLock); 556 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); 557 loader_platform_thread_lock_mutex(&globalLock); 558 559 // Obtain this pointer again after locking: 560 pInstance = &(my_data->instanceMap[instance]); 561 if ((result == VK_SUCCESS) && pInstance && pSurface) { 562 // Record the VkSurfaceKHR returned by the ICD: 563 my_data->surfaceMap[*pSurface].surface = *pSurface; 564 my_data->surfaceMap[*pSurface].pInstance = pInstance; 565 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); 566 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; 567 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; 568 // Point to the associated SwpInstance: 569 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; 570 } 571 loader_platform_thread_unlock_mutex(&globalLock); 572 return result; 573 } 574 loader_platform_thread_unlock_mutex(&globalLock); 575 return VK_ERROR_VALIDATION_FAILED_EXT; 576 } 577 578 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice, 579 uint32_t queueFamilyIndex, 580 struct wl_display *display) { 581 VkBool32 result = VK_FALSE; 582 VkBool32 skipCall = VK_FALSE; 583 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 584 loader_platform_thread_lock_mutex(&globalLock); 585 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 586 587 // Validate that the platform extension was enabled: 588 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) { 589 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 590 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 591 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 592 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); 593 } 594 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { 595 skipCall |= 596 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 597 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies); 598 } 599 loader_platform_thread_unlock_mutex(&globalLock); 600 601 if (VK_FALSE == skipCall) { 602 // Call down the call chain: 603 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, 604 display); 605 } 606 return result; 607 } 608 #endif // VK_USE_PLATFORM_WAYLAND_KHR 609 610 #ifdef VK_USE_PLATFORM_WIN32_KHR 611 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 612 vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 613 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 614 VkResult result = VK_SUCCESS; 615 VkBool32 skipCall = VK_FALSE; 616 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 617 loader_platform_thread_lock_mutex(&globalLock); 618 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 619 620 // Validate that the platform extension was enabled: 621 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) { 622 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 623 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 624 VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 625 } 626 627 if (!pCreateInfo) { 628 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 629 } else { 630 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) { 631 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 632 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR"); 633 } 634 if (pCreateInfo->pNext != NULL) { 635 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 636 } 637 } 638 639 if (VK_FALSE == skipCall) { 640 // Call down the call chain: 641 loader_platform_thread_unlock_mutex(&globalLock); 642 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); 643 loader_platform_thread_lock_mutex(&globalLock); 644 645 // Obtain this pointer again after locking: 646 pInstance = &(my_data->instanceMap[instance]); 647 if ((result == VK_SUCCESS) && pInstance && pSurface) { 648 // Record the VkSurfaceKHR returned by the ICD: 649 my_data->surfaceMap[*pSurface].surface = *pSurface; 650 my_data->surfaceMap[*pSurface].pInstance = pInstance; 651 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); 652 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; 653 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; 654 // Point to the associated SwpInstance: 655 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; 656 } 657 loader_platform_thread_unlock_mutex(&globalLock); 658 return result; 659 } 660 loader_platform_thread_unlock_mutex(&globalLock); 661 return VK_ERROR_VALIDATION_FAILED_EXT; 662 } 663 664 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL 665 vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) { 666 VkBool32 result = VK_FALSE; 667 VkBool32 skipCall = VK_FALSE; 668 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 669 loader_platform_thread_lock_mutex(&globalLock); 670 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 671 672 // Validate that the platform extension was enabled: 673 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) { 674 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 675 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 676 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 677 VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 678 } 679 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { 680 skipCall |= 681 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 682 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies); 683 } 684 loader_platform_thread_unlock_mutex(&globalLock); 685 686 if (VK_FALSE == skipCall) { 687 // Call down the call chain: 688 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex); 689 } 690 return result; 691 } 692 #endif // VK_USE_PLATFORM_WIN32_KHR 693 694 #ifdef VK_USE_PLATFORM_XCB_KHR 695 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 696 vkCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, 697 VkSurfaceKHR *pSurface) { 698 VkResult result = VK_SUCCESS; 699 VkBool32 skipCall = VK_FALSE; 700 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 701 loader_platform_thread_lock_mutex(&globalLock); 702 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 703 704 // Validate that the platform extension was enabled: 705 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) { 706 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 707 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 708 VK_KHR_XCB_SURFACE_EXTENSION_NAME); 709 } 710 711 if (!pCreateInfo) { 712 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 713 } else { 714 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) { 715 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 716 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR"); 717 } 718 if (pCreateInfo->pNext != NULL) { 719 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 720 } 721 } 722 723 if (VK_FALSE == skipCall) { 724 // Call down the call chain: 725 loader_platform_thread_unlock_mutex(&globalLock); 726 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); 727 loader_platform_thread_lock_mutex(&globalLock); 728 729 // Obtain this pointer again after locking: 730 pInstance = &(my_data->instanceMap[instance]); 731 if ((result == VK_SUCCESS) && pInstance && pSurface) { 732 // Record the VkSurfaceKHR returned by the ICD: 733 my_data->surfaceMap[*pSurface].surface = *pSurface; 734 my_data->surfaceMap[*pSurface].pInstance = pInstance; 735 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); 736 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; 737 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; 738 // Point to the associated SwpInstance: 739 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; 740 } 741 loader_platform_thread_unlock_mutex(&globalLock); 742 return result; 743 } 744 loader_platform_thread_unlock_mutex(&globalLock); 745 return VK_ERROR_VALIDATION_FAILED_EXT; 746 } 747 748 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL 749 vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 750 xcb_connection_t *connection, xcb_visualid_t visual_id) { 751 VkBool32 result = VK_FALSE; 752 VkBool32 skipCall = VK_FALSE; 753 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 754 loader_platform_thread_lock_mutex(&globalLock); 755 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 756 757 // Validate that the platform extension was enabled: 758 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) { 759 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 760 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 761 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 762 VK_KHR_XCB_SURFACE_EXTENSION_NAME); 763 } 764 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { 765 skipCall |= 766 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 767 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies); 768 } 769 loader_platform_thread_unlock_mutex(&globalLock); 770 771 if (VK_FALSE == skipCall) { 772 // Call down the call chain: 773 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex, 774 connection, visual_id); 775 } 776 return result; 777 } 778 #endif // VK_USE_PLATFORM_XCB_KHR 779 780 #ifdef VK_USE_PLATFORM_XLIB_KHR 781 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 782 vkCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, 783 VkSurfaceKHR *pSurface) { 784 VkResult result = VK_SUCCESS; 785 VkBool32 skipCall = VK_FALSE; 786 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 787 loader_platform_thread_lock_mutex(&globalLock); 788 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 789 790 // Validate that the platform extension was enabled: 791 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) { 792 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 793 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 794 VK_KHR_XLIB_SURFACE_EXTENSION_NAME); 795 } 796 797 if (!pCreateInfo) { 798 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 799 } else { 800 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) { 801 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 802 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR"); 803 } 804 if (pCreateInfo->pNext != NULL) { 805 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 806 } 807 } 808 809 if (VK_FALSE == skipCall) { 810 // Call down the call chain: 811 loader_platform_thread_unlock_mutex(&globalLock); 812 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); 813 loader_platform_thread_lock_mutex(&globalLock); 814 815 // Obtain this pointer again after locking: 816 pInstance = &(my_data->instanceMap[instance]); 817 if ((result == VK_SUCCESS) && pInstance && pSurface) { 818 // Record the VkSurfaceKHR returned by the ICD: 819 my_data->surfaceMap[*pSurface].surface = *pSurface; 820 my_data->surfaceMap[*pSurface].pInstance = pInstance; 821 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); 822 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; 823 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; 824 // Point to the associated SwpInstance: 825 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; 826 } 827 loader_platform_thread_unlock_mutex(&globalLock); 828 return result; 829 } 830 loader_platform_thread_unlock_mutex(&globalLock); 831 return VK_ERROR_VALIDATION_FAILED_EXT; 832 } 833 834 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice, 835 uint32_t queueFamilyIndex, 836 Display *dpy, VisualID visualID) { 837 VkBool32 result = VK_FALSE; 838 VkBool32 skipCall = VK_FALSE; 839 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 840 loader_platform_thread_lock_mutex(&globalLock); 841 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 842 843 // Validate that the platform extension was enabled: 844 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) { 845 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 846 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 847 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 848 VK_KHR_XLIB_SURFACE_EXTENSION_NAME); 849 } 850 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { 851 skipCall |= 852 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 853 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies); 854 } 855 loader_platform_thread_unlock_mutex(&globalLock); 856 857 if (VK_FALSE == skipCall) { 858 // Call down the call chain: 859 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, 860 dpy, visualID); 861 } 862 return result; 863 } 864 #endif // VK_USE_PLATFORM_XLIB_KHR 865 866 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL 867 vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) { 868 VkBool32 skipCall = VK_FALSE; 869 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 870 loader_platform_thread_lock_mutex(&globalLock); 871 SwpSurface *pSurface = &my_data->surfaceMap[surface]; 872 873 // Regardless of skipCall value, do some internal cleanup: 874 if (pSurface) { 875 // Delete the SwpSurface associated with this surface: 876 if (pSurface->pInstance) { 877 pSurface->pInstance->surfaces.erase(surface); 878 } 879 if (!pSurface->swapchains.empty()) { 880 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, 881 "%s() called before all of its associated " 882 "VkSwapchainKHRs were destroyed.", 883 __FUNCTION__); 884 // Empty and then delete all SwpSwapchain's 885 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) { 886 // Delete all SwpImage's 887 it->second->images.clear(); 888 // In case the swapchain's device hasn't been destroyed yet 889 // (which isn't likely, but is possible), delete its 890 // association with this swapchain (i.e. so we can't point to 891 // this swpchain from that device, later on): 892 if (it->second->pDevice) { 893 it->second->pDevice->swapchains.clear(); 894 } 895 } 896 pSurface->swapchains.clear(); 897 } 898 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) { 899 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR, 900 "%s() called with incompatible pAllocator from when " 901 "the object was created.", 902 __FUNCTION__); 903 } 904 my_data->surfaceMap.erase(surface); 905 } 906 loader_platform_thread_unlock_mutex(&globalLock); 907 908 if (VK_FALSE == skipCall) { 909 // Call down the call chain: 910 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator); 911 } 912 } 913 914 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 915 vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) { 916 VkResult result = VK_SUCCESS; 917 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 918 919 // Call down the call chain: 920 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); 921 922 loader_platform_thread_lock_mutex(&globalLock); 923 SwpInstance *pInstance = &(my_data->instanceMap[instance]); 924 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) { 925 // Record the VkPhysicalDevices returned by the ICD: 926 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) { 927 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i]; 928 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance; 929 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL; 930 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false; 931 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false; 932 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0; 933 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL; 934 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0; 935 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL; 936 // Point to the associated SwpInstance: 937 if (pInstance) { 938 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]]; 939 } 940 } 941 } 942 loader_platform_thread_unlock_mutex(&globalLock); 943 return result; 944 } 945 946 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, 947 const VkDeviceCreateInfo *pCreateInfo, 948 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 949 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 950 951 assert(chain_info->u.pLayerInfo); 952 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 953 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 954 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); 955 if (fpCreateDevice == NULL) { 956 return VK_ERROR_INITIALIZATION_FAILED; 957 } 958 959 // Advance the link info for the next element on the chain 960 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 961 962 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); 963 if (result != VK_SUCCESS) { 964 return result; 965 } 966 967 loader_platform_thread_lock_mutex(&globalLock); 968 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 969 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map); 970 971 // Setup device dispatch table 972 my_device_data->device_dispatch_table = new VkLayerDispatchTable; 973 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr); 974 975 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice); 976 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice); 977 loader_platform_thread_unlock_mutex(&globalLock); 978 979 return result; 980 } 981 982 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 983 dispatch_key key = get_dispatch_key(device); 984 layer_data *my_data = get_my_data_ptr(key, layer_data_map); 985 986 // Call down the call chain: 987 my_data->device_dispatch_table->DestroyDevice(device, pAllocator); 988 989 // Do some internal cleanup: 990 loader_platform_thread_lock_mutex(&globalLock); 991 SwpDevice *pDevice = &my_data->deviceMap[device]; 992 if (pDevice) { 993 // Delete the SwpDevice associated with this device: 994 if (pDevice->pPhysicalDevice) { 995 pDevice->pPhysicalDevice->pDevice = NULL; 996 } 997 if (!pDevice->swapchains.empty()) { 998 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, 999 "%s() called before all of its associated " 1000 "VkSwapchainKHRs were destroyed.", 1001 __FUNCTION__); 1002 // Empty and then delete all SwpSwapchain's 1003 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) { 1004 // Delete all SwpImage's 1005 it->second->images.clear(); 1006 // In case the swapchain's surface hasn't been destroyed yet 1007 // (which is likely) delete its association with this swapchain 1008 // (i.e. so we can't point to this swpchain from that surface, 1009 // later on): 1010 if (it->second->pSurface) { 1011 it->second->pSurface->swapchains.clear(); 1012 } 1013 } 1014 pDevice->swapchains.clear(); 1015 } 1016 my_data->deviceMap.erase(device); 1017 } 1018 delete my_data->device_dispatch_table; 1019 layer_data_map.erase(key); 1020 loader_platform_thread_unlock_mutex(&globalLock); 1021 } 1022 1023 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, 1024 uint32_t queueFamilyIndex, VkSurfaceKHR surface, 1025 VkBool32 *pSupported) { 1026 VkResult result = VK_SUCCESS; 1027 VkBool32 skipCall = VK_FALSE; 1028 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 1029 loader_platform_thread_lock_mutex(&globalLock); 1030 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1031 1032 // Validate that the surface extension was enabled: 1033 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) { 1034 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 1035 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1036 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 1037 VK_KHR_SURFACE_EXTENSION_NAME); 1038 } 1039 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) { 1040 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", 1041 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the " 1042 "vkGetPhysicalDeviceQueueFamilyProperties " 1043 "function.", 1044 __FUNCTION__); 1045 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { 1046 skipCall |= 1047 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 1048 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies); 1049 } 1050 if (!pSupported) { 1051 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported"); 1052 } 1053 1054 if (VK_FALSE == skipCall) { 1055 // Call down the call chain: 1056 loader_platform_thread_unlock_mutex(&globalLock); 1057 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, 1058 pSupported); 1059 loader_platform_thread_lock_mutex(&globalLock); 1060 1061 // Obtain this pointer again after locking: 1062 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1063 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) { 1064 // Record the result of this query: 1065 SwpInstance *pInstance = pPhysicalDevice->pInstance; 1066 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL; 1067 if (pSurface) { 1068 pPhysicalDevice->supportedSurfaces[surface] = pSurface; 1069 if (!pSurface->numQueueFamilyIndexSupport) { 1070 if (pPhysicalDevice->gotQueueFamilyPropertyCount) { 1071 pSurface->pQueueFamilyIndexSupport = 1072 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32)); 1073 if (pSurface->pQueueFamilyIndexSupport != NULL) { 1074 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies; 1075 } 1076 } 1077 } 1078 if (pSurface->numQueueFamilyIndexSupport) { 1079 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported; 1080 } 1081 } 1082 } 1083 loader_platform_thread_unlock_mutex(&globalLock); 1084 return result; 1085 } 1086 loader_platform_thread_unlock_mutex(&globalLock); 1087 return VK_ERROR_VALIDATION_FAILED_EXT; 1088 } 1089 1090 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1091 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 1092 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) { 1093 VkResult result = VK_SUCCESS; 1094 VkBool32 skipCall = VK_FALSE; 1095 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 1096 loader_platform_thread_lock_mutex(&globalLock); 1097 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1098 1099 // Validate that the surface extension was enabled: 1100 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) { 1101 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 1102 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1103 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 1104 VK_KHR_SURFACE_EXTENSION_NAME); 1105 } 1106 if (!pSurfaceCapabilities) { 1107 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities"); 1108 } 1109 1110 if (VK_FALSE == skipCall) { 1111 // Call down the call chain: 1112 loader_platform_thread_unlock_mutex(&globalLock); 1113 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, 1114 pSurfaceCapabilities); 1115 loader_platform_thread_lock_mutex(&globalLock); 1116 1117 // Obtain this pointer again after locking: 1118 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1119 if ((result == VK_SUCCESS) && pPhysicalDevice) { 1120 // Record the result of this query: 1121 pPhysicalDevice->gotSurfaceCapabilities = true; 1122 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA 1123 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities; 1124 } 1125 loader_platform_thread_unlock_mutex(&globalLock); 1126 return result; 1127 } 1128 loader_platform_thread_unlock_mutex(&globalLock); 1129 return VK_ERROR_VALIDATION_FAILED_EXT; 1130 } 1131 1132 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1133 vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, 1134 VkSurfaceFormatKHR *pSurfaceFormats) { 1135 VkResult result = VK_SUCCESS; 1136 VkBool32 skipCall = VK_FALSE; 1137 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 1138 loader_platform_thread_lock_mutex(&globalLock); 1139 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1140 1141 // Validate that the surface extension was enabled: 1142 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) { 1143 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 1144 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1145 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 1146 VK_KHR_SURFACE_EXTENSION_NAME); 1147 } 1148 if (!pSurfaceFormatCount) { 1149 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount"); 1150 } 1151 1152 if (VK_FALSE == skipCall) { 1153 // Call down the call chain: 1154 loader_platform_thread_unlock_mutex(&globalLock); 1155 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, 1156 pSurfaceFormats); 1157 loader_platform_thread_lock_mutex(&globalLock); 1158 1159 // Obtain this pointer again after locking: 1160 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1161 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) { 1162 // Record the result of this preliminary query: 1163 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount; 1164 } else if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats && pSurfaceFormatCount) { 1165 // Compare the preliminary value of *pSurfaceFormatCount with the 1166 // value this time: 1167 if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) { 1168 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount", 1169 "pSurfaceFormats", *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount); 1170 } else if (*pSurfaceFormatCount > 0) { 1171 // Record the result of this query: 1172 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount; 1173 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR)); 1174 if (pPhysicalDevice->pSurfaceFormats) { 1175 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 1176 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i]; 1177 } 1178 } else { 1179 pPhysicalDevice->surfaceFormatCount = 0; 1180 } 1181 } 1182 } 1183 loader_platform_thread_unlock_mutex(&globalLock); 1184 return result; 1185 } 1186 loader_platform_thread_unlock_mutex(&globalLock); 1187 return VK_ERROR_VALIDATION_FAILED_EXT; 1188 } 1189 1190 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1191 vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount, 1192 VkPresentModeKHR *pPresentModes) { 1193 VkResult result = VK_SUCCESS; 1194 VkBool32 skipCall = VK_FALSE; 1195 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); 1196 loader_platform_thread_lock_mutex(&globalLock); 1197 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1198 1199 // Validate that the surface extension was enabled: 1200 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) { 1201 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance", 1202 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1203 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, 1204 VK_KHR_SURFACE_EXTENSION_NAME); 1205 } 1206 if (!pPresentModeCount) { 1207 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount"); 1208 } 1209 1210 if (VK_FALSE == skipCall) { 1211 // Call down the call chain: 1212 loader_platform_thread_unlock_mutex(&globalLock); 1213 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, 1214 pPresentModeCount, pPresentModes); 1215 loader_platform_thread_lock_mutex(&globalLock); 1216 1217 // Obtain this pointer again after locking: 1218 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice]; 1219 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) { 1220 // Record the result of this preliminary query: 1221 pPhysicalDevice->presentModeCount = *pPresentModeCount; 1222 } else if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes && pPresentModeCount) { 1223 // Compare the preliminary value of *pPresentModeCount with the 1224 // value this time: 1225 if (*pPresentModeCount > pPhysicalDevice->presentModeCount) { 1226 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount", 1227 "pPresentModes", *pPresentModeCount, pPhysicalDevice->presentModeCount); 1228 } else if (*pPresentModeCount > 0) { 1229 // Record the result of this query: 1230 pPhysicalDevice->presentModeCount = *pPresentModeCount; 1231 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR)); 1232 if (pPhysicalDevice->pPresentModes) { 1233 for (uint32_t i = 0; i < *pPresentModeCount; i++) { 1234 pPhysicalDevice->pPresentModes[i] = pPresentModes[i]; 1235 } 1236 } else { 1237 pPhysicalDevice->presentModeCount = 0; 1238 } 1239 } 1240 } 1241 loader_platform_thread_unlock_mutex(&globalLock); 1242 return result; 1243 } 1244 loader_platform_thread_unlock_mutex(&globalLock); 1245 return VK_ERROR_VALIDATION_FAILED_EXT; 1246 } 1247 1248 // This function does the up-front validation work for vkCreateSwapchainKHR(), 1249 // and returns VK_TRUE if a logging callback indicates that the call down the 1250 // chain should be skipped: 1251 static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 1252 VkSwapchainKHR *pSwapchain) { 1253 // TODO: Validate cases of re-creating a swapchain (the current code 1254 // assumes a new swapchain is being created). 1255 VkBool32 skipCall = VK_FALSE; 1256 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1257 char fn[] = "vkCreateSwapchainKHR"; 1258 SwpDevice *pDevice = &my_data->deviceMap[device]; 1259 1260 // Validate that the swapchain extension was enabled: 1261 if (pDevice && !pDevice->swapchainExtensionEnabled) { 1262 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1263 "%s() called even though the %s extension was not enabled for this VkDevice.", fn, 1264 VK_KHR_SWAPCHAIN_EXTENSION_NAME); 1265 } 1266 if (!pCreateInfo) { 1267 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 1268 } else { 1269 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) { 1270 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo", 1271 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR"); 1272 } 1273 if (pCreateInfo->pNext != NULL) { 1274 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo"); 1275 } 1276 } 1277 if (!pSwapchain) { 1278 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain"); 1279 } 1280 1281 // Keep around a useful pointer to pPhysicalDevice: 1282 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice; 1283 1284 // Validate pCreateInfo values with result of 1285 // vkGetPhysicalDeviceQueueFamilyProperties 1286 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) { 1287 for (auto i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) { 1288 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) { 1289 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, 1290 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i], 1291 pPhysicalDevice->numOfQueueFamilies); 1292 } 1293 } 1294 } 1295 1296 // Validate pCreateInfo values with the results of 1297 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): 1298 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) { 1299 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, 1300 "%s() called before calling " 1301 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().", 1302 fn); 1303 } else if (pCreateInfo) { 1304 // Validate pCreateInfo->surface to make sure that 1305 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported 1306 // surface: 1307 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL); 1308 if (!pSurface) { 1309 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, 1310 "%s() called with pCreateInfo->surface that " 1311 "was not returned by " 1312 "vkGetPhysicalDeviceSurfaceSupportKHR() " 1313 "for the device.", 1314 fn); 1315 } 1316 1317 // Validate pCreateInfo->minImageCount against 1318 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount: 1319 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities; 1320 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) || 1321 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) { 1322 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1323 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount " 1324 "= %d, which is outside the bounds returned " 1325 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. " 1326 "minImageCount = %d, maxImageCount = %d).", 1327 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount); 1328 } 1329 // Validate pCreateInfo->imageExtent against 1330 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: 1331 if ((pCapabilities->currentExtent.width == -1) && 1332 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) || 1333 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) || 1334 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) || 1335 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) { 1336 skipCall |= LOG_ERROR( 1337 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS, 1338 "%s() called with pCreateInfo->imageExtent = " 1339 "(%d,%d), which is outside the bounds " 1340 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): " 1341 "currentExtent = (%d,%d), minImageExtent = " 1342 "(%d,%d), maxImageExtent = (%d,%d).", 1343 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width, 1344 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height, 1345 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height); 1346 } 1347 if ((pCapabilities->currentExtent.width != -1) && 1348 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) || 1349 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) { 1350 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1351 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = " 1352 "(%d,%d), which is not equal to the " 1353 "currentExtent = (%d,%d) returned by " 1354 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().", 1355 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 1356 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height); 1357 } 1358 // Validate pCreateInfo->preTransform has one bit set (1st two 1359 // lines of if-statement), which bit is also set in 1360 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement): 1361 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) || 1362 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) { 1363 // This is an error situation; one for which we'd like to give 1364 // the developer a helpful, multi-line error message. Build it 1365 // up a little at a time, and then log it: 1366 std::string errorString = ""; 1367 char str[1024]; 1368 // Here's the first part of the message: 1369 sprintf(str, "%s() called with a non-supported " 1370 "pCreateInfo->preTransform (i.e. %s). " 1371 "Supported values are:\n", 1372 fn, surfaceTransformStr(pCreateInfo->preTransform)); 1373 errorString += str; 1374 for (int i = 0; i < 32; i++) { 1375 // Build up the rest of the message: 1376 if ((1 << i) & pCapabilities->supportedTransforms) { 1377 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i)); 1378 sprintf(str, " %s\n", newStr); 1379 errorString += str; 1380 } 1381 } 1382 // Log the message that we've built up: 1383 skipCall |= debug_report_log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 1384 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, __LINE__, 1385 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME, errorString.c_str()); 1386 } 1387 // Validate pCreateInfo->compositeAlpha has one bit set (1st two 1388 // lines of if-statement), which bit is also set in 1389 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement): 1390 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) || 1391 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) { 1392 // This is an error situation; one for which we'd like to give 1393 // the developer a helpful, multi-line error message. Build it 1394 // up a little at a time, and then log it: 1395 std::string errorString = ""; 1396 char str[1024]; 1397 // Here's the first part of the message: 1398 sprintf(str, "%s() called with a non-supported " 1399 "pCreateInfo->compositeAlpha (i.e. %s). " 1400 "Supported values are:\n", 1401 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha)); 1402 errorString += str; 1403 for (int i = 0; i < 32; i++) { 1404 // Build up the rest of the message: 1405 if ((1 << i) & pCapabilities->supportedCompositeAlpha) { 1406 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i)); 1407 sprintf(str, " %s\n", newStr); 1408 errorString += str; 1409 } 1410 } 1411 // Log the message that we've built up: 1412 skipCall |= debug_report_log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 1413 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, 0, 1414 SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, LAYER_NAME, errorString.c_str()); 1415 } 1416 // Validate pCreateInfo->imageArraySize against 1417 // VkSurfaceCapabilitiesKHR::maxImageArraySize: 1418 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) { 1419 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1420 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, "%s() called with a non-supported " 1421 "pCreateInfo->imageArraySize (i.e. %d). " 1422 "Minimum value is 1, maximum value is %d.", 1423 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers); 1424 } 1425 // Validate pCreateInfo->imageUsage against 1426 // VkSurfaceCapabilitiesKHR::supportedUsageFlags: 1427 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) { 1428 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1429 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported " 1430 "pCreateInfo->imageUsage (i.e. 0x%08x)." 1431 " Supported flag bits are 0x%08x.", 1432 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags); 1433 } 1434 } 1435 1436 // Validate pCreateInfo values with the results of 1437 // vkGetPhysicalDeviceSurfaceFormatsKHR(): 1438 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) { 1439 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, 1440 "%s() called before calling " 1441 "vkGetPhysicalDeviceSurfaceFormatsKHR().", 1442 fn); 1443 } else if (pCreateInfo) { 1444 // Validate pCreateInfo->imageFormat against 1445 // VkSurfaceFormatKHR::format: 1446 bool foundFormat = false; 1447 bool foundColorSpace = false; 1448 bool foundMatch = false; 1449 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) { 1450 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) { 1451 // Validate pCreateInfo->imageColorSpace against 1452 // VkSurfaceFormatKHR::colorSpace: 1453 foundFormat = true; 1454 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) { 1455 foundMatch = true; 1456 break; 1457 } 1458 } else { 1459 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) { 1460 foundColorSpace = true; 1461 } 1462 } 1463 } 1464 if (!foundMatch) { 1465 if (!foundFormat) { 1466 if (!foundColorSpace) { 1467 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1468 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a " 1469 "supported pCreateInfo->imageFormat " 1470 "(i.e. %d) nor a supported " 1471 "pCreateInfo->imageColorSpace " 1472 "(i.e. %d).", 1473 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace); 1474 } else { 1475 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1476 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported " 1477 "pCreateInfo->imageFormat (i.e. %d).", 1478 fn, pCreateInfo->imageFormat); 1479 } 1480 } else if (!foundColorSpace) { 1481 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1482 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported " 1483 "pCreateInfo->imageColorSpace (i.e. %d).", 1484 fn, pCreateInfo->imageColorSpace); 1485 } 1486 } 1487 } 1488 1489 // Validate pCreateInfo values with the results of 1490 // vkGetPhysicalDeviceSurfacePresentModesKHR(): 1491 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) { 1492 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) { 1493 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, 1494 "%s() called before calling " 1495 "vkGetPhysicalDeviceSurfacePresentModesKHR().", 1496 fn); 1497 } 1498 } else if (pCreateInfo) { 1499 // Validate pCreateInfo->presentMode against 1500 // vkGetPhysicalDeviceSurfacePresentModesKHR(): 1501 bool foundMatch = false; 1502 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) { 1503 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) { 1504 foundMatch = true; 1505 break; 1506 } 1507 } 1508 if (!foundMatch) { 1509 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1510 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported " 1511 "pCreateInfo->presentMode (i.e. %s).", 1512 fn, presentModeStr(pCreateInfo->presentMode)); 1513 } 1514 } 1515 1516 // Validate pCreateInfo->imageSharingMode and related values: 1517 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) { 1518 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) { 1519 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1520 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported " 1521 "pCreateInfo->sharingMode of (i.e. %s)," 1522 "but with a bad value(s) for " 1523 "pCreateInfo->queueFamilyIndexCount or " 1524 "pCreateInfo->pQueueFamilyIndices).", 1525 fn, sharingModeStr(pCreateInfo->imageSharingMode)); 1526 } 1527 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) { 1528 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE, 1529 "%s() called with a non-supported " 1530 "pCreateInfo->imageSharingMode (i.e. %s).", 1531 fn, sharingModeStr(pCreateInfo->imageSharingMode)); 1532 } 1533 1534 // Validate pCreateInfo->clipped: 1535 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) { 1536 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL, 1537 "%s() called with a VkBool32 value that is " 1538 "neither VK_TRUE nor VK_FALSE, but has the " 1539 "numeric value of %d.", 1540 fn, pCreateInfo->clipped); 1541 } 1542 1543 // Validate pCreateInfo->oldSwapchain: 1544 if (pCreateInfo && pCreateInfo->oldSwapchain) { 1545 SwpSwapchain *pOldSwapchain = &my_data->swapchainMap[pCreateInfo->oldSwapchain]; 1546 if (pOldSwapchain) { 1547 if (device != pOldSwapchain->pDevice->device) { 1548 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1549 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice " 1550 "than the VkSwapchainKHR was created with.", 1551 __FUNCTION__); 1552 } 1553 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) { 1554 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", 1555 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain " 1556 "that has a different VkSurfaceKHR than " 1557 "pCreateInfo->surface.", 1558 fn); 1559 } 1560 } else { 1561 // TBD: Leave this in (not sure object_track will check this)? 1562 skipCall |= 1563 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR"); 1564 } 1565 } 1566 1567 return skipCall; 1568 } 1569 1570 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 1571 const VkAllocationCallbacks *pAllocator, 1572 VkSwapchainKHR *pSwapchain) { 1573 VkResult result = VK_SUCCESS; 1574 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1575 loader_platform_thread_lock_mutex(&globalLock); 1576 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain); 1577 1578 if (VK_FALSE == skipCall) { 1579 // Call down the call chain: 1580 loader_platform_thread_unlock_mutex(&globalLock); 1581 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 1582 loader_platform_thread_lock_mutex(&globalLock); 1583 1584 if (result == VK_SUCCESS) { 1585 // Remember the swapchain's handle, and link it to the device: 1586 SwpDevice *pDevice = &my_data->deviceMap[device]; 1587 1588 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain; 1589 if (pDevice) { 1590 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain]; 1591 } 1592 my_data->swapchainMap[*pSwapchain].pDevice = pDevice; 1593 my_data->swapchainMap[*pSwapchain].imageCount = 0; 1594 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL); 1595 // Store a pointer to the surface 1596 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice; 1597 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL; 1598 layer_data *my_instance_data = 1599 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL); 1600 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL); 1601 my_data->swapchainMap[*pSwapchain].pSurface = pSurface; 1602 if (pSurface) { 1603 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain]; 1604 } 1605 } 1606 loader_platform_thread_unlock_mutex(&globalLock); 1607 return result; 1608 } 1609 loader_platform_thread_unlock_mutex(&globalLock); 1610 return VK_ERROR_VALIDATION_FAILED_EXT; 1611 } 1612 1613 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL 1614 vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 1615 // TODOs: 1616 // 1617 // - Implement a check for validity language that reads: All uses of 1618 // presentable images acquired from pname:swapchain and owned by the 1619 // application must: have completed execution 1620 VkBool32 skipCall = VK_FALSE; 1621 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1622 loader_platform_thread_lock_mutex(&globalLock); 1623 SwpDevice *pDevice = &my_data->deviceMap[device]; 1624 1625 // Validate that the swapchain extension was enabled: 1626 if (pDevice && !pDevice->swapchainExtensionEnabled) { 1627 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1628 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__, 1629 VK_KHR_SWAPCHAIN_EXTENSION_NAME); 1630 } 1631 1632 // Regardless of skipCall value, do some internal cleanup: 1633 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain]; 1634 if (pSwapchain) { 1635 // Delete the SwpSwapchain associated with this swapchain: 1636 if (pSwapchain->pDevice) { 1637 pSwapchain->pDevice->swapchains.erase(swapchain); 1638 if (device != pSwapchain->pDevice->device) { 1639 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, 1640 "%s() called with a different VkDevice than the " 1641 "VkSwapchainKHR was created with.", 1642 __FUNCTION__); 1643 } 1644 } 1645 if (pSwapchain->pSurface) { 1646 pSwapchain->pSurface->swapchains.erase(swapchain); 1647 } 1648 if (pSwapchain->imageCount) { 1649 pSwapchain->images.clear(); 1650 } 1651 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) { 1652 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR, 1653 "%s() called with incompatible pAllocator from when " 1654 "the object was created.", 1655 __FUNCTION__); 1656 } 1657 my_data->swapchainMap.erase(swapchain); 1658 } 1659 loader_platform_thread_unlock_mutex(&globalLock); 1660 1661 if (VK_FALSE == skipCall) { 1662 // Call down the call chain: 1663 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator); 1664 } 1665 } 1666 1667 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1668 vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) { 1669 VkResult result = VK_SUCCESS; 1670 VkBool32 skipCall = VK_FALSE; 1671 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1672 loader_platform_thread_lock_mutex(&globalLock); 1673 SwpDevice *pDevice = &my_data->deviceMap[device]; 1674 1675 // Validate that the swapchain extension was enabled: 1676 if (pDevice && !pDevice->swapchainExtensionEnabled) { 1677 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1678 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__, 1679 VK_KHR_SWAPCHAIN_EXTENSION_NAME); 1680 } 1681 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain]; 1682 if (!pSwapchainImageCount) { 1683 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount"); 1684 } 1685 1686 if (VK_FALSE == skipCall) { 1687 // Call down the call chain: 1688 loader_platform_thread_unlock_mutex(&globalLock); 1689 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages); 1690 loader_platform_thread_lock_mutex(&globalLock); 1691 1692 // Obtain this pointer again after locking: 1693 pSwapchain = &my_data->swapchainMap[swapchain]; 1694 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) { 1695 // Record the result of this preliminary query: 1696 pSwapchain->imageCount = *pSwapchainImageCount; 1697 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages && pSwapchainImageCount) { 1698 // Compare the preliminary value of *pSwapchainImageCount with the 1699 // value this time: 1700 if (*pSwapchainImageCount > pSwapchain->imageCount) { 1701 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount", "pSwapchainImages", 1702 *pSwapchainImageCount, pSwapchain->imageCount); 1703 } else if (*pSwapchainImageCount > 0) { 1704 // Record the images and their state: 1705 pSwapchain->imageCount = *pSwapchainImageCount; 1706 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) { 1707 pSwapchain->images[i].image = pSwapchainImages[i]; 1708 pSwapchain->images[i].pSwapchain = pSwapchain; 1709 pSwapchain->images[i].ownedByApp = false; 1710 } 1711 } 1712 } 1713 loader_platform_thread_unlock_mutex(&globalLock); 1714 return result; 1715 } 1716 loader_platform_thread_unlock_mutex(&globalLock); 1717 return VK_ERROR_VALIDATION_FAILED_EXT; 1718 } 1719 1720 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 1721 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 1722 // TODOs: 1723 // 1724 // - Address the timeout. Possibilities include looking at the state of the 1725 // swapchain's images, depending on the timeout value. 1726 // - Implement a check for validity language that reads: If pname:semaphore is 1727 // not sname:VK_NULL_HANDLE it must: be unsignalled 1728 // - Implement a check for validity language that reads: If pname:fence is not 1729 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated 1730 // with any other queue command that has not yet completed execution on that 1731 // queue 1732 // - Record/update the state of the swapchain, in case an error occurs 1733 // (e.g. VK_ERROR_OUT_OF_DATE_KHR). 1734 VkResult result = VK_SUCCESS; 1735 VkBool32 skipCall = VK_FALSE; 1736 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1737 loader_platform_thread_lock_mutex(&globalLock); 1738 SwpDevice *pDevice = &my_data->deviceMap[device]; 1739 1740 // Validate that the swapchain extension was enabled: 1741 if (pDevice && !pDevice->swapchainExtensionEnabled) { 1742 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1743 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__, 1744 VK_KHR_SWAPCHAIN_EXTENSION_NAME); 1745 } 1746 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) { 1747 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, 1748 "%s() called with both the semaphore and fence parameters set to " 1749 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__); 1750 } 1751 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain]; 1752 if (pSwapchain) { 1753 // Look to see if the application is trying to own too many images at 1754 // the same time (i.e. not leave any to display): 1755 uint32_t imagesOwnedByApp = 0; 1756 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) { 1757 if (pSwapchain->images[i].ownedByApp) { 1758 imagesOwnedByApp++; 1759 } 1760 } 1761 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) { 1762 skipCall |= LOG_PERF_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, swapchain, "VkSwapchainKHR", 1763 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES, "%s() called when the application " 1764 "already owns all presentable images " 1765 "in this swapchain except for the " 1766 "image currently being displayed. " 1767 "This call to %s() cannot succeed " 1768 "unless another thread calls the " 1769 "vkQueuePresentKHR() function in " 1770 "order to release ownership of one of " 1771 "the presentable images of this " 1772 "swapchain.", 1773 __FUNCTION__, __FUNCTION__); 1774 } 1775 } 1776 if (!pImageIndex) { 1777 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex"); 1778 } 1779 1780 if (VK_FALSE == skipCall) { 1781 // Call down the call chain: 1782 loader_platform_thread_unlock_mutex(&globalLock); 1783 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 1784 loader_platform_thread_lock_mutex(&globalLock); 1785 1786 // Obtain this pointer again after locking: 1787 pSwapchain = &my_data->swapchainMap[swapchain]; 1788 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) { 1789 // Change the state of the image (now owned by the application): 1790 pSwapchain->images[*pImageIndex].ownedByApp = true; 1791 } 1792 loader_platform_thread_unlock_mutex(&globalLock); 1793 return result; 1794 } 1795 loader_platform_thread_unlock_mutex(&globalLock); 1796 return VK_ERROR_VALIDATION_FAILED_EXT; 1797 } 1798 1799 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 1800 // TODOs: 1801 // 1802 // - Implement a check for validity language that reads: Any given element of 1803 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal 1804 // of that sname:VkSemaphore that won't be consumed by any other wait on that 1805 // semaphore 1806 // - Record/update the state of the swapchain, in case an error occurs 1807 // (e.g. VK_ERROR_OUT_OF_DATE_KHR). 1808 VkResult result = VK_SUCCESS; 1809 VkBool32 skipCall = VK_FALSE; 1810 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); 1811 1812 if (!pPresentInfo) { 1813 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo"); 1814 } else { 1815 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) { 1816 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo", 1817 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR"); 1818 } 1819 if (pPresentInfo->pNext != NULL) { 1820 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo"); 1821 } 1822 if (!pPresentInfo->swapchainCount) { 1823 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount"); 1824 } 1825 if (!pPresentInfo->pSwapchains) { 1826 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains"); 1827 } 1828 if (!pPresentInfo->pImageIndices) { 1829 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices"); 1830 } 1831 // Note: pPresentInfo->pResults is allowed to be NULL 1832 } 1833 1834 loader_platform_thread_lock_mutex(&globalLock); 1835 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) { 1836 uint32_t index = pPresentInfo->pImageIndices[i]; 1837 SwpSwapchain *pSwapchain = &my_data->swapchainMap[pPresentInfo->pSwapchains[i]]; 1838 if (pSwapchain) { 1839 if (!pSwapchain->pDevice->swapchainExtensionEnabled) { 1840 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice", 1841 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, 1842 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__, 1843 VK_KHR_SWAPCHAIN_EXTENSION_NAME); 1844 } 1845 if (index >= pSwapchain->imageCount) { 1846 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR", 1847 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too " 1848 "large (i.e. %d). There are only %d " 1849 "images in this VkSwapchainKHR.\n", 1850 __FUNCTION__, index, pSwapchain->imageCount); 1851 } else { 1852 if (!pSwapchain->images[index].ownedByApp) { 1853 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], 1854 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) " 1855 "for an image that is not owned by " 1856 "the application.", 1857 __FUNCTION__, index); 1858 } 1859 } 1860 SwpQueue *pQueue = &my_data->queueMap[queue]; 1861 SwpSurface *pSurface = pSwapchain->pSurface; 1862 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) { 1863 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex; 1864 // Note: the 1st test is to ensure queueFamilyIndex is in range, 1865 // and the 2nd test is the validation check: 1866 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) && 1867 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) { 1868 skipCall |= 1869 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR", 1870 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose " 1871 "surface is not supported for " 1872 "presention on this device with the " 1873 "queueFamilyIndex (i.e. %d) of the " 1874 "given queue.", 1875 __FUNCTION__, queueFamilyIndex); 1876 } 1877 } 1878 } 1879 } 1880 1881 if (VK_FALSE == skipCall) { 1882 // Call down the call chain: 1883 loader_platform_thread_unlock_mutex(&globalLock); 1884 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo); 1885 loader_platform_thread_lock_mutex(&globalLock); 1886 1887 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) { 1888 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 1889 int index = pPresentInfo->pImageIndices[i]; 1890 SwpSwapchain *pSwapchain = &my_data->swapchainMap[pPresentInfo->pSwapchains[i]]; 1891 if (pSwapchain) { 1892 // Change the state of the image (no longer owned by the 1893 // application): 1894 pSwapchain->images[index].ownedByApp = false; 1895 } 1896 } 1897 } 1898 loader_platform_thread_unlock_mutex(&globalLock); 1899 return result; 1900 } 1901 loader_platform_thread_unlock_mutex(&globalLock); 1902 return VK_ERROR_VALIDATION_FAILED_EXT; 1903 } 1904 1905 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL 1906 vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { 1907 VkBool32 skipCall = VK_FALSE; 1908 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1909 1910 if (VK_FALSE == skipCall) { 1911 // Call down the call chain: 1912 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 1913 1914 // Remember the queue's handle, and link it to the device: 1915 loader_platform_thread_lock_mutex(&globalLock); 1916 SwpDevice *pDevice = &my_data->deviceMap[device]; 1917 my_data->queueMap[&pQueue].queue = *pQueue; 1918 if (pDevice) { 1919 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue]; 1920 } 1921 my_data->queueMap[&pQueue].pDevice = pDevice; 1922 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex; 1923 loader_platform_thread_unlock_mutex(&globalLock); 1924 } 1925 } 1926 1927 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1928 vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 1929 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) { 1930 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 1931 VkResult result = 1932 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 1933 if (VK_SUCCESS == result) { 1934 loader_platform_thread_lock_mutex(&globalLock); 1935 result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); 1936 loader_platform_thread_unlock_mutex(&globalLock); 1937 } 1938 return result; 1939 } 1940 1941 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, 1942 VkDebugReportCallbackEXT msgCallback, 1943 const VkAllocationCallbacks *pAllocator) { 1944 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 1945 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 1946 loader_platform_thread_lock_mutex(&globalLock); 1947 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator); 1948 loader_platform_thread_unlock_mutex(&globalLock); 1949 } 1950 1951 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL 1952 vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, 1953 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1954 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 1955 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, 1956 pMsg); 1957 } 1958 1959 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) { 1960 if (!strcmp("vkGetDeviceProcAddr", funcName)) 1961 return (PFN_vkVoidFunction)vkGetDeviceProcAddr; 1962 if (!strcmp(funcName, "vkDestroyDevice")) 1963 return (PFN_vkVoidFunction)vkDestroyDevice; 1964 1965 if (device == VK_NULL_HANDLE) { 1966 return NULL; 1967 } 1968 1969 layer_data *my_data; 1970 1971 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 1972 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table; 1973 if (!strcmp("vkCreateSwapchainKHR", funcName)) 1974 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR); 1975 if (!strcmp("vkDestroySwapchainKHR", funcName)) 1976 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR); 1977 if (!strcmp("vkGetSwapchainImagesKHR", funcName)) 1978 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR); 1979 if (!strcmp("vkAcquireNextImageKHR", funcName)) 1980 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR); 1981 if (!strcmp("vkQueuePresentKHR", funcName)) 1982 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR); 1983 if (!strcmp("vkGetDeviceQueue", funcName)) 1984 return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue); 1985 1986 if (pDisp->GetDeviceProcAddr == NULL) 1987 return NULL; 1988 return pDisp->GetDeviceProcAddr(device, funcName); 1989 } 1990 1991 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1992 if (!strcmp("vkGetInstanceProcAddr", funcName)) 1993 return (PFN_vkVoidFunction)vkGetInstanceProcAddr; 1994 if (!strcmp(funcName, "vkCreateInstance")) 1995 return (PFN_vkVoidFunction)vkCreateInstance; 1996 if (!strcmp(funcName, "vkDestroyInstance")) 1997 return (PFN_vkVoidFunction)vkDestroyInstance; 1998 if (!strcmp(funcName, "vkCreateDevice")) 1999 return (PFN_vkVoidFunction)vkCreateDevice; 2000 if (!strcmp(funcName, "vkEnumeratePhysicalDevices")) 2001 return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices; 2002 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) 2003 return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties; 2004 if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) 2005 return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties; 2006 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) 2007 return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties; 2008 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties")) 2009 return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties; 2010 if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties")) 2011 return (PFN_vkVoidFunction)vkGetPhysicalDeviceQueueFamilyProperties; 2012 2013 if (instance == VK_NULL_HANDLE) { 2014 return NULL; 2015 } 2016 2017 PFN_vkVoidFunction addr; 2018 2019 layer_data *my_data; 2020 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 2021 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table; 2022 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName); 2023 if (addr) { 2024 return addr; 2025 } 2026 2027 #ifdef VK_USE_PLATFORM_ANDROID_KHR 2028 if (!strcmp("vkCreateAndroidSurfaceKHR", funcName)) 2029 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateAndroidSurfaceKHR); 2030 #endif // VK_USE_PLATFORM_ANDROID_KHR 2031 #ifdef VK_USE_PLATFORM_MIR_KHR 2032 if (!strcmp("vkCreateMirSurfaceKHR", funcName)) 2033 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateMirSurfaceKHR); 2034 if (!strcmp("vkGetPhysicalDeviceMirPresentationSupportKHR", funcName)) 2035 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceMirPresentationSupportKHR); 2036 #endif // VK_USE_PLATFORM_MIR_KHR 2037 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 2038 if (!strcmp("vkCreateWaylandSurfaceKHR", funcName)) 2039 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWaylandSurfaceKHR); 2040 if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", funcName)) 2041 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWaylandPresentationSupportKHR); 2042 #endif // VK_USE_PLATFORM_WAYLAND_KHR 2043 #ifdef VK_USE_PLATFORM_WIN32_KHR 2044 if (!strcmp("vkCreateWin32SurfaceKHR", funcName)) 2045 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWin32SurfaceKHR); 2046 if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", funcName)) 2047 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWin32PresentationSupportKHR); 2048 #endif // VK_USE_PLATFORM_WIN32_KHR 2049 #ifdef VK_USE_PLATFORM_XCB_KHR 2050 if (!strcmp("vkCreateXcbSurfaceKHR", funcName)) 2051 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXcbSurfaceKHR); 2052 if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", funcName)) 2053 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXcbPresentationSupportKHR); 2054 #endif // VK_USE_PLATFORM_XCB_KHR 2055 #ifdef VK_USE_PLATFORM_XLIB_KHR 2056 if (!strcmp("vkCreateXlibSurfaceKHR", funcName)) 2057 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXlibSurfaceKHR); 2058 if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", funcName)) 2059 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXlibPresentationSupportKHR); 2060 #endif // VK_USE_PLATFORM_XLIB_KHR 2061 if (!strcmp("vkDestroySurfaceKHR", funcName)) 2062 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR); 2063 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName)) 2064 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR); 2065 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName)) 2066 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); 2067 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName)) 2068 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR); 2069 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName)) 2070 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR); 2071 2072 if (pTable->GetInstanceProcAddr == NULL) 2073 return NULL; 2074 return pTable->GetInstanceProcAddr(instance, funcName); 2075 } 2076