Swapchain: Keep/check relationships between surfaces and swapchains.
authorIan Elliott <ianelliott@google.com>
Wed, 20 Jan 2016 23:33:34 +0000 (16:33 -0700)
committerJon Ashburn <jon@lunarg.com>
Thu, 28 Jan 2016 18:18:56 +0000 (11:18 -0700)
layers/swapchain.cpp
layers/swapchain.h
layers/vk_validation_layer_details.md

index 4690e7f..2338836 100644 (file)
@@ -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;
index ba80a0e..d60f956 100644 (file)
@@ -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<const void*, SwpSurface*> surfaces;
+
     // When vkEnumeratePhysicalDevices is called, the VkPhysicalDevice's are
     // remembered:
     unordered_map<const void*, SwpPhysicalDevice*> 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<VkSwapchainKHR, SwpSwapchain*> 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<void *, SwpInstance>       instanceMap;
+    std::unordered_map<void *, SwpSurface>        surfaceMap;
     std::unordered_map<void *, SwpPhysicalDevice> physicalDeviceMap;
     std::unordered_map<void *, SwpDevice>         deviceMap;
     std::unordered_map<VkSwapchainKHR, SwpSwapchain>    swapchainMap;
index 43c3b64..6298693 100644 (file)
@@ -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 |