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@lunarg.com> 19 * Author: Ian Elliott <ianelliott@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_LAYERS, // Called vkCreateSwapchainKHR() with a non-supported imageArrayLayers 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_APP_ACQUIRES_TOO_MANY_IMAGES, // vkAcquireNextImageKHR() asked for more images than are available 58 SWAPCHAIN_BAD_BOOL, // VkBool32 that doesn't have value of VK_TRUE or VK_FALSE (e.g. is a non-zero form of true) 59 SWAPCHAIN_PRIOR_COUNT, // Query must be called first to get value of pCount, then called second time 60 SWAPCHAIN_INVALID_COUNT, // Second time a query called, the pCount value didn't match first time 61 SWAPCHAIN_WRONG_STYPE, // The sType for a struct has the wrong value 62 SWAPCHAIN_WRONG_NEXT, // The pNext for a struct is not NULL 63 SWAPCHAIN_ZERO_VALUE, // A value should be non-zero 64 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, // A function using a queueFamilyIndex was called before 65 // vkGetPhysicalDeviceQueueFamilyProperties() was called 66 SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by 67 // vkGetPhysicalDeviceQueueFamilyProperties() 68 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, // A surface is not supported by a given queueFamilyIndex, as seen by 69 // vkGetPhysicalDeviceSurfaceSupportKHR() 70 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, // vkGetDisplayPlaneSupportedDisplaysKHR should be called after querying 71 // device display plane properties 72 SWAPCHAIN_PLANE_INDEX_TOO_LARGE, // a planeIndex value is larger than what vkGetDisplayPlaneSupportedDisplaysKHR returns 73 }; 74 75 // The following is for logging error messages: 76 const char * swapchain_layer_name = "Swapchain"; 77 78 #define LAYER_NAME (char *) "Swapchain" 79 80 // NOTE: The following struct's/typedef's are for keeping track of 81 // info that is used for validating the WSI extensions. 82 83 // Forward declarations: 84 struct SwpInstance; 85 struct SwpSurface; 86 struct SwpPhysicalDevice; 87 struct SwpDevice; 88 struct SwpSwapchain; 89 struct SwpImage; 90 struct SwpQueue; 91 92 // Create one of these for each VkInstance: 93 struct SwpInstance { 94 // The actual handle for this VkInstance: 95 VkInstance instance; 96 97 // Remember the VkSurfaceKHR's that are created for this VkInstance: 98 unordered_map<VkSurfaceKHR, SwpSurface *> surfaces; 99 100 // When vkEnumeratePhysicalDevices is called, the VkPhysicalDevice's are 101 // remembered: 102 unordered_map<const void *, SwpPhysicalDevice *> physicalDevices; 103 104 // Set to true if VK_KHR_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 105 bool surfaceExtensionEnabled; 106 107 // Set to true if VK_KHR_DISPLAY_EXTENSION_NAME was enabled for this VkInstance: 108 bool displayExtensionEnabled; 109 110 // TODO: Add additional booleans for platform-specific extensions: 111 #ifdef VK_USE_PLATFORM_ANDROID_KHR 112 // Set to true if VK_KHR_ANDROID_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 113 bool androidSurfaceExtensionEnabled; 114 #endif // VK_USE_PLATFORM_ANDROID_KHR 115 #ifdef VK_USE_PLATFORM_MIR_KHR 116 // Set to true if VK_KHR_MIR_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 117 bool mirSurfaceExtensionEnabled; 118 #endif // VK_USE_PLATFORM_MIR_KHR 119 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 120 // Set to true if VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 121 bool waylandSurfaceExtensionEnabled; 122 #endif // VK_USE_PLATFORM_WAYLAND_KHR 123 #ifdef VK_USE_PLATFORM_WIN32_KHR 124 // Set to true if VK_KHR_WIN32_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 125 bool win32SurfaceExtensionEnabled; 126 #endif // VK_USE_PLATFORM_WIN32_KHR 127 #ifdef VK_USE_PLATFORM_XCB_KHR 128 // Set to true if VK_KHR_XCB_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 129 bool xcbSurfaceExtensionEnabled; 130 #endif // VK_USE_PLATFORM_XCB_KHR 131 #ifdef VK_USE_PLATFORM_XLIB_KHR 132 // Set to true if VK_KHR_XLIB_SURFACE_EXTENSION_NAME was enabled for this VkInstance: 133 bool xlibSurfaceExtensionEnabled; 134 #endif // VK_USE_PLATFORM_XLIB_KHR 135 }; 136 137 // Create one of these for each VkSurfaceKHR: 138 struct SwpSurface { 139 // The actual handle for this VkSurfaceKHR: 140 VkSurfaceKHR surface; 141 142 // VkInstance that this VkSurfaceKHR is associated with: 143 SwpInstance *pInstance; 144 145 // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are 146 // remembered: 147 unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains; 148 149 // Value of pQueueFamilyPropertyCount that was returned by the 150 // vkGetPhysicalDeviceQueueFamilyProperties() function: 151 uint32_t numQueueFamilyIndexSupport; 152 // Array of VkBool32's that is intialized by the 153 // vkGetPhysicalDeviceSurfaceSupportKHR() function. First call for a given 154 // surface allocates and initializes this array to false for all 155 // queueFamilyIndex's (and sets numQueueFamilyIndexSupport to non-zero). 156 // All calls set the entry for a given queueFamilyIndex: 157 VkBool32 *pQueueFamilyIndexSupport; 158 }; 159 160 // Create one of these for each VkPhysicalDevice within a VkInstance: 161 struct SwpPhysicalDevice { 162 // The actual handle for this VkPhysicalDevice: 163 VkPhysicalDevice physicalDevice; 164 165 // Corresponding VkDevice (and info) to this VkPhysicalDevice: 166 SwpDevice *pDevice; 167 168 // VkInstance that this VkPhysicalDevice is associated with: 169 SwpInstance *pInstance; 170 171 // Records results of vkGetPhysicalDeviceQueueFamilyProperties()'s 172 // numOfQueueFamilies parameter when pQueueFamilyProperties is NULL: 173 bool gotQueueFamilyPropertyCount; 174 uint32_t numOfQueueFamilies; 175 176 // Record all surfaces that vkGetPhysicalDeviceSurfaceSupportKHR() was 177 // called for: 178 unordered_map<VkSurfaceKHR, SwpSurface *> supportedSurfaces; 179 180 // TODO: Record/use this info per-surface, not per-device, once a 181 // non-dispatchable surface object is added to WSI: 182 // Results of vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): 183 bool gotSurfaceCapabilities; 184 VkSurfaceCapabilitiesKHR surfaceCapabilities; 185 186 // TODO: Record/use this info per-surface, not per-device, once a 187 // non-dispatchable surface object is added to WSI: 188 // Count and VkSurfaceFormatKHR's returned by vkGetPhysicalDeviceSurfaceFormatsKHR(): 189 uint32_t surfaceFormatCount; 190 VkSurfaceFormatKHR *pSurfaceFormats; 191 192 // TODO: Record/use this info per-surface, not per-device, once a 193 // non-dispatchable surface object is added to WSI: 194 // Count and VkPresentModeKHR's returned by vkGetPhysicalDeviceSurfacePresentModesKHR(): 195 uint32_t presentModeCount; 196 VkPresentModeKHR *pPresentModes; 197 198 // Count returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR(): 199 uint32_t displayPlanePropertyCount; 200 bool gotDisplayPlanePropertyCount; 201 }; 202 203 // Create one of these for each VkDevice within a VkInstance: 204 struct SwpDevice { 205 // The actual handle for this VkDevice: 206 VkDevice device; 207 208 // Corresponding VkPhysicalDevice (and info) to this VkDevice: 209 SwpPhysicalDevice *pPhysicalDevice; 210 211 // Set to true if VK_KHR_SWAPCHAIN_EXTENSION_NAME was enabled: 212 bool swapchainExtensionEnabled; 213 214 // Set to true if VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME was enabled: 215 bool displaySwapchainExtensionEnabled; 216 217 // When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are 218 // remembered: 219 unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains; 220 221 // When vkGetDeviceQueue is called, the VkQueue's are remembered: 222 unordered_map<VkQueue, SwpQueue *> queues; 223 }; 224 225 // Create one of these for each VkImage within a VkSwapchainKHR: 226 struct SwpImage { 227 // The actual handle for this VkImage: 228 VkImage image; 229 230 // Corresponding VkSwapchainKHR (and info) to this VkImage: 231 SwpSwapchain *pSwapchain; 232 233 // true if application acquired this image from vkAcquireNextImageKHR(), 234 // and hasn't yet called vkQueuePresentKHR() for it; otherwise false: 235 bool acquiredByApp; 236 }; 237 238 // Create one of these for each VkSwapchainKHR within a VkDevice: 239 struct SwpSwapchain { 240 // The actual handle for this VkSwapchainKHR: 241 VkSwapchainKHR swapchain; 242 243 // Corresponding VkDevice (and info) to this VkSwapchainKHR: 244 SwpDevice *pDevice; 245 246 // Corresponding VkSurfaceKHR to this VkSwapchainKHR: 247 SwpSurface *pSurface; 248 249 // When vkGetSwapchainImagesKHR is called, the VkImage's are 250 // remembered: 251 uint32_t imageCount; 252 unordered_map<int, SwpImage> images; 253 }; 254 255 // Create one of these for each VkQueue within a VkDevice: 256 struct SwpQueue { 257 // The actual handle for this VkQueue: 258 VkQueue queue; 259 260 // Corresponding VkDevice (and info) to this VkSwapchainKHR: 261 SwpDevice *pDevice; 262 263 // Which queueFamilyIndex this VkQueue is associated with: 264 uint32_t queueFamilyIndex; 265 }; 266 267 struct layer_data { 268 VkInstance instance; 269 270 debug_report_data *report_data; 271 std::vector<VkDebugReportCallbackEXT> logging_callback; 272 VkLayerDispatchTable *device_dispatch_table; 273 VkLayerInstanceDispatchTable *instance_dispatch_table; 274 275 // The following are for keeping track of the temporary callbacks that can 276 // be used in vkCreateInstance and vkDestroyInstance: 277 uint32_t num_tmp_callbacks; 278 VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos; 279 VkDebugReportCallbackEXT *tmp_callbacks; 280 281 // NOTE: The following are for keeping track of info that is used for 282 // validating the WSI extensions. 283 std::unordered_map<void *, SwpInstance> instanceMap; 284 std::unordered_map<VkSurfaceKHR, SwpSurface> surfaceMap; 285 std::unordered_map<void *, SwpPhysicalDevice> physicalDeviceMap; 286 std::unordered_map<void *, SwpDevice> deviceMap; 287 std::unordered_map<VkSwapchainKHR, SwpSwapchain> swapchainMap; 288 std::unordered_map<void *, SwpQueue> queueMap; 289 layer_datalayer_data290 layer_data() 291 : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), num_tmp_callbacks(0), 292 tmp_dbg_create_infos(nullptr), tmp_callbacks(nullptr){}; 293 }; 294 295 #endif // SWAPCHAIN_H 296