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 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials 11 * are furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included 14 * in all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS 24 * 25 * Author: Ian Elliott <ian@lunarg.com> 26 * Author: Ian Elliott <ianelliott@google.com> 27 */ 28 29 #ifndef SWAPCHAIN_H 30 #define SWAPCHAIN_H 31 32 #include "vulkan/vk_layer.h" 33 #include "vk_layer_config.h" 34 #include "vk_layer_logging.h" 35 #include <vector> 36 #include <unordered_map> 37 38 using namespace std; 39 40 // Swapchain ERROR codes 41 typedef enum _SWAPCHAIN_ERROR { 42 SWAPCHAIN_INVALID_HANDLE, // Handle used that isn't currently valid 43 SWAPCHAIN_NULL_POINTER, // Pointer set to NULL, instead of being a valid pointer 44 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, // Did not enable WSI extension, but called WSI function 45 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, // Called vkDestroyDevice() before vkDestroySwapchainKHR() 46 SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, // Called vkCreateSwapchainKHR() with a pCreateInfo->surface that wasn't seen as supported 47 // by vkGetPhysicalDeviceSurfaceSupportKHR for the device 48 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, // Called vkCreateSwapchainKHR() without calling a query (e.g. 49 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR()) 50 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, // Called vkCreateSwapchainKHR() with out-of-bounds minImageCount 51 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS, // Called vkCreateSwapchainKHR() with out-of-bounds imageExtent 52 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, // Called vkCreateSwapchainKHR() with imageExtent that doesn't match window's extent 53 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, // Called vkCreateSwapchainKHR() with a non-supported preTransform 54 SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, // Called vkCreateSwapchainKHR() with a non-supported compositeAlpha 55 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, // Called vkCreateSwapchainKHR() with a non-supported imageArraySize 56 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, // Called vkCreateSwapchainKHR() with a non-supported imageUsageFlags 57 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace 58 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, // Called vkCreateSwapchainKHR() with a non-supported imageFormat 59 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace 60 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, // Called vkCreateSwapchainKHR() with a non-supported presentMode 61 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE, // Called vkCreateSwapchainKHR() with a non-supported imageSharingMode 62 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, // Called vkCreateSwapchainKHR() with bad values when imageSharingMode is 63 // VK_SHARING_MODE_CONCURRENT 64 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, // Called vkCreateSwapchainKHR() with pCreateInfo->oldSwapchain that has a different surface 65 // than pCreateInfo->surface 66 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, // Called vkDestroySwapchainKHR() with a different VkDevice than vkCreateSwapchainKHR() 67 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES, // vkAcquireNextImageKHR() asked for more images than are available 68 SWAPCHAIN_INDEX_TOO_LARGE, // Index is too large for swapchain 69 SWAPCHAIN_INDEX_NOT_IN_USE, // vkQueuePresentKHR() given index that is not owned by app 70 SWAPCHAIN_BAD_BOOL, // VkBool32 that doesn't have value of VK_TRUE or VK_FALSE (e.g. is a non-zero form of true) 71 SWAPCHAIN_INVALID_COUNT, // Second time a query called, the pCount value didn't match first time 72 SWAPCHAIN_WRONG_STYPE, // The sType for a struct has the wrong value 73 SWAPCHAIN_WRONG_NEXT, // The pNext for a struct is not NULL 74 SWAPCHAIN_ZERO_VALUE, // A value should be non-zero 75 SWAPCHAIN_INCOMPATIBLE_ALLOCATOR, // pAllocator must be compatible (i.e. NULL or not) when object is created and destroyed 76 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, // A function using a queueFamilyIndex was called before 77 // vkGetPhysicalDeviceQueueFamilyProperties() was called 78 SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by 79 // vkGetPhysicalDeviceQueueFamilyProperties() 80 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, // A surface is not supported by a given queueFamilyIndex, as seen by 81 // vkGetPhysicalDeviceSurfaceSupportKHR() 82 SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, // vkAcquireNextImageKHR should be called with a valid semaphore and/or fence 83 } SWAPCHAIN_ERROR; 84 85 // The following is for logging error messages: 86 #define LAYER_NAME (char *) "Swapchain" 87 #define LOG_ERROR_NON_VALID_OBJ(objType, type, obj) \ 88 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), __LINE__, \ 89 SWAPCHAIN_INVALID_HANDLE, LAYER_NAME, "%s() called with a non-valid %s.", __FUNCTION__, (obj)) \ 90 : VK_FALSE 91 #define LOG_ERROR_NULL_POINTER(objType, type, obj) \ 92 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 93 SWAPCHAIN_NULL_POINTER, LAYER_NAME, "%s() called with NULL pointer %s.", __FUNCTION__, (obj)) \ 94 : VK_FALSE 95 #define LOG_ERROR_INVALID_COUNT(objType, type, obj, obj2, val, val2) \ 96 (my_data) ? log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (objType), (uint64_t)(obj), 0, \ 97 SWAPCHAIN_INVALID_COUNT, LAYER_NAME, "%s() called with non-NULL %s, and with %s set to a " \ 98 "value (%d) that is greater than the value (%d) that " \ 99 "was returned when %s was NULL.", \ 100 __FUNCTION__, (obj2), (obj), (val), (val2), (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 typedef _SwpInstance SwpInstance; 150 typedef _SwpSurface SwpSurface; 151 ; 152 typedef _SwpPhysicalDevice SwpPhysicalDevice; 153 typedef _SwpDevice SwpDevice; 154 typedef _SwpSwapchain SwpSwapchain; 155 typedef _SwpImage SwpImage; 156 typedef _SwpQueue SwpQueue; 157 158 // Create one of these for each VkInstance: 159 struct _SwpInstance { 160 // The actual handle for this VkInstance: 161 VkInstance instance; 162 163 // Remember the VkSurfaceKHR's that are created for this VkInstance: 164 unordered_map<VkSurfaceKHR, SwpSurface *> surfaces; 165 166 // When vkEnumeratePhysicalDevices is called, the VkPhysicalDevice's are 167 // remembered: 168 unordered_map<const void *, SwpPhysicalDevice *> physicalDevices; 169 170 // Set to true if VK_KHR_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 171 bool surfaceExtensionEnabled; 172 173 // TODO: Add additional booleans for platform-specific extensions: 174 #ifdef VK_USE_PLATFORM_ANDROID_KHR 175 // Set to true if VK_KHR_ANDROID_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 176 bool androidSurfaceExtensionEnabled; 177 #endif // VK_USE_PLATFORM_ANDROID_KHR 178 #ifdef VK_USE_PLATFORM_MIR_KHR 179 // Set to true if VK_KHR_MIR_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 180 bool mirSurfaceExtensionEnabled; 181 #endif // VK_USE_PLATFORM_MIR_KHR 182 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 183 // Set to true if VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 184 bool waylandSurfaceExtensionEnabled; 185 #endif // VK_USE_PLATFORM_WAYLAND_KHR 186 #ifdef VK_USE_PLATFORM_WIN32_KHR 187 // Set to true if VK_KHR_WIN32_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 188 bool win32SurfaceExtensionEnabled; 189 #endif // VK_USE_PLATFORM_WIN32_KHR 190 #ifdef VK_USE_PLATFORM_XCB_KHR 191 // Set to true if VK_KHR_XCB_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 192 bool xcbSurfaceExtensionEnabled; 193 #endif // VK_USE_PLATFORM_XCB_KHR 194 #ifdef VK_USE_PLATFORM_XLIB_KHR 195 // Set to true if VK_KHR_XLIB_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 196 bool xlibSurfaceExtensionEnabled; 197 #endif // VK_USE_PLATFORM_XLIB_KHR 198 }; 199 200 // Create one of these for each VkSurfaceKHR: 201 struct _SwpSurface { 202 // The actual handle for this VkSurfaceKHR: 203 VkSurfaceKHR surface; 204 205 // VkInstance that this VkSurfaceKHR is associated with: 206 SwpInstance *pInstance; 207 208 // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are 209 // remembered: 210 unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains; 211 212 // 'true' if pAllocator was non-NULL when vkCreate*SurfaceKHR was called: 213 bool usedAllocatorToCreate; 214 215 // Value of pQueueFamilyPropertyCount that was returned by the 216 // vkGetPhysicalDeviceQueueFamilyProperties() function: 217 uint32_t numQueueFamilyIndexSupport; 218 // Array of VkBool32's that is intialized by the 219 // vkGetPhysicalDeviceSurfaceSupportKHR() function. First call for a given 220 // surface allocates and initializes this array to false for all 221 // queueFamilyIndex's (and sets numQueueFamilyIndexSupport to non-zero). 222 // All calls set the entry for a given queueFamilyIndex: 223 VkBool32 *pQueueFamilyIndexSupport; 224 }; 225 226 // Create one of these for each VkPhysicalDevice within a VkInstance: 227 struct _SwpPhysicalDevice { 228 // The actual handle for this VkPhysicalDevice: 229 VkPhysicalDevice physicalDevice; 230 231 // Corresponding VkDevice (and info) to this VkPhysicalDevice: 232 SwpDevice *pDevice; 233 234 // VkInstance that this VkPhysicalDevice is associated with: 235 SwpInstance *pInstance; 236 237 // Records results of vkGetPhysicalDeviceQueueFamilyProperties()'s 238 // numOfQueueFamilies parameter when pQueueFamilyProperties is NULL: 239 bool gotQueueFamilyPropertyCount; 240 uint32_t numOfQueueFamilies; 241 242 // Record all surfaces that vkGetPhysicalDeviceSurfaceSupportKHR() was 243 // called for: 244 unordered_map<VkSurfaceKHR, SwpSurface *> supportedSurfaces; 245 246 // TODO: Record/use this info per-surface, not per-device, once a 247 // non-dispatchable surface object is added to WSI: 248 // Results of vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): 249 bool gotSurfaceCapabilities; 250 VkSurfaceCapabilitiesKHR surfaceCapabilities; 251 252 // TODO: Record/use this info per-surface, not per-device, once a 253 // non-dispatchable surface object is added to WSI: 254 // Count and VkSurfaceFormatKHR's returned by vkGetPhysicalDeviceSurfaceFormatsKHR(): 255 uint32_t surfaceFormatCount; 256 VkSurfaceFormatKHR *pSurfaceFormats; 257 258 // TODO: Record/use this info per-surface, not per-device, once a 259 // non-dispatchable surface object is added to WSI: 260 // Count and VkPresentModeKHR's returned by vkGetPhysicalDeviceSurfacePresentModesKHR(): 261 uint32_t presentModeCount; 262 VkPresentModeKHR *pPresentModes; 263 }; 264 265 // Create one of these for each VkDevice within a VkInstance: 266 struct _SwpDevice { 267 // The actual handle for this VkDevice: 268 VkDevice device; 269 270 // Corresponding VkPhysicalDevice (and info) to this VkDevice: 271 SwpPhysicalDevice *pPhysicalDevice; 272 273 // Set to true if VK_KHR_SWAPCHAIN_EXTENSION_NAME was enabled: 274 bool swapchainExtensionEnabled; 275 276 // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are 277 // remembered: 278 unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains; 279 280 // When vkGetDeviceQueue is called, the VkQueue's are remembered: 281 unordered_map<VkQueue, SwpQueue *> queues; 282 }; 283 284 // Create one of these for each VkImage within a VkSwapchainKHR: 285 struct _SwpImage { 286 // The actual handle for this VkImage: 287 VkImage image; 288 289 // Corresponding VkSwapchainKHR (and info) to this VkImage: 290 SwpSwapchain *pSwapchain; 291 292 // true if application got this image from vkAcquireNextImageKHR(), and 293 // hasn't yet called vkQueuePresentKHR() for it; otherwise false: 294 bool ownedByApp; 295 }; 296 297 // Create one of these for each VkSwapchainKHR within a VkDevice: 298 struct _SwpSwapchain { 299 // The actual handle for this VkSwapchainKHR: 300 VkSwapchainKHR swapchain; 301 302 // Corresponding VkDevice (and info) to this VkSwapchainKHR: 303 SwpDevice *pDevice; 304 305 // Corresponding VkSurfaceKHR to this VkSwapchainKHR: 306 SwpSurface *pSurface; 307 308 // When vkGetSwapchainImagesKHR is called, the VkImage's are 309 // remembered: 310 uint32_t imageCount; 311 unordered_map<int, SwpImage> images; 312 313 // 'true' if pAllocator was non-NULL when vkCreateSwapchainKHR was called: 314 bool usedAllocatorToCreate; 315 }; 316 317 // Create one of these for each VkQueue within a VkDevice: 318 struct _SwpQueue { 319 // The actual handle for this VkQueue: 320 VkQueue queue; 321 322 // Corresponding VkDevice (and info) to this VkSwapchainKHR: 323 SwpDevice *pDevice; 324 325 // Which queueFamilyIndex this VkQueue is associated with: 326 uint32_t queueFamilyIndex; 327 }; 328 329 struct layer_data { 330 debug_report_data *report_data; 331 std::vector<VkDebugReportCallbackEXT> logging_callback; 332 VkLayerDispatchTable *device_dispatch_table; 333 VkLayerInstanceDispatchTable *instance_dispatch_table; 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 layer_datalayer_data343 layer_data() : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr){}; 344 }; 345 346 #endif // SWAPCHAIN_H 347