1 /* Copyright (c) 2015-2016 The Khronos Group Inc. 2 * Copyright (c) 2015-2016 Valve Corporation 3 * Copyright (c) 2015-2016 LunarG, Inc. 4 * Copyright (C) 2015-2016 Google Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Ian Elliott <ian (at) lunarg.com> 19 * Author: Ian Elliott <ianelliott (at) google.com> 20 */ 21 22 #ifndef SWAPCHAIN_H 23 #define SWAPCHAIN_H 24 25 #include "vulkan/vk_layer.h" 26 #include "vk_layer_config.h" 27 #include "vk_layer_logging.h" 28 #include <vector> 29 #include <unordered_map> 30 31 using namespace std; 32 33 // Swapchain ERROR codes 34 enum SWAPCHAIN_ERROR { 35 SWAPCHAIN_INVALID_HANDLE, // Handle used that isn't currently valid 36 SWAPCHAIN_NULL_POINTER, // Pointer set to NULL, instead of being a valid pointer 37 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, // Did not enable WSI extension, but called WSI function 38 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, // Called vkDestroyDevice() before vkDestroySwapchainKHR() 39 SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, // Called vkCreateSwapchainKHR() with a pCreateInfo->surface that wasn't seen as supported 40 // by vkGetPhysicalDeviceSurfaceSupportKHR for the device 41 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, // Called vkCreateSwapchainKHR() without calling a query (e.g. 42 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR()) 43 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, // Called vkCreateSwapchainKHR() with out-of-bounds minImageCount 44 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS, // Called vkCreateSwapchainKHR() with out-of-bounds imageExtent 45 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, // Called vkCreateSwapchainKHR() with imageExtent that doesn't match window's extent 46 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, // Called vkCreateSwapchainKHR() with a non-supported preTransform 47 SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, // Called vkCreateSwapchainKHR() with a non-supported compositeAlpha 48 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, // Called vkCreateSwapchainKHR() with a non-supported imageArraySize 49 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, // Called vkCreateSwapchainKHR() with a non-supported imageUsageFlags 50 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace 51 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, // Called vkCreateSwapchainKHR() with a non-supported imageFormat 52 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace 53 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, // Called vkCreateSwapchainKHR() with a non-supported presentMode 54 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE, // Called vkCreateSwapchainKHR() with a non-supported imageSharingMode 55 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, // Called vkCreateSwapchainKHR() with bad values when imageSharingMode is 56 // VK_SHARING_MODE_CONCURRENT 57 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, // Called vkCreateSwapchainKHR() with pCreateInfo->oldSwapchain that has a different surface 58 // than pCreateInfo->surface 59 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, // Called vkDestroySwapchainKHR() with a different VkDevice than vkCreateSwapchainKHR() 60 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES, // vkAcquireNextImageKHR() asked for more images than are available 61 SWAPCHAIN_INDEX_TOO_LARGE, // Index is too large for swapchain 62 SWAPCHAIN_INDEX_NOT_IN_USE, // vkQueuePresentKHR() given index that is not acquired by app 63 SWAPCHAIN_BAD_BOOL, // VkBool32 that doesn't have value of VK_TRUE or VK_FALSE (e.g. is a non-zero form of true) 64 SWAPCHAIN_PRIOR_COUNT, // Query must be called first to get value of pCount, then called second time 65 SWAPCHAIN_INVALID_COUNT, // Second time a query called, the pCount value didn't match first time 66 SWAPCHAIN_WRONG_STYPE, // The sType for a struct has the wrong value 67 SWAPCHAIN_WRONG_NEXT, // The pNext for a struct is not NULL 68 SWAPCHAIN_ZERO_VALUE, // A value should be non-zero 69 SWAPCHAIN_INCOMPATIBLE_ALLOCATOR, // pAllocator must be compatible (i.e. NULL or not) when object is created and destroyed 70 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, // A function using a queueFamilyIndex was called before 71 // vkGetPhysicalDeviceQueueFamilyProperties() was called 72 SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by 73 // vkGetPhysicalDeviceQueueFamilyProperties() 74 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, // A surface is not supported by a given queueFamilyIndex, as seen by 75 // vkGetPhysicalDeviceSurfaceSupportKHR() 76 SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, // vkAcquireNextImageKHR should be called with a valid semaphore and/or fence 77 }; 78 79 // The following is for logging error messages: 80 #define LAYER_NAME (char *) "Swapchain" 81 #define LOG_ERROR_NON_VALID_OBJ(objType, type, obj) \ 82 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), __LINE__, \ 83 SWAPCHAIN_INVALID_HANDLE, LAYER_NAME, "%s() called with a non-valid %s.", __FUNCTION__, (obj)) \ 84 : VK_FALSE 85 #define LOG_ERROR_NULL_POINTER(objType, type, obj) \ 86 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 87 SWAPCHAIN_NULL_POINTER, LAYER_NAME, "%s() called with NULL pointer %s.", __FUNCTION__, (obj)) \ 88 : VK_FALSE 89 #define LOG_ERROR_INVALID_COUNT(objType, type, obj, obj2, val, val2) \ 90 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 91 SWAPCHAIN_INVALID_COUNT, LAYER_NAME, "%s() called with non-NULL %s, and with %s set to a " \ 92 "value (%d) that is greater than the value (%d) that " \ 93 "was returned when %s was NULL.", \ 94 __FUNCTION__, (obj2), (obj), (val), (val2), (obj2)) \ 95 : VK_FALSE 96 #define LOG_ERROR_ZERO_PRIOR_COUNT(objType, type, obj, obj2) \ 97 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 98 SWAPCHAIN_PRIOR_COUNT, LAYER_NAME, "%s() called with non-NULL %s; but no prior " \ 99 "positive value has been seen for %s.", \ 100 __FUNCTION__, (obj), (obj2)) \ 101 : VK_FALSE 102 #define LOG_ERROR_WRONG_STYPE(objType, type, obj, val) \ 103 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, SWAPCHAIN_WRONG_STYPE, \ 104 LAYER_NAME, "%s() called with the wrong value for %s->sType " \ 105 "(expected %s).", \ 106 __FUNCTION__, (obj), (val)) \ 107 : VK_FALSE 108 #define LOG_ERROR_ZERO_VALUE(objType, type, obj) \ 109 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, SWAPCHAIN_ZERO_VALUE, \ 110 LAYER_NAME, "%s() called with a zero value for %s.", __FUNCTION__, (obj)) \ 111 : VK_FALSE 112 #define LOG_ERROR(objType, type, obj, enm, fmt, ...) \ 113 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), __LINE__, (enm), \ 114 LAYER_NAME, (fmt), __VA_ARGS__) \ 115 : VK_FALSE 116 #define LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(objType, type, obj, val1, val2) \ 117 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 118 SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, LAYER_NAME, "%s() called with a queueFamilyIndex that is too " \ 119 "large (i.e. %d). The maximum value (returned " \ 120 "by vkGetPhysicalDeviceQueueFamilyProperties) is " \ 121 "only %d.\n", \ 122 __FUNCTION__, (val1), (val2)) \ 123 : VK_FALSE 124 #define LOG_PERF_WARNING(objType, type, obj, enm, fmt, ...) \ 125 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (objType), (uint64_t)(obj), __LINE__, \ 126 (enm), LAYER_NAME, (fmt), __VA_ARGS__) \ 127 : VK_FALSE 128 #define LOG_WARNING(objType, type, obj, enm, fmt, ...) \ 129 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (objType), (uint64_t)(obj), __LINE__, (enm), \ 130 LAYER_NAME, (fmt), __VA_ARGS__) \ 131 : VK_FALSE 132 #define LOG_INFO_WRONG_NEXT(objType, type, obj) \ 133 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 134 SWAPCHAIN_WRONG_NEXT, LAYER_NAME, "%s() called with non-NULL value for %s->pNext.", __FUNCTION__, (obj)) \ 135 : VK_FALSE 136 137 // NOTE: The following struct's/typedef's are for keeping track of 138 // info that is used for validating the WSI extensions. 139 140 // Forward declarations: 141 struct SwpInstance; 142 struct SwpSurface; 143 struct SwpPhysicalDevice; 144 struct SwpDevice; 145 struct SwpSwapchain; 146 struct SwpImage; 147 struct SwpQueue; 148 149 // Create one of these for each VkInstance: 150 struct SwpInstance { 151 // The actual handle for this VkInstance: 152 VkInstance instance; 153 154 // Remember the VkSurfaceKHR's that are created for this VkInstance: 155 unordered_map<VkSurfaceKHR, SwpSurface *> surfaces; 156 157 // When vkEnumeratePhysicalDevices is called, the VkPhysicalDevice's are 158 // remembered: 159 unordered_map<const void *, SwpPhysicalDevice *> physicalDevices; 160 161 // Set to true if VK_KHR_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 162 bool surfaceExtensionEnabled; 163 164 // TODO: Add additional booleans for platform-specific extensions: 165 #ifdef VK_USE_PLATFORM_ANDROID_KHR 166 // Set to true if VK_KHR_ANDROID_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 167 bool androidSurfaceExtensionEnabled; 168 #endif // VK_USE_PLATFORM_ANDROID_KHR 169 #ifdef VK_USE_PLATFORM_MIR_KHR 170 // Set to true if VK_KHR_MIR_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 171 bool mirSurfaceExtensionEnabled; 172 #endif // VK_USE_PLATFORM_MIR_KHR 173 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 174 // Set to true if VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 175 bool waylandSurfaceExtensionEnabled; 176 #endif // VK_USE_PLATFORM_WAYLAND_KHR 177 #ifdef VK_USE_PLATFORM_WIN32_KHR 178 // Set to true if VK_KHR_WIN32_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 179 bool win32SurfaceExtensionEnabled; 180 #endif // VK_USE_PLATFORM_WIN32_KHR 181 #ifdef VK_USE_PLATFORM_XCB_KHR 182 // Set to true if VK_KHR_XCB_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 183 bool xcbSurfaceExtensionEnabled; 184 #endif // VK_USE_PLATFORM_XCB_KHR 185 #ifdef VK_USE_PLATFORM_XLIB_KHR 186 // Set to true if VK_KHR_XLIB_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 187 bool xlibSurfaceExtensionEnabled; 188 #endif // VK_USE_PLATFORM_XLIB_KHR 189 }; 190 191 // Create one of these for each VkSurfaceKHR: 192 struct SwpSurface { 193 // The actual handle for this VkSurfaceKHR: 194 VkSurfaceKHR surface; 195 196 // VkInstance that this VkSurfaceKHR is associated with: 197 SwpInstance *pInstance; 198 199 // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are 200 // remembered: 201 unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains; 202 203 // 'true' if pAllocator was non-NULL when vkCreate*SurfaceKHR was called: 204 bool usedAllocatorToCreate; 205 206 // Value of pQueueFamilyPropertyCount that was returned by the 207 // vkGetPhysicalDeviceQueueFamilyProperties() function: 208 uint32_t numQueueFamilyIndexSupport; 209 // Array of VkBool32's that is intialized by the 210 // vkGetPhysicalDeviceSurfaceSupportKHR() function. First call for a given 211 // surface allocates and initializes this array to false for all 212 // queueFamilyIndex's (and sets numQueueFamilyIndexSupport to non-zero). 213 // All calls set the entry for a given queueFamilyIndex: 214 VkBool32 *pQueueFamilyIndexSupport; 215 }; 216 217 // Create one of these for each VkPhysicalDevice within a VkInstance: 218 struct SwpPhysicalDevice { 219 // The actual handle for this VkPhysicalDevice: 220 VkPhysicalDevice physicalDevice; 221 222 // Corresponding VkDevice (and info) to this VkPhysicalDevice: 223 SwpDevice *pDevice; 224 225 // VkInstance that this VkPhysicalDevice is associated with: 226 SwpInstance *pInstance; 227 228 // Records results of vkGetPhysicalDeviceQueueFamilyProperties()'s 229 // numOfQueueFamilies parameter when pQueueFamilyProperties is NULL: 230 bool gotQueueFamilyPropertyCount; 231 uint32_t numOfQueueFamilies; 232 233 // Record all surfaces that vkGetPhysicalDeviceSurfaceSupportKHR() was 234 // called for: 235 unordered_map<VkSurfaceKHR, SwpSurface *> supportedSurfaces; 236 237 // TODO: Record/use this info per-surface, not per-device, once a 238 // non-dispatchable surface object is added to WSI: 239 // Results of vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): 240 bool gotSurfaceCapabilities; 241 VkSurfaceCapabilitiesKHR surfaceCapabilities; 242 243 // TODO: Record/use this info per-surface, not per-device, once a 244 // non-dispatchable surface object is added to WSI: 245 // Count and VkSurfaceFormatKHR's returned by vkGetPhysicalDeviceSurfaceFormatsKHR(): 246 uint32_t surfaceFormatCount; 247 VkSurfaceFormatKHR *pSurfaceFormats; 248 249 // TODO: Record/use this info per-surface, not per-device, once a 250 // non-dispatchable surface object is added to WSI: 251 // Count and VkPresentModeKHR's returned by vkGetPhysicalDeviceSurfacePresentModesKHR(): 252 uint32_t presentModeCount; 253 VkPresentModeKHR *pPresentModes; 254 }; 255 256 // Create one of these for each VkDevice within a VkInstance: 257 struct SwpDevice { 258 // The actual handle for this VkDevice: 259 VkDevice device; 260 261 // Corresponding VkPhysicalDevice (and info) to this VkDevice: 262 SwpPhysicalDevice *pPhysicalDevice; 263 264 // Set to true if VK_KHR_SWAPCHAIN_EXTENSION_NAME was enabled: 265 bool swapchainExtensionEnabled; 266 267 // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are 268 // remembered: 269 unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains; 270 271 // When vkGetDeviceQueue is called, the VkQueue's are remembered: 272 unordered_map<VkQueue, SwpQueue *> queues; 273 }; 274 275 // Create one of these for each VkImage within a VkSwapchainKHR: 276 struct SwpImage { 277 // The actual handle for this VkImage: 278 VkImage image; 279 280 // Corresponding VkSwapchainKHR (and info) to this VkImage: 281 SwpSwapchain *pSwapchain; 282 283 // true if application acquired this image from vkAcquireNextImageKHR(), 284 // and hasn't yet called vkQueuePresentKHR() for it; otherwise false: 285 bool acquiredByApp; 286 }; 287 288 // Create one of these for each VkSwapchainKHR within a VkDevice: 289 struct SwpSwapchain { 290 // The actual handle for this VkSwapchainKHR: 291 VkSwapchainKHR swapchain; 292 293 // Corresponding VkDevice (and info) to this VkSwapchainKHR: 294 SwpDevice *pDevice; 295 296 // Corresponding VkSurfaceKHR to this VkSwapchainKHR: 297 SwpSurface *pSurface; 298 299 // When vkGetSwapchainImagesKHR is called, the VkImage's are 300 // remembered: 301 uint32_t imageCount; 302 unordered_map<int, SwpImage> images; 303 304 // 'true' if pAllocator was non-NULL when vkCreateSwapchainKHR was called: 305 bool usedAllocatorToCreate; 306 }; 307 308 // Create one of these for each VkQueue within a VkDevice: 309 struct SwpQueue { 310 // The actual handle for this VkQueue: 311 VkQueue queue; 312 313 // Corresponding VkDevice (and info) to this VkSwapchainKHR: 314 SwpDevice *pDevice; 315 316 // Which queueFamilyIndex this VkQueue is associated with: 317 uint32_t queueFamilyIndex; 318 }; 319 320 struct layer_data { 321 VkInstance instance; 322 323 debug_report_data *report_data; 324 std::vector<VkDebugReportCallbackEXT> logging_callback; 325 VkLayerDispatchTable *device_dispatch_table; 326 VkLayerInstanceDispatchTable *instance_dispatch_table; 327 328 // The following are for keeping track of the temporary callbacks that can 329 // be used in vkCreateInstance and vkDestroyInstance: 330 uint32_t num_tmp_callbacks; 331 VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos; 332 VkDebugReportCallbackEXT *tmp_callbacks; 333 334 // NOTE: The following are for keeping track of info that is used for 335 // validating the WSI extensions. 336 std::unordered_map<void *, SwpInstance> instanceMap; 337 std::unordered_map<VkSurfaceKHR, SwpSurface> surfaceMap; 338 std::unordered_map<void *, SwpPhysicalDevice> physicalDeviceMap; 339 std::unordered_map<void *, SwpDevice> deviceMap; 340 std::unordered_map<VkSwapchainKHR, SwpSwapchain> swapchainMap; 341 std::unordered_map<void *, SwpQueue> queueMap; 342 343 layer_data() 344 : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), num_tmp_callbacks(0), 345 tmp_dbg_create_infos(nullptr), tmp_callbacks(nullptr){}; 346 }; 347 348 #endif // SWAPCHAIN_H 349