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  * 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 (at) lunarg.com>
     26  * Author: Ian Elliott <ianelliott (at) 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 
    343     layer_data() : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr){};
    344 };
    345 
    346 #endif // SWAPCHAIN_H
    347