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