From 46b88bca67b586be0459fd01f38b50ed70746f0d Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Wed, 20 Jan 2016 16:33:34 -0700 Subject: [PATCH] Swapchain: Keep/check relationships between surfaces and swapchains. --- layers/swapchain.cpp | 103 ++++++++++++++++++++++++++++++++-- layers/swapchain.h | 23 +++++++- layers/vk_validation_layer_details.md | 2 +- 3 files changed, 119 insertions(+), 9 deletions(-) diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp index 4690e7f..2338836 100644 --- a/layers/swapchain.cpp +++ b/layers/swapchain.cpp @@ -435,6 +435,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( // Call down the call chain: result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface); + + if ((result == VK_SUCCESS) && pInstance && pSurface) { + // Record the VkSurfaceKHR returned by the ICD: + my_data->surfaceMap[*pSurface].surface = *pSurface; + my_data->surfaceMap[*pSurface].pInstance = pInstance; + // Point to the associated SwpInstance: + pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; + } + return result; } return VK_ERROR_VALIDATION_FAILED_EXT; @@ -485,6 +494,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( // Call down the call chain: result = my_data->instance_dispatch_table->CreateMirSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface); + + if ((result == VK_SUCCESS) && pInstance && pSurface) { + // Record the VkSurfaceKHR returned by the ICD: + my_data->surfaceMap[*pSurface].surface = *pSurface; + my_data->surfaceMap[*pSurface].pInstance = pInstance; + // Point to the associated SwpInstance: + pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; + } + return result; } return VK_ERROR_VALIDATION_FAILED_EXT; @@ -572,6 +590,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( // Call down the call chain: result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface); + + if ((result == VK_SUCCESS) && pInstance && pSurface) { + // Record the VkSurfaceKHR returned by the ICD: + my_data->surfaceMap[*pSurface].surface = *pSurface; + my_data->surfaceMap[*pSurface].pInstance = pInstance; + // Point to the associated SwpInstance: + pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; + } + return result; } return VK_ERROR_VALIDATION_FAILED_EXT; @@ -659,6 +686,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( // Call down the call chain: result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR( instance, pCreateInfo, pAllocator, pSurface); + + if ((result == VK_SUCCESS) && pInstance && pSurface) { + // Record the VkSurfaceKHR returned by the ICD: + my_data->surfaceMap[*pSurface].surface = *pSurface; + my_data->surfaceMap[*pSurface].pInstance = pInstance; + // Point to the associated SwpInstance: + pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; + } + return result; } return VK_ERROR_VALIDATION_FAILED_EXT; @@ -745,6 +781,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR( // Call down the call chain: result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface); + + if ((result == VK_SUCCESS) && pInstance && pSurface) { + // Record the VkSurfaceKHR returned by the ICD: + my_data->surfaceMap[*pSurface].surface = *pSurface; + my_data->surfaceMap[*pSurface].pInstance = pInstance; + // Point to the associated SwpInstance: + pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; + } + return result; } return VK_ERROR_VALIDATION_FAILED_EXT; @@ -833,6 +878,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR( // Call down the call chain: result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface); + + if ((result == VK_SUCCESS) && pInstance && pSurface) { + // Record the VkSurfaceKHR returned by the ICD: + my_data->surfaceMap[*pSurface].surface = *pSurface; + my_data->surfaceMap[*pSurface].pInstance = pInstance; + // Point to the associated SwpInstance: + pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; + } + return result; } return VK_ERROR_VALIDATION_FAILED_EXT; @@ -881,14 +935,37 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance insta { VkBool32 skipCall = VK_FALSE; layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); + SwpInstance *pInstance = &(my_data->instanceMap[instance]); + SwpSurface *pSurface = &my_data->surfaceMap[surface]; + + // Regardless of skipCall value, do some internal cleanup: + if (pSurface) { + // Delete the SwpSurface associated with this surface: + if (pSurface->pInstance) { + pSurface->pInstance->surfaces.erase(surface); + } + if (!pSurface->swapchains.empty()) { + LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", + SWAPCHAIN_DEL_OBJECT_BEFORE_SWAPCHAINS, + "%s() called before all of its associated " + "VkSwapchainKHRs were destroyed.", + __FUNCTION__); + // Empty and then delete all SwpSwapchain's + for (auto it = pSurface->swapchains.begin() ; + it != pSurface->swapchains.end() ; it++) { + // Delete all SwpImage's + it->second->images.clear(); + } + pSurface->swapchains.clear(); + } + my_data->surfaceMap.erase(surface); + } if (VK_FALSE == skipCall) { // Call down the call chain: my_data->instance_dispatch_table->DestroySurfaceKHR( instance, surface, pAllocator); } - - // No need to do any cleanup--rely on object_tracker to track VkSurfaceKHR } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) @@ -983,7 +1060,7 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, cons } if (!pDevice->swapchains.empty()) { LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", - SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS, + SWAPCHAIN_DEL_OBJECT_BEFORE_SWAPCHAINS, "%s() called before all of its associated " "VkSwapchainKHRs were destroyed.", __FUNCTION__); @@ -1605,7 +1682,7 @@ static VkBool32 validateCreateSwapchainKHR( "than the VkSwapchainKHR was created with.", __FUNCTION__); } - if (pCreateInfo->surface != pOldSwapchain->surface) { + if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) { skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, @@ -1649,9 +1726,23 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain]; my_data->swapchainMap[*pSwapchain].pDevice = pDevice; - my_data->swapchainMap[*pSwapchain].surface = - (pCreateInfo) ? pCreateInfo->surface : 0; my_data->swapchainMap[*pSwapchain].imageCount = 0; + // Store a pointer to the surface + SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice; + SwpInstance *pInstance = + (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL; + layer_data *my_instance_data = + ((pInstance) ? + get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : + NULL); + SwpSurface *pSurface = + ((my_data && pCreateInfo) ? + &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL); + my_data->swapchainMap[*pSwapchain].pSurface = pSurface; + if (pSurface) { + pSurface->swapchains[*pSwapchain] = + &my_data->swapchainMap[*pSwapchain]; + } } return result; diff --git a/layers/swapchain.h b/layers/swapchain.h index ba80a0e..d60f956 100644 --- a/layers/swapchain.h +++ b/layers/swapchain.h @@ -63,7 +63,7 @@ typedef enum _SWAPCHAIN_ERROR SWAPCHAIN_INVALID_HANDLE, // Handle used that isn't currently valid SWAPCHAIN_NULL_POINTER, // Pointer set to NULL, instead of being a valid pointer SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, // Did not enable WSI extension, but called WSI function - SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS, // Called vkDestroyDevice() before vkDestroySwapchainKHR() + SWAPCHAIN_DEL_OBJECT_BEFORE_SWAPCHAINS, // Called vkDestroyDevice() before vkDestroySwapchainKHR() SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, // Called vkCreateSwapchainKHR() with a pCreateInfo->surface that wasn't seen as supported by vkGetPhysicalDeviceSurfaceSupportKHR for the device SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, // Called vkCreateSwapchainKHR() without calling a query (e.g. vkGetPhysicalDeviceSurfaceCapabilitiesKHR()) SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, // Called vkCreateSwapchainKHR() with out-of-bounds minImageCount @@ -165,12 +165,14 @@ typedef enum _SWAPCHAIN_ERROR // Forward declarations: struct _SwpInstance; +struct _SwpSurface; struct _SwpPhysicalDevice; struct _SwpDevice; struct _SwpSwapchain; struct _SwpImage; typedef _SwpInstance SwpInstance; +typedef _SwpSurface SwpSurface;; typedef _SwpPhysicalDevice SwpPhysicalDevice; typedef _SwpDevice SwpDevice; typedef _SwpSwapchain SwpSwapchain; @@ -181,6 +183,9 @@ struct _SwpInstance { // The actual handle for this VkInstance: VkInstance instance; + // Remember the VkSurfaceKHR's that are created for this VkInstance: + unordered_map surfaces; + // When vkEnumeratePhysicalDevices is called, the VkPhysicalDevice's are // remembered: unordered_map physicalDevices; @@ -214,6 +219,19 @@ struct _SwpInstance { bool xlibSurfaceExtensionEnabled; #endif // VK_USE_PLATFORM_XLIB_KHR }; + +// Create one of these for each VkSurfaceKHR: +struct _SwpSurface { + // The actual handle for this VkSurfaceKHR: + VkSurfaceKHR surface; + + // VkInstance that this VkSurfaceKHR is associated with: + SwpInstance *pInstance; + + // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are + // remembered: + unordered_map swapchains; +}; // Create one of these for each VkPhysicalDevice within a VkInstance: struct _SwpPhysicalDevice { @@ -296,7 +314,7 @@ struct _SwpSwapchain { SwpDevice *pDevice; // Corresponding VkSurfaceKHR to this VkSwapchainKHR: - VkSurfaceKHR surface; + SwpSurface *pSurface; // When vkGetSwapchainImagesKHR is called, the VkImage's are // remembered: @@ -312,6 +330,7 @@ struct layer_data { // NOTE: The following are for keeping track of info that is used for // validating the WSI extensions. std::unordered_map instanceMap; + std::unordered_map surfaceMap; std::unordered_map physicalDeviceMap; std::unordered_map deviceMap; std::unordered_map swapchainMap; diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md index 43c3b64..6298693 100644 --- a/layers/vk_validation_layer_details.md +++ b/layers/vk_validation_layer_details.md @@ -347,7 +347,7 @@ This layer is a work in progress. VK_LAYER_LUNARG_swapchain layer is intended to | Valid handle | If an invalid handle is used, this error will be flagged | INVALID_HANDLE | vkCreateDevice vkCreateSwapchainKHR | NA | None | | Valid pointer | If a NULL pointer is used, this error will be flagged | NULL_POINTER | vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfacePresentModesKHR vkCreateSwapchainKHR vkGetSwapchainImagesKHR vkAcquireNextImageKHR vkQueuePresentKHR | NA | None | | Extension enabled before use | Validates that a WSI extension is enabled before its functions are used | EXT_NOT_ENABLED_BUT_USED | vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfacePresentModesKHR vkCreateSwapchainKHR vkDestroySwapchainKHR vkGetSwapchainImagesKHR vkAcquireNextImageKHR vkQueuePresentKHR | NA | None | -| Swapchains destroyed before devices | Validates that vkDestroySwapchainKHR() is called for all swapchains associated with a device before vkDestroyDevice() is called | DEL_DEVICE_BEFORE_SWAPCHAINS | vkDestroyDevice | NA | None | +| Swapchains destroyed before devices | Validates that vkDestroySwapchainKHR() is called for all swapchains associated with a device before vkDestroyDevice() is called | DEL_OBJECT_BEFORE_SWAPCHAINS | vkDestroyDevice vkDestroySurfaceKHR | NA | None | | Supported surface used with a swapchain | Validates that vkGetPhysicalDeviceSurfaceSupportKHR() was seen to support the surface used with a swapchain | CREATE_SWAP_UNSUPPORTED_SURFACE | vkCreateSwapchainKHR | NA | None | | Queries occur before swapchain creation | Validates that vkGetPhysicalDeviceSurfaceCapabilitiesKHR(), vkGetPhysicalDeviceSurfaceFormatsKHR() and vkGetPhysicalDeviceSurfacePresentModesKHR() are called before vkCreateSwapchainKHR() | CREATE_SWAP_WITHOUT_QUERY | vkCreateSwapchainKHR | NA | None | | vkCreateSwapchainKHR(pCreateInfo->minImageCount) | Validates vkCreateSwapchainKHR(pCreateInfo->minImageCount) | CREATE_SWAP_BAD_MIN_IMG_COUNT | vkCreateSwapchainKHR | NA | None | -- 2.7.4