• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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