From 22ababc340f8f08baefa4c02b9776a62474631e1 Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Thu, 21 Jan 2016 14:29:45 -0700 Subject: [PATCH] Swapchain: Validating supported surface for presenting with a queue. This validation involves multiple levels of indirection as vkQueuePresentKHR() receives a queue parameter, and a pPresentInfo->pSwapchains array. For each swapchain, it's surface must have been seen to be supported with a queueFamilyIndex that is associated with the queue parameter. Info must be recorded at various previous calls, and be correlatable at this point in time. Very complicated! --- layers/swapchain.cpp | 145 +++++++++++++++++++++++++++------- layers/swapchain.h | 46 ++++++++--- layers/vk_validation_layer_details.md | 6 +- 3 files changed, 155 insertions(+), 42 deletions(-) diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp index d75a0ac..47e4fe8 100644 --- a/layers/swapchain.cpp +++ b/layers/swapchain.cpp @@ -89,6 +89,7 @@ static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, cons pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR"); pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR"); pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR"); + pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue) gpa(device, "vkGetDeviceQueue"); SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice]; if (pPhysicalDevice) { @@ -121,7 +122,6 @@ static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreate layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table; PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr; - pDisp->GetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) gpa(instance, "vkGetPhysicalDeviceQueueFamilyProperties"); #ifdef VK_USE_PLATFORM_ANDROID_KHR pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR) gpa(instance, "vkCreateAndroidSurfaceKHR"); #endif // VK_USE_PLATFORM_ANDROID_KHR @@ -403,7 +403,7 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPropert if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) { pPhysicalDevice->gotQueueFamilyPropertyCount = true; - pPhysicalDevice->pQueueFamilyPropertyCount = + pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount; } } @@ -460,6 +460,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( my_data->surfaceMap[*pSurface].pInstance = pInstance; my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); + my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; + my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; // Point to the associated SwpInstance: pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; } @@ -521,6 +523,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( my_data->surfaceMap[*pSurface].pInstance = pInstance; my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); + my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; + my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; // Point to the associated SwpInstance: pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; } @@ -551,12 +555,12 @@ VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentatio __FUNCTION__, VK_KHR_MIR_SURFACE_EXTENSION_NAME); } if (pPhysicalDevice->gotQueueFamilyPropertyCount && - (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) { + (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", queueFamilyIndex, - pPhysicalDevice->pQueueFamilyPropertyCount); + pPhysicalDevice->numOfQueueFamilies); } if (VK_FALSE == skipCall) { @@ -619,6 +623,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( my_data->surfaceMap[*pSurface].pInstance = pInstance; my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); + my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; + my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; // Point to the associated SwpInstance: pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; } @@ -649,12 +655,12 @@ VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresent __FUNCTION__, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); } if (pPhysicalDevice->gotQueueFamilyPropertyCount && - (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) { + (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", queueFamilyIndex, - pPhysicalDevice->pQueueFamilyPropertyCount); + pPhysicalDevice->numOfQueueFamilies); } if (VK_FALSE == skipCall) { @@ -717,6 +723,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( my_data->surfaceMap[*pSurface].pInstance = pInstance; my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); + my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; + my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; // Point to the associated SwpInstance: pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; } @@ -746,12 +754,12 @@ VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32Presentat __FUNCTION__, VK_KHR_WIN32_SURFACE_EXTENSION_NAME); } if (pPhysicalDevice->gotQueueFamilyPropertyCount && - (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) { + (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", queueFamilyIndex, - pPhysicalDevice->pQueueFamilyPropertyCount); + pPhysicalDevice->numOfQueueFamilies); } if (VK_FALSE == skipCall) { @@ -814,6 +822,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR( my_data->surfaceMap[*pSurface].pInstance = pInstance; my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); + my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; + my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; // Point to the associated SwpInstance: pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; } @@ -845,12 +855,12 @@ VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentatio __FUNCTION__, VK_KHR_XCB_SURFACE_EXTENSION_NAME); } if (pPhysicalDevice->gotQueueFamilyPropertyCount && - (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) { + (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", queueFamilyIndex, - pPhysicalDevice->pQueueFamilyPropertyCount); + pPhysicalDevice->numOfQueueFamilies); } if (VK_FALSE == skipCall) { @@ -913,6 +923,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR( my_data->surfaceMap[*pSurface].pInstance = pInstance; my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL); + my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0; + my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL; // Point to the associated SwpInstance: pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface]; } @@ -944,12 +956,12 @@ VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentati __FUNCTION__, VK_KHR_XLIB_SURFACE_EXTENSION_NAME); } if (pPhysicalDevice->gotQueueFamilyPropertyCount && - (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) { + (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", queueFamilyIndex, - pPhysicalDevice->pQueueFamilyPropertyCount); + pPhysicalDevice->numOfQueueFamilies); } if (VK_FALSE == skipCall) { @@ -1136,13 +1148,22 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupport "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME); } - if (pPhysicalDevice->gotQueueFamilyPropertyCount && - (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) { + if (!pPhysicalDevice->gotQueueFamilyPropertyCount) { + skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, + pPhysicalDevice, + "VkPhysicalDevice", + SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, + "%s() called before calling the " + "vkGetPhysicalDeviceQueueFamilyProperties " + "function.", + __FUNCTION__); + } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && + (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) { skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice", queueFamilyIndex, - pPhysicalDevice->pQueueFamilyPropertyCount); + pPhysicalDevice->numOfQueueFamilies); } if (!pSupported) { skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, @@ -1158,13 +1179,27 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupport if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) { // Record the result of this query: - pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] = - surface; - pPhysicalDevice->surfaceSupport[surface] = - queueFamilyIndex; - // TODO: We need to compare this with the actual queue used for - // presentation, to ensure it was advertised to the application as - // supported for presentation. + SwpInstance *pInstance = pPhysicalDevice->pInstance; + SwpSurface *pSurface = + (pInstance) ? pInstance->surfaces[surface] : NULL; + if (pSurface) { + pPhysicalDevice->supportedSurfaces[surface] = pSurface; + if (!pSurface->numQueueFamilyIndexSupport) { + if (pPhysicalDevice->gotQueueFamilyPropertyCount) { + pSurface->pQueueFamilyIndexSupport = (VkBool32 *) + malloc(pPhysicalDevice->numOfQueueFamilies * + sizeof(VkBool32)); + if (pSurface->pQueueFamilyIndexSupport != NULL) { + pSurface->numQueueFamilyIndexSupport = + pPhysicalDevice->numOfQueueFamilies; + } + } + } + if (pSurface->numQueueFamilyIndexSupport) { + pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = + *pSupported; + } + } } return result; @@ -1414,8 +1449,10 @@ static VkBool32 validateCreateSwapchainKHR( // Validate pCreateInfo->surface to make sure that // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported // surface: - uint32_t queueFamilyIndex = pPhysicalDevice->surfaceSupport[pCreateInfo->surface]; - if (!queueFamilyIndex) { + SwpSurface *pSurface = + ((pPhysicalDevice) ? + pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL); + if (!pSurface) { skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, "%s() called with pCreateInfo->surface that " @@ -1760,8 +1797,10 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( SwpDevice *pDevice = &my_data->deviceMap[device]; my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain; - pDevice->swapchains[*pSwapchain] = - &my_data->swapchainMap[*pSwapchain]; + if (pDevice) { + pDevice->swapchains[*pSwapchain] = + &my_data->swapchainMap[*pSwapchain]; + } my_data->swapchainMap[*pSwapchain].pDevice = pDevice; my_data->swapchainMap[*pSwapchain].imageCount = 0; my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = @@ -1999,8 +2038,6 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal // of that sname:VkSemaphore that won't be consumed by any other wait on that // semaphore -// - Ensure that the queue is active, and is one of the queueFamilyIndex's -// that was returned by a previuos query. // - Record/update the state of the swapchain, in case an error occurs // (e.g. VK_ERROR_OUT_OF_DATE_KHR). VkResult result = VK_SUCCESS; @@ -2078,6 +2115,26 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( __FUNCTION__, index); } } + SwpQueue *pQueue = &my_data->queueMap[queue]; + SwpSurface *pSurface = pSwapchain->pSurface; + if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) { + uint32_t queueFamilyIndex = pQueue->queueFamilyIndex; + // Note: the 1st test is to ensure queueFamilyIndex is in range, + // and the 2nd test is the validation check: + if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) && + (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) { + skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, + pPresentInfo->pSwapchains[i], + "VkSwapchainKHR", + SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, + "%s() called with a swapchain whose " + "surface is not supported for " + "presention on this device with the " + "queueFamilyIndex (i.e. %d) of the " + "given queue.", + __FUNCTION__, queueFamilyIndex); + } + } } } @@ -2105,6 +2162,32 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( return VK_ERROR_VALIDATION_FAILED_EXT; } +VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue( + VkDevice device, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue* pQueue) +{ + VkBool32 skipCall = VK_FALSE; + layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + + if (VK_FALSE == skipCall) { + // Call down the call chain: + my_data->device_dispatch_table->GetDeviceQueue( + device, queueFamilyIndex, queueIndex, pQueue); + + // Remember the queue's handle, and link it to the device: + SwpDevice *pDevice = &my_data->deviceMap[device]; + my_data->queueMap[&pQueue].queue = *pQueue; + if (pDevice) { + pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue]; + } + my_data->queueMap[&pQueue].pDevice = pDevice; + my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex; + } +} + + VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, @@ -2169,6 +2252,8 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD if (!strcmp("vkQueuePresentKHR", funcName)) return reinterpret_cast(vkQueuePresentKHR); } + if (!strcmp("vkGetDeviceQueue", funcName)) + return reinterpret_cast(vkGetDeviceQueue); if (pDisp->GetDeviceProcAddr == NULL) return NULL; @@ -2191,6 +2276,8 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties; if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties; + if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties")) + return (PFN_vkVoidFunction) vkGetPhysicalDeviceQueueFamilyProperties; if (instance == VK_NULL_HANDLE) { return NULL; @@ -2206,8 +2293,6 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(V return addr; } - if (!strcmp("vkGetPhysicalDeviceQueueFamilyProperties", funcName)) - return reinterpret_cast(vkGetPhysicalDeviceQueueFamilyProperties); #ifdef VK_USE_PLATFORM_ANDROID_KHR if (my_data->instanceMap.size() != 0 && my_data->instanceMap[instance].androidSurfaceExtensionEnabled) diff --git a/layers/swapchain.h b/layers/swapchain.h index 6fc3819..154b921 100644 --- a/layers/swapchain.h +++ b/layers/swapchain.h @@ -89,8 +89,10 @@ typedef enum _SWAPCHAIN_ERROR SWAPCHAIN_WRONG_STYPE, // The sType for a struct has the wrong value SWAPCHAIN_WRONG_NEXT, // The pNext for a struct is not NULL SWAPCHAIN_ZERO_VALUE, // A value should be non-zero - SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by vkGetPhysicalDeviceQueueFamilyProperties() SWAPCHAIN_INCOMPATIBLE_ALLOCATOR, // pAllocator must be compatible (i.e. NULL or not) when object is created and destroyed + SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, // A function using a queueFamilyIndex was called before vkGetPhysicalDeviceQueueFamilyProperties() was called + SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by vkGetPhysicalDeviceQueueFamilyProperties() + SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, // A surface is not supported by a given queueFamilyIndex, as seen by vkGetPhysicalDeviceSurfaceSupportKHR() } SWAPCHAIN_ERROR; @@ -171,6 +173,7 @@ struct _SwpPhysicalDevice; struct _SwpDevice; struct _SwpSwapchain; struct _SwpImage; +struct _SwpQueue; typedef _SwpInstance SwpInstance; typedef _SwpSurface SwpSurface;; @@ -178,6 +181,7 @@ typedef _SwpPhysicalDevice SwpPhysicalDevice; typedef _SwpDevice SwpDevice; typedef _SwpSwapchain SwpSwapchain; typedef _SwpImage SwpImage; +typedef _SwpQueue SwpQueue; // Create one of these for each VkInstance: struct _SwpInstance { @@ -235,6 +239,16 @@ struct _SwpSurface { // 'true' if pAllocator was non-NULL when vkCreate*SurfaceKHR was called: bool usedAllocatorToCreate; + + // Value of pQueueFamilyPropertyCount that was returned by the + // vkGetPhysicalDeviceQueueFamilyProperties() function: + uint32_t numQueueFamilyIndexSupport; + // Array of VkBool32's that is intialized by the + // vkGetPhysicalDeviceSurfaceSupportKHR() function. First call for a given + // surface allocates and initializes this array to false for all + // queueFamilyIndex's (and sets numQueueFamilyIndexSupport to non-zero). + // All calls set the entry for a given queueFamilyIndex: + VkBool32 *pQueueFamilyIndexSupport; }; // Create one of these for each VkPhysicalDevice within a VkInstance: @@ -249,17 +263,13 @@ struct _SwpPhysicalDevice { SwpInstance *pInstance; // Records results of vkGetPhysicalDeviceQueueFamilyProperties()'s - // pQueueFamilyPropertyCount parameter when pQueueFamilyProperties is NULL: + // numOfQueueFamilies parameter when pQueueFamilyProperties is NULL: bool gotQueueFamilyPropertyCount; - uint32_t pQueueFamilyPropertyCount; + uint32_t numOfQueueFamilies; - // Record all supported queueFamilyIndex-surface pairs that support - // presenting with WSI swapchains: - unordered_map queueFamilyIndexSupport; - - // Record all supported surface-queueFamilyIndex pairs that support - // presenting with WSI swapchains: - unordered_map surfaceSupport; + // Record all surfaces that vkGetPhysicalDeviceSurfaceSupportKHR() was + // called for: + unordered_map supportedSurfaces; // TODO: Record/use this info per-surface, not per-device, once a // non-dispatchable surface object is added to WSI: @@ -294,6 +304,9 @@ struct _SwpDevice { // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are // remembered: unordered_map swapchains; + + // When vkGetDeviceQueue is called, the VkQueue's are remembered: + unordered_map queues; }; // Create one of these for each VkImage within a VkSwapchainKHR: @@ -329,6 +342,18 @@ struct _SwpSwapchain { bool usedAllocatorToCreate; }; +// Create one of these for each VkQueue within a VkDevice: +struct _SwpQueue { + // The actual handle for this VkQueue: + VkQueue queue; + + // Corresponding VkDevice (and info) to this VkSwapchainKHR: + SwpDevice *pDevice; + + // Which queueFamilyIndex this VkQueue is associated with: + uint32_t queueFamilyIndex; +}; + struct layer_data { debug_report_data *report_data; std::vector logging_callback; @@ -341,6 +366,7 @@ struct layer_data { std::unordered_map physicalDeviceMap; std::unordered_map deviceMap; std::unordered_map swapchainMap; + std::unordered_map queueMap; layer_data() : report_data(nullptr), diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md index 5ebe0d7..3d6d9ee 100644 --- a/layers/vk_validation_layer_details.md +++ b/layers/vk_validation_layer_details.md @@ -348,7 +348,7 @@ This layer is a work in progress. VK_LAYER_LUNARG_swapchain layer is intended to | 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_OBJECT_BEFORE_CHILDREN | 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 | +| Surface seen to support presentation | Validates that pCreateInfo->surface was seen by vkGetPhysicalDeviceSurfaceSupportKHR() to support presentation | CREATE_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 | | vkCreateSwapchainKHR(pCreateInfo->imageExtent) | Validates vkCreateSwapchainKHR(pCreateInfo->imageExtent) when window has no fixed size | CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS | vkCreateSwapchainKHR | NA | None | @@ -373,8 +373,10 @@ This layer is a work in progress. VK_LAYER_LUNARG_swapchain layer is intended to | Valid sType | Validates that a struct has correct value for sType | WRONG_STYPE | vkCreateSwapchainKHR vkQueuePresentKHR | NA | None | | Valid pNext | Validates that a struct has NULL for the value of pNext | WRONG_NEXT | vkCreateSwapchainKHR vkQueuePresentKHR | NA | None | | Non-zero value | Validates that a required value should be non-zero | ZERO_VALUE | vkQueuePresentKHR | NA | None | -| Valid queueFamilyIndex value | Validates that a queueFamilyIndex value is less-than pQueueFamilyPropertyCount returned by vkGetPhysicalDeviceQueueFamilyProperties | ZERO_VALUE | vkGetPhysicalDeviceSurfaceSupportKHR | NA | None | | Compaitible Allocator | Validates that pAllocator is compatible (i.e. NULL or not) when an object is created and destroyed | INCOMPATIBLE_ALLOCATOR | vkDestroySurfaceKHR | NA | None | +| Valid use of queueFamilyIndex | Validates that a queueFamilyIndex not used before vkGetPhysicalDeviceQueueFamilyProperties() was called | DID_NOT_QUERY_QUEUE_FAMILIES | vkGetPhysicalDeviceSurfaceSupportKHR | NA | None | +| Valid queueFamilyIndex value | Validates that a queueFamilyIndex value is less-than pQueueFamilyPropertyCount returned by vkGetPhysicalDeviceQueueFamilyProperties | QUEUE_FAMILY_INDEX_TOO_LARGE | vkGetPhysicalDeviceSurfaceSupportKHR | NA | None | +| Supported combination of queue and surface | Validates that the surface associated with a swapchain was seen to support the queueFamilyIndex of a given queue | SURFACE_NOT_SUPPORTED_WITH_QUEUE | vkQueuePresentKHR | NA | None | Note: The following platform-specific functions are not mentioned above, because they are protected by ifdefs, which cause test failures: -- 2.7.4