Home | History | Annotate | Download | only in layers
      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_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 
    290     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