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