• 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 #include <mutex>
23 #include <stdio.h>
24 #include <string.h>
25 #include <vk_loader_platform.h>
26 #include <vulkan/vk_icd.h>
27 #include "swapchain.h"
28 #include "vk_layer_extension_utils.h"
29 #include "vk_enum_string_helper.h"
30 #include "vk_layer_utils.h"
31 
32 namespace swapchain {
33 
34 static std::mutex global_lock;
35 
36 // The following is for logging error messages:
37 static std::unordered_map<void *, layer_data *> layer_data_map;
38 
39 static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
40 
41 static const VkLayerProperties swapchain_layer = {
42     "VK_LAYER_LUNARG_swapchain", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
43 };
44 
checkDeviceRegisterExtensions(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,VkDevice device)45 static void checkDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
46     uint32_t i;
47     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
48     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
49 
50     SwpPhysicalDevice *pPhysicalDevice = NULL;
51     {
52         auto it = my_instance_data->physicalDeviceMap.find(physicalDevice);
53         pPhysicalDevice = (it == my_instance_data->physicalDeviceMap.end()) ? NULL : &it->second;
54     }
55     if (pPhysicalDevice) {
56         my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
57         pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
58     } else {
59         // TBD: Should we leave error in (since Swapchain really needs this
60         // link)?
61         log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
62                 reinterpret_cast<uint64_t>(physicalDevice), __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
63                 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
64     }
65     my_device_data->deviceMap[device].device = device;
66     my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
67     my_device_data->deviceMap[device].displaySwapchainExtensionEnabled = false;
68 
69     // Record whether the WSI device extension was enabled for this VkDevice.
70     // No need to check if the extension was advertised by
71     // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
72     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
73         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
74             my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
75         }
76         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) {
77             my_device_data->deviceMap[device].displaySwapchainExtensionEnabled = true;
78         }
79     }
80 }
81 
checkInstanceRegisterExtensions(const VkInstanceCreateInfo * pCreateInfo,VkInstance instance)82 static void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
83     uint32_t i;
84     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
85 
86     // Remember this instance, and whether the VK_KHR_surface extension
87     // was enabled for it:
88     my_data->instanceMap[instance].instance = instance;
89     my_data->instanceMap[instance].surfaceExtensionEnabled = false;
90     my_data->instanceMap[instance].displayExtensionEnabled = false;
91 #ifdef VK_USE_PLATFORM_ANDROID_KHR
92     my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
93 #endif // VK_USE_PLATFORM_ANDROID_KHR
94 #ifdef VK_USE_PLATFORM_MIR_KHR
95     my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
96 #endif // VK_USE_PLATFORM_MIR_KHR
97 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
98     my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
99 #endif // VK_USE_PLATFORM_WAYLAND_KHR
100 #ifdef VK_USE_PLATFORM_WIN32_KHR
101     my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
102 #endif // VK_USE_PLATFORM_WIN32_KHR
103 #ifdef VK_USE_PLATFORM_XCB_KHR
104     my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
105 #endif // VK_USE_PLATFORM_XCB_KHR
106 #ifdef VK_USE_PLATFORM_XLIB_KHR
107     my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
108 #endif // VK_USE_PLATFORM_XLIB_KHR
109 
110     // Look for one or more debug report create info structures, and copy the
111     // callback(s) for each one found (for use by vkDestroyInstance)
112     layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos,
113                              &my_data->tmp_callbacks);
114 
115     // Record whether the WSI instance extension was enabled for this
116     // VkInstance.  No need to check if the extension was advertised by
117     // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
118     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
119         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
120 
121             my_data->instanceMap[instance].surfaceExtensionEnabled = true;
122         }
123         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
124 
125             my_data->instanceMap[instance].displayExtensionEnabled = true;
126         }
127 #ifdef VK_USE_PLATFORM_ANDROID_KHR
128         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
129 
130             my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
131         }
132 #endif // VK_USE_PLATFORM_ANDROID_KHR
133 #ifdef VK_USE_PLATFORM_MIR_KHR
134         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
135 
136             my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
137         }
138 #endif // VK_USE_PLATFORM_MIR_KHR
139 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
140         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
141 
142             my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
143         }
144 #endif // VK_USE_PLATFORM_WAYLAND_KHR
145 #ifdef VK_USE_PLATFORM_WIN32_KHR
146         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
147 
148             my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
149         }
150 #endif // VK_USE_PLATFORM_WIN32_KHR
151 #ifdef VK_USE_PLATFORM_XCB_KHR
152         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
153 
154             my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
155         }
156 #endif // VK_USE_PLATFORM_XCB_KHR
157 #ifdef VK_USE_PLATFORM_XLIB_KHR
158         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
159 
160             my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
161         }
162 #endif // VK_USE_PLATFORM_XLIB_KHR
163     }
164 }
165 
166 #include "vk_dispatch_table_helper.h"
init_swapchain(layer_data * my_data,const VkAllocationCallbacks * pAllocator)167 static void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
168 
169     layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain");
170 }
171 
surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)172 static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) {
173     // Return a string corresponding to the value:
174     return string_VkSurfaceTransformFlagBitsKHR(value);
175 }
176 
surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value)177 static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) {
178     // Return a string corresponding to the value:
179     return string_VkCompositeAlphaFlagBitsKHR(value);
180 }
181 
presentModeStr(VkPresentModeKHR value)182 static const char *presentModeStr(VkPresentModeKHR value) {
183     // Return a string corresponding to the value:
184     return string_VkPresentModeKHR(value);
185 }
186 
sharingModeStr(VkSharingMode value)187 static const char *sharingModeStr(VkSharingMode value) {
188     // Return a string corresponding to the value:
189     return string_VkSharingMode(value);
190 }
191 
ValidateQueueFamilyIndex(layer_data * my_data,uint32_t queue_family_index,uint32_t queue_family_count,VkPhysicalDevice physical_device,const char * function)192 static bool ValidateQueueFamilyIndex(layer_data *my_data, uint32_t queue_family_index, uint32_t queue_family_count,
193                                      VkPhysicalDevice physical_device, const char *function) {
194     bool skip_call = false;
195     if (queue_family_index >= queue_family_count) {
196         skip_call = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
197                             reinterpret_cast<uint64_t>(physical_device), __LINE__, SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE,
198                             swapchain_layer_name,
199                             "%s() called with a queueFamilyIndex that is too large (i.e. %d).  The maximum value (returned by "
200                             "vkGetPhysicalDeviceQueueFamilyProperties) is only %d.",
201                             function, queue_family_index, queue_family_count);
202     }
203     return skip_call;
204 }
205 
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)206 VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
207                                               VkInstance *pInstance) {
208     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
209 
210     assert(chain_info->u.pLayerInfo);
211     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
212     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
213     if (fpCreateInstance == NULL) {
214         return VK_ERROR_INITIALIZATION_FAILED;
215     }
216 
217     // Advance the link info for the next element on the chain
218     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
219 
220     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
221     if (result != VK_SUCCESS) {
222         return result;
223     }
224 
225     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
226     my_data->instance = *pInstance;
227     my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
228     layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
229 
230     my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
231                                                         pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
232 
233     // Call the following function after my_data is initialized:
234     checkInstanceRegisterExtensions(pCreateInfo, *pInstance);
235     init_swapchain(my_data, pAllocator);
236 
237     return result;
238 }
239 
DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)240 VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
241     dispatch_key key = get_dispatch_key(instance);
242     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
243     SwpInstance *pInstance = NULL;
244     {
245         auto it = my_data->instanceMap.find(instance);
246         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
247     }
248 
249     // Call down the call chain:
250     my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
251 
252     std::lock_guard<std::mutex> lock(global_lock);
253 
254     // Enable the temporary callback(s) here to catch cleanup issues:
255     bool callback_setup = false;
256     if (my_data->num_tmp_callbacks > 0) {
257         if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos,
258                                         my_data->tmp_callbacks)) {
259             callback_setup = true;
260         }
261     }
262 
263     // Do additional internal cleanup:
264     if (pInstance) {
265         // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
266         // SwpInstance associated with this instance:
267         for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.end(); it++) {
268 
269             // Free memory that was allocated for/by this SwpPhysicalDevice:
270             SwpPhysicalDevice *pPhysicalDevice = it->second;
271             if (pPhysicalDevice) {
272                 if (pPhysicalDevice->pDevice) {
273                     log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
274                             reinterpret_cast<uint64_t>(pPhysicalDevice->pDevice->device), __LINE__,
275                             SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, swapchain_layer_name,
276                             "VkDestroyInstance() called before all of its associated VkDevices were destroyed.");
277                 }
278                 free(pPhysicalDevice->pSurfaceFormats);
279                 free(pPhysicalDevice->pPresentModes);
280             }
281 
282             // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
283             // are simply pointed to by the SwpInstance):
284             my_data->physicalDeviceMap.erase(it->second->physicalDevice);
285         }
286         for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) {
287 
288             // Free memory that was allocated for/by this SwpPhysicalDevice:
289             SwpSurface *pSurface = it->second;
290             if (pSurface) {
291                 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
292                         reinterpret_cast<uint64_t>(pInstance->instance), __LINE__, SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
293                         swapchain_layer_name,
294                         "VkDestroyInstance() called before all of its associated VkSurfaceKHRs were destroyed.");
295             }
296         }
297         my_data->instanceMap.erase(instance);
298     }
299 
300     // Disable and cleanup the temporary callback(s):
301     if (callback_setup) {
302         layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks);
303     }
304     if (my_data->num_tmp_callbacks > 0) {
305         layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks);
306         my_data->num_tmp_callbacks = 0;
307     }
308 
309     // Clean up logging callback, if any
310     while (my_data->logging_callback.size() > 0) {
311         VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
312         layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
313         my_data->logging_callback.pop_back();
314     }
315     layer_debug_report_destroy_instance(my_data->report_data);
316 
317     delete my_data->instance_dispatch_table;
318     layer_data_map.erase(key);
319 }
320 
GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties * pQueueFamilyProperties)321 VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
322                                                                   uint32_t *pQueueFamilyPropertyCount,
323                                                                   VkQueueFamilyProperties *pQueueFamilyProperties) {
324     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
325 
326     // Call down the call chain:
327     my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
328                                                                              pQueueFamilyProperties);
329 
330     // Record the result of this query:
331     std::lock_guard<std::mutex> lock(global_lock);
332     SwpPhysicalDevice *pPhysicalDevice = NULL;
333     {
334         auto it = my_data->physicalDeviceMap.find(physicalDevice);
335         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
336     }
337     // Note: for poorly-written applications (e.g. that don't call this command
338     // twice, the first time with pQueueFamilyProperties set to NULL, and the
339     // second time with a non-NULL pQueueFamilyProperties and with the same
340     // count as returned the first time), record the count when
341     // pQueueFamilyProperties is non-NULL:
342     if (pPhysicalDevice && pQueueFamilyPropertyCount && pQueueFamilyProperties) {
343         pPhysicalDevice->gotQueueFamilyPropertyCount = true;
344         pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
345     }
346 }
347 
348 #ifdef VK_USE_PLATFORM_ANDROID_KHR
CreateAndroidSurfaceKHR(VkInstance instance,const VkAndroidSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)349 VKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
350                                                        const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
351     VkResult result = VK_SUCCESS;
352     bool skip_call = false;
353     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
354     std::unique_lock<std::mutex> lock(global_lock);
355     SwpInstance *pInstance = NULL;
356     {
357         auto it = my_data->instanceMap.find(instance);
358         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
359     }
360 
361     // Validate that the platform extension was enabled:
362     if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
363         skip_call |=
364             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
365                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
366                     "vkCreateAndroidSurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
367                     VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
368     }
369     lock.unlock();
370 
371     if (!skip_call) {
372         // Call down the call chain:
373         result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
374         lock.lock();
375 
376         // Obtain this pointer again after locking:
377         {
378             auto it = my_data->instanceMap.find(instance);
379             pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
380         }
381         if ((result == VK_SUCCESS) && pInstance && pSurface) {
382             // Record the VkSurfaceKHR returned by the ICD:
383             my_data->surfaceMap[*pSurface].surface = *pSurface;
384             my_data->surfaceMap[*pSurface].pInstance = pInstance;
385             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
386             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
387             // Point to the associated SwpInstance:
388             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
389         }
390         lock.unlock();
391 
392         return result;
393     }
394     return VK_ERROR_VALIDATION_FAILED_EXT;
395 }
396 #endif // VK_USE_PLATFORM_ANDROID_KHR
397 
398 #ifdef VK_USE_PLATFORM_MIR_KHR
CreateMirSurfaceKHR(VkInstance instance,const VkMirSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)399 VKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
400                                                    const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
401     VkResult result = VK_SUCCESS;
402     bool skip_call = false;
403     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
404     std::unique_lock<std::mutex> lock(global_lock);
405     SwpInstance *pInstance = NULL;
406     {
407         auto it = my_data->instanceMap.find(instance);
408         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
409     }
410 
411     // Validate that the platform extension was enabled:
412     if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
413         skip_call |=
414             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
415                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
416                     "vkCreateMirSurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
417                     VK_KHR_MIR_SURFACE_EXTENSION_NAME);
418     }
419     lock.unlock();
420 
421     if (!skip_call) {
422         // Call down the call chain:
423         result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
424         lock.lock();
425 
426         // Obtain this pointer again after locking:
427         {
428             auto it = my_data->instanceMap.find(instance);
429             pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
430         }
431         if ((result == VK_SUCCESS) && pInstance && pSurface) {
432             // Record the VkSurfaceKHR returned by the ICD:
433             my_data->surfaceMap[*pSurface].surface = *pSurface;
434             my_data->surfaceMap[*pSurface].pInstance = pInstance;
435             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
436             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
437             // Point to the associated SwpInstance:
438             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
439         }
440         lock.unlock();
441 
442         return result;
443     }
444     return VK_ERROR_VALIDATION_FAILED_EXT;
445 }
446 
GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,MirConnection * connection)447 VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
448                                                                           uint32_t queueFamilyIndex, MirConnection *connection) {
449     VkBool32 result = VK_FALSE;
450     bool skip_call = false;
451     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
452     std::unique_lock<std::mutex> lock(global_lock);
453     SwpPhysicalDevice *pPhysicalDevice = NULL;
454     {
455         auto it = my_data->physicalDeviceMap.find(physicalDevice);
456         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
457     }
458 
459     // Validate that the platform extension was enabled:
460     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
461         skip_call |=
462             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
463                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
464                     swapchain_layer_name, "vkGetPhysicalDeviceMirPresentationSupportKHR() called even though the %s "
465                                           "extension was not enabled for this VkInstance.",
466                     VK_KHR_MIR_SURFACE_EXTENSION_NAME);
467     }
468     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
469         skip_call |= ValidateQueueFamilyIndex(my_data, queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies,
470                                               pPhysicalDevice->physicalDevice, "vkGetPhysicalDeviceMirPresentationSupportKHR");
471     }
472     lock.unlock();
473 
474     if (!skip_call) {
475         // Call down the call chain:
476         result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
477                                                                                               connection);
478     }
479     return result;
480 }
481 #endif // VK_USE_PLATFORM_MIR_KHR
482 
483 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
CreateWaylandSurfaceKHR(VkInstance instance,const VkWaylandSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)484 VKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
485                                                        const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
486     VkResult result = VK_SUCCESS;
487     bool skip_call = false;
488     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
489     std::unique_lock<std::mutex> lock(global_lock);
490     SwpInstance *pInstance = NULL;
491     {
492         auto it = my_data->instanceMap.find(instance);
493         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
494     }
495 
496     // Validate that the platform extension was enabled:
497     if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
498         skip_call |=
499             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
500                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
501                     "vkCreateWaylandSurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
502                     VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
503     }
504     lock.unlock();
505 
506     if (!skip_call) {
507         // Call down the call chain:
508         result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
509         lock.lock();
510 
511         // Obtain this pointer again after locking:
512         {
513             auto it = my_data->instanceMap.find(instance);
514             pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
515         }
516         if ((result == VK_SUCCESS) && pInstance && pSurface) {
517             // Record the VkSurfaceKHR returned by the ICD:
518             my_data->surfaceMap[*pSurface].surface = *pSurface;
519             my_data->surfaceMap[*pSurface].pInstance = pInstance;
520             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
521             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
522             // Point to the associated SwpInstance:
523             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
524         }
525         lock.unlock();
526 
527         return result;
528     }
529     return VK_ERROR_VALIDATION_FAILED_EXT;
530 }
531 
GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,struct wl_display * display)532 VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
533                                                                               uint32_t queueFamilyIndex,
534                                                                               struct wl_display *display) {
535     VkBool32 result = VK_FALSE;
536     bool skip_call = false;
537     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
538     std::unique_lock<std::mutex> lock(global_lock);
539     SwpPhysicalDevice *pPhysicalDevice = NULL;
540     {
541         auto it = my_data->physicalDeviceMap.find(physicalDevice);
542         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
543     }
544 
545     // Validate that the platform extension was enabled:
546     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
547         skip_call |=
548             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
549                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
550                     swapchain_layer_name, "vkGetPhysicalDeviceWaylandPresentationSupportKHR() called even though the %s "
551                                           "extension was not enabled for this VkInstance.",
552                     VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
553     }
554     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
555         skip_call |= ValidateQueueFamilyIndex(my_data, queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies,
556                                               pPhysicalDevice->physicalDevice, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
557     }
558     lock.unlock();
559 
560     if (!skip_call) {
561         // Call down the call chain:
562         result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
563                                                                                                   display);
564     }
565     return result;
566 }
567 #endif // VK_USE_PLATFORM_WAYLAND_KHR
568 
569 #ifdef VK_USE_PLATFORM_WIN32_KHR
CreateWin32SurfaceKHR(VkInstance instance,const VkWin32SurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)570 VKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
571                                                      const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
572     VkResult result = VK_SUCCESS;
573     bool skip_call = false;
574     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
575     std::unique_lock<std::mutex> lock(global_lock);
576     SwpInstance *pInstance = NULL;
577     {
578         auto it = my_data->instanceMap.find(instance);
579         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
580     }
581 
582     // Validate that the platform extension was enabled:
583     if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
584         skip_call |=
585             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
586                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
587                     "vkCreateWin32SurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
588                     VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
589     }
590     lock.unlock();
591 
592     if (!skip_call) {
593         // Call down the call chain:
594         result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
595         lock.lock();
596 
597         // Obtain this pointer again after locking:
598         {
599             auto it = my_data->instanceMap.find(instance);
600             pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
601         }
602         if ((result == VK_SUCCESS) && pInstance && pSurface) {
603             // Record the VkSurfaceKHR returned by the ICD:
604             my_data->surfaceMap[*pSurface].surface = *pSurface;
605             my_data->surfaceMap[*pSurface].pInstance = pInstance;
606             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
607             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
608             // Point to the associated SwpInstance:
609             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
610         }
611         lock.unlock();
612 
613         return result;
614     }
615     return VK_ERROR_VALIDATION_FAILED_EXT;
616 }
617 
GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex)618 VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
619                                                                             uint32_t queueFamilyIndex) {
620     VkBool32 result = VK_FALSE;
621     bool skip_call = false;
622     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
623     std::unique_lock<std::mutex> lock(global_lock);
624     SwpPhysicalDevice *pPhysicalDevice = NULL;
625     {
626         auto it = my_data->physicalDeviceMap.find(physicalDevice);
627         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
628     }
629 
630     // Validate that the platform extension was enabled:
631     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
632         skip_call |=
633             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
634                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
635                     swapchain_layer_name, "vkGetPhysicalDeviceWin32PresentationSupportKHR() called even though the %s extension "
636                                           "was not enabled for this VkInstance.",
637                     VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
638     }
639     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
640         skip_call |= ValidateQueueFamilyIndex(my_data, queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies,
641                                               pPhysicalDevice->physicalDevice, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
642     }
643     lock.unlock();
644 
645     if (!skip_call) {
646         // Call down the call chain:
647         result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
648     }
649     return result;
650 }
651 #endif // VK_USE_PLATFORM_WIN32_KHR
652 
653 #ifdef VK_USE_PLATFORM_XCB_KHR
CreateXcbSurfaceKHR(VkInstance instance,const VkXcbSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)654 VKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
655                                                    const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
656     VkResult result = VK_SUCCESS;
657     bool skip_call = false;
658     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
659     std::unique_lock<std::mutex> lock(global_lock);
660     SwpInstance *pInstance = NULL;
661     {
662         auto it = my_data->instanceMap.find(instance);
663         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
664     }
665 
666     // Validate that the platform extension was enabled:
667     if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
668         skip_call |=
669             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
670                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
671                     "vkCreateXcbSurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
672                     VK_KHR_XCB_SURFACE_EXTENSION_NAME);
673     }
674     lock.unlock();
675 
676     if (!skip_call) {
677         // Call down the call chain:
678         result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
679         lock.lock();
680 
681         // Obtain this pointer again after locking:
682         {
683             auto it = my_data->instanceMap.find(instance);
684             pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
685         }
686         if ((result == VK_SUCCESS) && pInstance && pSurface) {
687             // Record the VkSurfaceKHR returned by the ICD:
688             my_data->surfaceMap[*pSurface].surface = *pSurface;
689             my_data->surfaceMap[*pSurface].pInstance = pInstance;
690             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
691             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
692             // Point to the associated SwpInstance:
693             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
694         }
695         lock.unlock();
696 
697         return result;
698     }
699     return VK_ERROR_VALIDATION_FAILED_EXT;
700 }
701 
GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,xcb_connection_t * connection,xcb_visualid_t visual_id)702 VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
703                                                                           uint32_t queueFamilyIndex, xcb_connection_t *connection,
704                                                                           xcb_visualid_t visual_id) {
705     VkBool32 result = VK_FALSE;
706     bool skip_call = false;
707     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
708     std::unique_lock<std::mutex> lock(global_lock);
709     SwpPhysicalDevice *pPhysicalDevice = NULL;
710     {
711         auto it = my_data->physicalDeviceMap.find(physicalDevice);
712         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
713     }
714 
715     // Validate that the platform extension was enabled:
716     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
717         skip_call |=
718             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
719                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
720                     swapchain_layer_name, "vkGetPhysicalDeviceXcbPresentationSupportKHR() called even though the %s "
721                                           "extension was not enabled for this VkInstance.",
722                     VK_KHR_XCB_SURFACE_EXTENSION_NAME);
723     }
724     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
725         skip_call |= ValidateQueueFamilyIndex(my_data, queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies,
726                                               pPhysicalDevice->physicalDevice, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
727     }
728     lock.unlock();
729 
730     if (!skip_call) {
731         // Call down the call chain:
732         result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
733                                                                                               connection, visual_id);
734     }
735     return result;
736 }
737 #endif // VK_USE_PLATFORM_XCB_KHR
738 
739 #ifdef VK_USE_PLATFORM_XLIB_KHR
CreateXlibSurfaceKHR(VkInstance instance,const VkXlibSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)740 VKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
741                                                     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
742     VkResult result = VK_SUCCESS;
743     bool skip_call = false;
744     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
745     std::unique_lock<std::mutex> lock(global_lock);
746     SwpInstance *pInstance = NULL;
747     {
748         auto it = my_data->instanceMap.find(instance);
749         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
750     }
751 
752     // Validate that the platform extension was enabled:
753     if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
754         skip_call |=
755             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
756                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
757                     "vkCreateXlibSurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
758                     VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
759     }
760     lock.unlock();
761 
762     if (!skip_call) {
763         // Call down the call chain:
764         result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
765         lock.lock();
766 
767         // Obtain this pointer again after locking:
768         {
769             auto it = my_data->instanceMap.find(instance);
770             pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
771         }
772         if ((result == VK_SUCCESS) && pInstance && pSurface) {
773             // Record the VkSurfaceKHR returned by the ICD:
774             my_data->surfaceMap[*pSurface].surface = *pSurface;
775             my_data->surfaceMap[*pSurface].pInstance = pInstance;
776             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
777             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
778             // Point to the associated SwpInstance:
779             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
780         }
781         lock.unlock();
782 
783         return result;
784     }
785     return VK_ERROR_VALIDATION_FAILED_EXT;
786 }
787 
GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,Display * dpy,VisualID visualID)788 VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
789                                                                            uint32_t queueFamilyIndex, Display *dpy,
790                                                                            VisualID visualID) {
791     VkBool32 result = VK_FALSE;
792     bool skip_call = false;
793     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
794     std::unique_lock<std::mutex> lock(global_lock);
795     SwpPhysicalDevice *pPhysicalDevice = NULL;
796     {
797         auto it = my_data->physicalDeviceMap.find(physicalDevice);
798         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
799     }
800 
801     // Validate that the platform extension was enabled:
802     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
803         skip_call |=
804             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
805                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
806                     swapchain_layer_name, "vkGetPhysicalDeviceXlibPresentationSupportKHR() called even though the %s "
807                                           "extension was not enabled for this VkInstance.",
808                     VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
809     }
810     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
811         skip_call |= ValidateQueueFamilyIndex(my_data, queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies,
812                                               pPhysicalDevice->physicalDevice, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
813     }
814     lock.unlock();
815 
816     if (!skip_call) {
817         // Call down the call chain:
818         result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
819                                                                                                dpy, visualID);
820     }
821     return result;
822 }
823 #endif // VK_USE_PLATFORM_XLIB_KHR
824 
GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPropertiesKHR * pProperties)825 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
826                                                                      VkDisplayPropertiesKHR *pProperties) {
827     VkResult result = VK_SUCCESS;
828     bool skip_call = false;
829     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
830     std::unique_lock<std::mutex> lock(global_lock);
831     SwpPhysicalDevice *pPhysicalDevice = NULL;
832     {
833         auto it = my_data->physicalDeviceMap.find(physicalDevice);
834         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
835     }
836 
837     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
838         skip_call |=
839             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
840                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
841                     swapchain_layer_name, "vkGetPhysicalDeviceDisplayPropertiesKHR() called even though the %s "
842                                           "extension was not enabled for this VkInstance.",
843                     VK_KHR_DISPLAY_EXTENSION_NAME);
844     }
845     lock.unlock();
846 
847     if (!skip_call) {
848         result =
849             my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties);
850         return result;
851     }
852     return VK_ERROR_VALIDATION_FAILED_EXT;
853 }
854 
GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPlanePropertiesKHR * pProperties)855 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
856                                                                           VkDisplayPlanePropertiesKHR *pProperties) {
857     VkResult result = VK_SUCCESS;
858     bool skip_call = false;
859     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
860     std::unique_lock<std::mutex> lock(global_lock);
861     SwpPhysicalDevice *pPhysicalDevice = NULL;
862     {
863         auto it = my_data->physicalDeviceMap.find(physicalDevice);
864         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
865     }
866 
867     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
868         skip_call |=
869             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
870                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
871                     swapchain_layer_name, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR() called even though the %s "
872                                           "extension was not enabled for this VkInstance.",
873                     VK_KHR_DISPLAY_EXTENSION_NAME);
874     }
875     lock.unlock();
876 
877     if (!skip_call) {
878         result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount,
879                                                                                               pProperties);
880 
881         lock.lock();
882         if (!pPhysicalDevice->gotDisplayPlanePropertyCount) {
883             pPhysicalDevice->displayPlanePropertyCount = *pPropertyCount;
884             pPhysicalDevice->gotDisplayPlanePropertyCount = true;
885         }
886         // TODO store the properties for later checks
887         lock.unlock();
888 
889         return result;
890     }
891     return VK_ERROR_VALIDATION_FAILED_EXT;
892 }
893 
GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,uint32_t planeIndex,uint32_t * pDisplayCount,VkDisplayKHR * pDisplays)894 VKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
895                                                                    uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
896     VkResult result = VK_SUCCESS;
897     bool skip_call = false;
898     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
899     std::unique_lock<std::mutex> lock(global_lock);
900     SwpPhysicalDevice *pPhysicalDevice = NULL;
901     {
902         auto it = my_data->physicalDeviceMap.find(physicalDevice);
903         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
904     }
905 
906     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
907         skip_call |=
908             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
909                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
910                     swapchain_layer_name, "vkGetDisplayPlaneSupportedDisplaysKHR() called even though the %s "
911                                           "extension was not enabled for this VkInstance.",
912                     VK_KHR_DISPLAY_EXTENSION_NAME);
913     }
914 
915     if (!pPhysicalDevice->gotDisplayPlanePropertyCount) {
916         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
917                              reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__,
918                              SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, swapchain_layer_name,
919                              "Potential problem with calling vkGetDisplayPlaneSupportedDisplaysKHR() without first "
920                              "querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.");
921     }
922 
923     if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount) {
924         skip_call |=
925             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
926                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
927                     swapchain_layer_name,
928                     "vkGetDisplayPlaneSupportedDisplaysKHR(): planeIndex must be in the range [0, %d] that was returned by "
929                     "vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
930                     pPhysicalDevice->displayPlanePropertyCount - 1);
931     }
932     lock.unlock();
933 
934     if (!skip_call) {
935         result = my_data->instance_dispatch_table->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount,
936                                                                                        pDisplays);
937 
938         return result;
939     }
940     // TODO validate the returned display objects
941     return VK_ERROR_VALIDATION_FAILED_EXT;
942 }
943 
GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModePropertiesKHR * pProperties)944 VKAPI_ATTR VkResult VKAPI_CALL GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
945                                                            uint32_t *pPropertyCount, VkDisplayModePropertiesKHR *pProperties) {
946     VkResult result = VK_SUCCESS;
947     bool skip_call = false;
948     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
949     std::unique_lock<std::mutex> lock(global_lock);
950     SwpPhysicalDevice *pPhysicalDevice = NULL;
951     {
952         auto it = my_data->physicalDeviceMap.find(physicalDevice);
953         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
954     }
955 
956     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
957         skip_call |=
958             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
959                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
960                     swapchain_layer_name,
961                     "vkGetDisplayModePropertiesKHR() called even though the %s extension was not enabled for this VkInstance.",
962                     VK_KHR_DISPLAY_EXTENSION_NAME);
963     }
964 
965     lock.unlock();
966 
967     if (!skip_call) {
968         result =
969             my_data->instance_dispatch_table->GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties);
970         return result;
971     }
972     // TODO store the displayMode for later checking
973     return VK_ERROR_VALIDATION_FAILED_EXT;
974 }
975 
CreateDisplayModeKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,const VkDisplayModeCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDisplayModeKHR * pMode)976 VKAPI_ATTR VkResult VKAPI_CALL CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
977                                                     const VkDisplayModeCreateInfoKHR *pCreateInfo,
978                                                     const VkAllocationCallbacks *pAllocator, VkDisplayModeKHR *pMode) {
979     VkResult result = VK_SUCCESS;
980     bool skip_call = false;
981     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
982     std::unique_lock<std::mutex> lock(global_lock);
983     SwpPhysicalDevice *pPhysicalDevice = NULL;
984     {
985         auto it = my_data->physicalDeviceMap.find(physicalDevice);
986         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
987     }
988 
989     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
990         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
991                              reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__,
992                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
993                              "vkCreateDisplayModeKHR() called even though the %s extension was not enabled for this VkInstance.",
994                              VK_KHR_DISPLAY_EXTENSION_NAME);
995     }
996 
997     lock.unlock();
998 
999     // TODO more validation checks needed
1000     if (!skip_call) {
1001         result = my_data->instance_dispatch_table->CreateDisplayModeKHR(physicalDevice, display, pCreateInfo, pAllocator, pMode);
1002         return result;
1003     }
1004 
1005     return VK_ERROR_VALIDATION_FAILED_EXT;
1006 }
1007 
GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkDisplayModeKHR mode,uint32_t planeIndex,VkDisplayPlaneCapabilitiesKHR * pCapabilities)1008 VKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode,
1009                                                               uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
1010     VkResult result = VK_SUCCESS;
1011     bool skip_call = false;
1012     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1013     std::unique_lock<std::mutex> lock(global_lock);
1014     SwpPhysicalDevice *pPhysicalDevice = NULL;
1015     {
1016         auto it = my_data->physicalDeviceMap.find(physicalDevice);
1017         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1018     }
1019 
1020     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1021         skip_call |=
1022             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1023                     reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1024                     swapchain_layer_name,
1025                     "vkGetDisplayPlaneCapabilitiesKHR) called even though the %s extension was not enabled for this VkInstance.",
1026                     VK_KHR_DISPLAY_EXTENSION_NAME);
1027     }
1028 
1029     if (!pPhysicalDevice->gotDisplayPlanePropertyCount) {
1030         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1031                              reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__,
1032                              SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, swapchain_layer_name,
1033                              "Potential problem with calling vkGetDisplayPlaneCapabilitiesKHR() without first "
1034                              "querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.");
1035     }
1036 
1037     if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount) {
1038         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1039                              reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__,
1040                              SWAPCHAIN_PLANE_INDEX_TOO_LARGE, swapchain_layer_name,
1041                              "vkGetDisplayPlaneCapabilitiesKHR(): planeIndex must be in the range [0, %d] that was returned by "
1042                              "vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1043                              pPhysicalDevice->displayPlanePropertyCount - 1);
1044     }
1045 
1046     lock.unlock();
1047 
1048     if (!skip_call) {
1049         result = my_data->instance_dispatch_table->GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
1050         return result;
1051     }
1052 
1053     return VK_ERROR_VALIDATION_FAILED_EXT;
1054 }
1055 
CreateDisplayPlaneSurfaceKHR(VkInstance instance,const VkDisplaySurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1056 VKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
1057                                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1058     VkResult result = VK_SUCCESS;
1059     bool skip_call = false;
1060     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1061     std::unique_lock<std::mutex> lock(global_lock);
1062     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
1063 
1064     // Validate that the platform extension was enabled:
1065     if (pInstance && !pInstance->displayExtensionEnabled) {
1066         skip_call |=
1067             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1068                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
1069                     "vkCreateDisplayPlaneSurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
1070                     VK_KHR_DISPLAY_EXTENSION_NAME);
1071     }
1072 
1073     // TODO more validation checks
1074     if (!skip_call) {
1075         // Call down the call chain:
1076         lock.unlock();
1077         result = my_data->instance_dispatch_table->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
1078         lock.lock();
1079 
1080         // Obtain this pointer again after locking:
1081         pInstance = &(my_data->instanceMap[instance]);
1082         if ((result == VK_SUCCESS) && pInstance && pSurface) {
1083             // Record the VkSurfaceKHR returned by the ICD:
1084             my_data->surfaceMap[*pSurface].surface = *pSurface;
1085             my_data->surfaceMap[*pSurface].pInstance = pInstance;
1086             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
1087             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
1088             // Point to the associated SwpInstance:
1089             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
1090         }
1091         lock.unlock();
1092         return result;
1093     }
1094     return VK_ERROR_VALIDATION_FAILED_EXT;
1095 }
1096 
DestroySurfaceKHR(VkInstance instance,VkSurfaceKHR surface,const VkAllocationCallbacks * pAllocator)1097 VKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
1098     bool skip_call = false;
1099     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1100     std::unique_lock<std::mutex> lock(global_lock);
1101     SwpSurface *pSurface = NULL;
1102     {
1103         auto it = my_data->surfaceMap.find(surface);
1104         pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
1105     }
1106     SwpInstance *pInstance = NULL;
1107     {
1108         auto it = my_data->instanceMap.find(instance);
1109         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1110     }
1111 
1112     // Validate that the platform extension was enabled:
1113     if (pInstance && !pInstance->surfaceExtensionEnabled) {
1114         skip_call |=
1115             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1116                     reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
1117                     "vkDestroySurfaceKHR() called even though the %s extension was not enabled for this VkInstance.",
1118                     VK_KHR_DISPLAY_EXTENSION_NAME);
1119     }
1120 
1121     // Regardless of skip_call value, do some internal cleanup:
1122     if (pSurface) {
1123         // Delete the SwpSurface associated with this surface:
1124         if (pSurface->pInstance) {
1125             pSurface->pInstance->surfaces.erase(surface);
1126         }
1127         if (!pSurface->swapchains.empty()) {
1128             skip_call |=
1129                 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1130                         reinterpret_cast<uint64_t>(instance), __LINE__, SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, swapchain_layer_name,
1131                         "vkDestroySurfaceKHR() called before all of its associated VkSwapchainKHRs were destroyed.");
1132 
1133             // Empty and then delete all SwpSwapchains
1134             for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
1135                 // Delete all SwpImage's
1136                 it->second->images.clear();
1137                 // In case the swapchain's device hasn't been destroyed yet
1138                 // (which isn't likely, but is possible), delete its
1139                 // association with this swapchain (i.e. so we can't point to
1140                 // this swpchain from that device, later on):
1141                 if (it->second->pDevice) {
1142                     it->second->pDevice->swapchains.clear();
1143                 }
1144             }
1145             pSurface->swapchains.clear();
1146         }
1147         my_data->surfaceMap.erase(surface);
1148     }
1149     lock.unlock();
1150 
1151     if (!skip_call) {
1152         // Call down the call chain:
1153         my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
1154     }
1155 }
1156 
EnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)1157 VKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
1158                                                         VkPhysicalDevice *pPhysicalDevices) {
1159     VkResult result = VK_SUCCESS;
1160     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1161 
1162     // Call down the call chain:
1163     result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
1164 
1165     std::lock_guard<std::mutex> lock(global_lock);
1166     SwpInstance *pInstance = NULL;
1167     {
1168         auto it = my_data->instanceMap.find(instance);
1169         pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1170     }
1171     if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
1172         // Record the VkPhysicalDevices returned by the ICD:
1173         for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
1174             my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
1175             my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1176             my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1177             my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1178             my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1179             my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1180             my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1181             my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1182             my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1183             // Point to the associated SwpInstance:
1184             if (pInstance) {
1185                 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
1186             }
1187         }
1188     }
1189     return result;
1190 }
1191 
CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1192 VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
1193                                             const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
1194     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1195     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1196 
1197     assert(chain_info->u.pLayerInfo);
1198     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1199     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
1200     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
1201     if (fpCreateDevice == NULL) {
1202         return VK_ERROR_INITIALIZATION_FAILED;
1203     }
1204 
1205     // Advance the link info for the next element on the chain
1206     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1207 
1208     VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1209     if (result != VK_SUCCESS) {
1210         return result;
1211     }
1212 
1213     std::lock_guard<std::mutex> lock(global_lock);
1214     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1215 
1216     // Setup device dispatch table
1217     my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1218     layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1219 
1220     my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1221     checkDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
1222 
1223     return result;
1224 }
1225 
DestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)1226 VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1227     dispatch_key key = get_dispatch_key(device);
1228     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
1229 
1230     // Call down the call chain:
1231     my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1232 
1233     // Do some internal cleanup:
1234     std::lock_guard<std::mutex> lock(global_lock);
1235     SwpDevice *pDevice = NULL;
1236     {
1237         auto it = my_data->deviceMap.find(device);
1238         pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1239     }
1240     if (pDevice) {
1241         // Delete the SwpDevice associated with this device:
1242         if (pDevice->pPhysicalDevice) {
1243             pDevice->pPhysicalDevice->pDevice = NULL;
1244         }
1245         if (!pDevice->swapchains.empty()) {
1246             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1247                     reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, swapchain_layer_name,
1248                     "vkDestroyDevice() called before all of its associated VkSwapchainKHRs were destroyed.");
1249 
1250             // Empty and then delete all SwpSwapchain's
1251             for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
1252                 // Delete all SwpImage's
1253                 it->second->images.clear();
1254                 // In case the swapchain's surface hasn't been destroyed yet
1255                 // (which is likely) delete its association with this swapchain
1256                 // (i.e. so we can't point to this swpchain from that surface,
1257                 // later on):
1258                 if (it->second->pSurface) {
1259                     it->second->pSurface->swapchains.clear();
1260                 }
1261             }
1262             pDevice->swapchains.clear();
1263         }
1264         my_data->deviceMap.erase(device);
1265     }
1266     delete my_data->device_dispatch_table;
1267     layer_data_map.erase(key);
1268 }
1269 
GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,VkSurfaceKHR surface,VkBool32 * pSupported)1270 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
1271                                                                   VkSurfaceKHR surface, VkBool32 *pSupported) {
1272     VkResult result = VK_SUCCESS;
1273     bool skip_call = false;
1274     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1275     std::unique_lock<std::mutex> lock(global_lock);
1276     SwpPhysicalDevice *pPhysicalDevice = NULL;
1277     {
1278         auto it = my_data->physicalDeviceMap.find(physicalDevice);
1279         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1280     }
1281 
1282     // Validate that the surface extension was enabled:
1283     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1284         skip_call |= log_msg(
1285             my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1286             reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1287             swapchain_layer_name,
1288             "vkGetPhysicalDeviceSurfaceSupportKHR() called even though the %s extension was not enabled for this VkInstance.",
1289             VK_KHR_SURFACE_EXTENSION_NAME);
1290     }
1291     if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
1292         skip_call |= log_msg(
1293             my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1294             reinterpret_cast<uint64_t>(pPhysicalDevice->physicalDevice), __LINE__, SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES,
1295             swapchain_layer_name,
1296             "vkGetPhysicalDeviceSurfaceSupportKHR() called before calling the vkGetPhysicalDeviceQueueFamilyProperties function.");
1297     } else if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
1298         skip_call |= ValidateQueueFamilyIndex(my_data, queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies,
1299                                               pPhysicalDevice->physicalDevice, "vkGetPhysicalDeviceSurfaceSupportKHR");
1300     }
1301 
1302     lock.unlock();
1303 
1304     if (!skip_call) {
1305         // Call down the call chain:
1306         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1307                                                                                       pSupported);
1308         lock.lock();
1309 
1310         // Obtain this pointer again after locking:
1311         {
1312             auto it = my_data->physicalDeviceMap.find(physicalDevice);
1313             pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1314         }
1315         if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1316             // Record the result of this query:
1317             SwpInstance *pInstance = pPhysicalDevice->pInstance;
1318             SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
1319             if (pSurface) {
1320                 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1321                 if (!pSurface->numQueueFamilyIndexSupport) {
1322                     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
1323                         pSurface->pQueueFamilyIndexSupport =
1324                             (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
1325                         if (pSurface->pQueueFamilyIndexSupport != NULL) {
1326                             pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
1327                         }
1328                     }
1329                 }
1330                 if (pSurface->numQueueFamilyIndexSupport) {
1331                     pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
1332                 }
1333             }
1334         }
1335         lock.unlock();
1336 
1337         return result;
1338     }
1339     return VK_ERROR_VALIDATION_FAILED_EXT;
1340 }
1341 
GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)1342 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1343                                                                        VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
1344     VkResult result = VK_SUCCESS;
1345     bool skip_call = false;
1346     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1347     std::unique_lock<std::mutex> lock(global_lock);
1348     SwpPhysicalDevice *pPhysicalDevice = NULL;
1349     {
1350         auto it = my_data->physicalDeviceMap.find(physicalDevice);
1351         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1352     }
1353 
1354     // Validate that the surface extension was enabled:
1355     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1356         skip_call |= log_msg(
1357             my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1358             reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1359             swapchain_layer_name,
1360             "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() called even though the %s extension was not enabled for this VkInstance.",
1361             VK_KHR_DISPLAY_EXTENSION_NAME);
1362     }
1363     lock.unlock();
1364 
1365     if (!skip_call) {
1366         // Call down the call chain:
1367         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1368                                                                                            pSurfaceCapabilities);
1369         lock.lock();
1370 
1371         // Obtain this pointer again after locking:
1372         {
1373             auto it = my_data->physicalDeviceMap.find(physicalDevice);
1374             pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1375         }
1376         if ((result == VK_SUCCESS) && pPhysicalDevice) {
1377             // Record the result of this query:
1378             pPhysicalDevice->gotSurfaceCapabilities = true;
1379             pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1380         }
1381         lock.unlock();
1382 
1383         return result;
1384     }
1385     return VK_ERROR_VALIDATION_FAILED_EXT;
1386 }
1387 
GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats)1388 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1389                                                                   uint32_t *pSurfaceFormatCount,
1390                                                                   VkSurfaceFormatKHR *pSurfaceFormats) {
1391     VkResult result = VK_SUCCESS;
1392     bool skip_call = false;
1393     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1394     std::unique_lock<std::mutex> lock(global_lock);
1395     SwpPhysicalDevice *pPhysicalDevice = NULL;
1396     {
1397         auto it = my_data->physicalDeviceMap.find(physicalDevice);
1398         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1399     }
1400 
1401     // Validate that the surface extension was enabled:
1402     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1403         skip_call |= log_msg(
1404             my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1405             reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1406             swapchain_layer_name,
1407             "vkGetPhysicalDeviceSurfaceFormatsKHR() called even though the %s extension was not enabled for this VkInstance.",
1408             VK_KHR_DISPLAY_EXTENSION_NAME);
1409     }
1410     if (pPhysicalDevice && pSurfaceFormats) {
1411         // Compare the preliminary value of *pSurfaceFormatCount with the value this time:
1412         if (pPhysicalDevice->surfaceFormatCount == 0) {
1413             // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application didn't
1414             // previously call this function with a NULL value of pSurfaceFormats:
1415             skip_call |= log_msg(
1416                 my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1417                 reinterpret_cast<uint64_t>(pPhysicalDevice->physicalDevice), __LINE__, SWAPCHAIN_PRIOR_COUNT, swapchain_layer_name,
1418                 "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive "
1419                 "value has been seen for pSurfaceFormats.");
1420         } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1421             skip_call |= log_msg(
1422                 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1423                 reinterpret_cast<uint64_t>(pPhysicalDevice->physicalDevice), __LINE__, SWAPCHAIN_INVALID_COUNT,
1424                 swapchain_layer_name,
1425                 "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats set to "
1426                 "a value (%d) that is greater than the value (%d) that was returned when pSurfaceFormatCount was NULL.",
1427                 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1428         }
1429     }
1430     lock.unlock();
1431 
1432     if (!skip_call) {
1433         // Call down the call chain:
1434         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1435                                                                                       pSurfaceFormats);
1436         lock.lock();
1437 
1438         // Obtain this pointer again after locking:
1439         {
1440             auto it = my_data->physicalDeviceMap.find(physicalDevice);
1441             pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1442         }
1443         if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
1444             // Record the result of this preliminary query:
1445             pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1446         } else if (((result == VK_SUCCESS) || (result == VK_INCOMPLETE)) && pPhysicalDevice && pSurfaceFormats &&
1447                    pSurfaceFormatCount && (*pSurfaceFormatCount > 0)) {
1448             // Record the result of this query:
1449 
1450             // Note: for poorly-written applications (e.g. that don't call this command
1451             // twice, the first time with pSurfaceFormats set to NULL, and the second time
1452             // with a non-NULL pSurfaceFormats and with the same count as returned the
1453             // first time), record again the count when pSurfaceFormats is non-NULL:
1454             pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1455             pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1456             if (pPhysicalDevice->pSurfaceFormats) {
1457                 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1458                     pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
1459                 }
1460             } else {
1461                 pPhysicalDevice->surfaceFormatCount = 0;
1462             }
1463         }
1464         lock.unlock();
1465 
1466         return result;
1467     }
1468     return VK_ERROR_VALIDATION_FAILED_EXT;
1469 }
1470 
GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)1471 VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1472                                                                        uint32_t *pPresentModeCount,
1473                                                                        VkPresentModeKHR *pPresentModes) {
1474     VkResult result = VK_SUCCESS;
1475     bool skip_call = false;
1476     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1477     std::unique_lock<std::mutex> lock(global_lock);
1478     SwpPhysicalDevice *pPhysicalDevice = NULL;
1479     {
1480         auto it = my_data->physicalDeviceMap.find(physicalDevice);
1481         pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1482     }
1483 
1484     // Validate that the surface extension was enabled:
1485     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1486         skip_call |= log_msg(
1487             my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1488             reinterpret_cast<uint64_t>(pPhysicalDevice->pInstance->instance), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1489             swapchain_layer_name,
1490             "vkGetPhysicalDeviceSurfacePresentModesKHR() called even though the %s extension was not enabled for this VkInstance.",
1491             VK_KHR_DISPLAY_EXTENSION_NAME);
1492     }
1493     if (pPhysicalDevice && pPresentModes) {
1494         // Compare the preliminary value of *pPresentModeCount with the value this time:
1495         if (pPhysicalDevice->presentModeCount == 0) {
1496             // Since we haven't recorded a preliminary value of *pPresentModeCount, that likely means that the application didn't
1497             // previously call this function with a NULL value of pPresentModes:
1498             skip_call |= log_msg(
1499                 my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1500                 reinterpret_cast<uint64_t>(pPhysicalDevice->physicalDevice), __LINE__, SWAPCHAIN_PRIOR_COUNT, swapchain_layer_name,
1501                 "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive "
1502                 "value has been seen for pPresentModes.");
1503         } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1504             skip_call |= log_msg(
1505                 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1506                 reinterpret_cast<uint64_t>(pPhysicalDevice->physicalDevice), __LINE__, SWAPCHAIN_INVALID_COUNT,
1507                 swapchain_layer_name,
1508                 "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount, and with pPresentModes set to "
1509                 "a value (%d) that is greater than the value (%d) that was returned when pPresentModeCount was NULL.",
1510                 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1511         }
1512     }
1513     lock.unlock();
1514 
1515     if (!skip_call) {
1516         // Call down the call chain:
1517         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1518                                                                                            pPresentModeCount, pPresentModes);
1519         lock.lock();
1520 
1521         // Obtain this pointer again after locking:
1522         {
1523             auto it = my_data->physicalDeviceMap.find(physicalDevice);
1524             pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1525         }
1526         if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
1527             // Record the result of this preliminary query:
1528             pPhysicalDevice->presentModeCount = *pPresentModeCount;
1529         } else if (((result == VK_SUCCESS) || (result == VK_INCOMPLETE)) && pPhysicalDevice &&
1530                    pPresentModes && pPresentModeCount && (*pPresentModeCount > 0)) {
1531             // Record the result of this query:
1532 
1533             // Note: for poorly-written applications (e.g. that don't call this command
1534             // twice, the first time with pPresentModes set to NULL, and the second time
1535             // with a non-NULL pPresentModes and with the same count as returned the
1536             // first time), record again the count when pPresentModes is non-NULL:
1537             pPhysicalDevice->presentModeCount = *pPresentModeCount;
1538             pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1539             if (pPhysicalDevice->pPresentModes) {
1540                 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1541                     pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
1542                 }
1543             } else {
1544                 pPhysicalDevice->presentModeCount = 0;
1545             }
1546         }
1547         lock.unlock();
1548 
1549         return result;
1550     }
1551     return VK_ERROR_VALIDATION_FAILED_EXT;
1552 }
1553 
1554 // This function does the up-front validation work for vkCreateSwapchainKHR(),
1555 // and returns true if a logging callback indicates that the call down the
1556 // chain should be skipped:
validateCreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,VkSwapchainKHR * pSwapchain)1557 static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
1558     // TODO: Validate cases of re-creating a swapchain (the current code
1559     // assumes a new swapchain is being created).
1560     bool skip_call = false;
1561     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1562     char fn[] = "vkCreateSwapchainKHR";
1563     SwpDevice *pDevice = NULL;
1564     {
1565         auto it = my_data->deviceMap.find(device);
1566         pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1567     }
1568 
1569     // Validate that the swapchain extension was enabled:
1570     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1571         return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1572                        reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
1573                        "vkCreateSwapchainKHR() called even though the %s extension was not enabled for this VkDevice.",
1574                        VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1575     }
1576 
1577     // Keep around a useful pointer to pPhysicalDevice:
1578     SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1579 
1580     // Validate pCreateInfo values with result of
1581     // vkGetPhysicalDeviceQueueFamilyProperties
1582     if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
1583         for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
1584             skip_call |= ValidateQueueFamilyIndex(my_data, pCreateInfo->pQueueFamilyIndices[i], pPhysicalDevice->numOfQueueFamilies,
1585                                                   pPhysicalDevice->physicalDevice, "vkCreateSwapchainKHR");
1586         }
1587     }
1588 
1589     // Validate pCreateInfo values with the results of
1590     // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1591     if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
1592         skip_call |=
1593             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1594                     reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, swapchain_layer_name,
1595                     "vkCreateSwapchainKHR() called before calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR().");
1596     } else if (pCreateInfo) {
1597         // Validate pCreateInfo->surface to make sure that
1598         // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1599         // surface:
1600         SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
1601         if (!pSurface) {
1602             skip_call |=
1603                 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1604                         reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, swapchain_layer_name,
1605                         "The surface in pCreateInfo->surface, that was given to vkCreateSwapchainKHR(), must be a surface "
1606                         "that is supported by the device as determined by vkGetPhysicalDeviceSurfaceSupportKHR().  "
1607                         "However, vkGetPhysicalDeviceSurfaceSupportKHR() was never called with this surface.");
1608         }
1609 
1610         // Validate pCreateInfo->minImageCount against
1611         // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1612         VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1613         if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
1614             ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
1615             skip_call |=
1616                 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1617                         reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, swapchain_layer_name,
1618                         "vkCreateSwapchainKHR() called with pCreateInfo->minImageCount = %d, which is outside the bounds returned "
1619                         "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d).",
1620                         pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
1621         }
1622         // Validate pCreateInfo->imageExtent against
1623         // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1624         if ((pCapabilities->currentExtent.width == -1) &&
1625             ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1626              (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1627              (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1628              (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
1629             skip_call |= log_msg(
1630                 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1631                 reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS, swapchain_layer_name,
1632                 "vkCreateSwapchainKHR() called with pCreateInfo->imageExtent = (%d,%d), which is outside the "
1633                 "bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), "
1634                 "minImageExtent = (%d,%d), maxImageExtent = (%d,%d).",
1635                 pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1636                 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1637                 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
1638         }
1639         if ((pCapabilities->currentExtent.width != -1) &&
1640             ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1641              (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1642             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1643                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
1644                                  swapchain_layer_name,
1645                                  "vkCreateSwapchainKHR() called with pCreateInfo->imageExtent = (%d,%d), which is not equal to the "
1646                                  "currentExtent = (%d,%d) returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1647                                  pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1648                                  pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
1649         }
1650         // Validate pCreateInfo->preTransform has one bit set (1st two
1651         // lines of if-statement), which bit is also set in
1652         // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
1653         if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
1654             !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1655             // This is an error situation; one for which we'd like to give
1656             // the developer a helpful, multi-line error message.  Build it
1657             // up a little at a time, and then log it:
1658             std::string errorString = "";
1659             char str[1024];
1660             // Here's the first part of the message:
1661             sprintf(str, "%s() called with a non-supported "
1662                          "pCreateInfo->preTransform (i.e. %s).  "
1663                          "Supported values are:\n",
1664                     fn, surfaceTransformStr(pCreateInfo->preTransform));
1665             errorString += str;
1666             for (int i = 0; i < 32; i++) {
1667                 // Build up the rest of the message:
1668                 if ((1 << i) & pCapabilities->supportedTransforms) {
1669                     const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
1670                     sprintf(str, "    %s\n", newStr);
1671                     errorString += str;
1672                 }
1673             }
1674             // Log the message that we've built up:
1675             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1676                                  reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
1677                                  LAYER_NAME, "%s", errorString.c_str());
1678         }
1679         // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1680         // lines of if-statement), which bit is also set in
1681         // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
1682         if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
1683             !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1684             // This is an error situation; one for which we'd like to give
1685             // the developer a helpful, multi-line error message.  Build it
1686             // up a little at a time, and then log it:
1687             std::string errorString = "";
1688             char str[1024];
1689             // Here's the first part of the message:
1690             sprintf(str, "%s() called with a non-supported "
1691                          "pCreateInfo->compositeAlpha (i.e. %s).  "
1692                          "Supported values are:\n",
1693                     fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
1694             errorString += str;
1695             for (int i = 0; i < 32; i++) {
1696                 // Build up the rest of the message:
1697                 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
1698                     const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
1699                     sprintf(str, "    %s\n", newStr);
1700                     errorString += str;
1701                 }
1702             }
1703             // Log the message that we've built up:
1704             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1705                                  reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1706                                  LAYER_NAME, "%s", errorString.c_str());
1707         }
1708         // Validate pCreateInfo->imageArrayLayers against
1709         // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
1710         if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
1711             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1712                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS,
1713                                  swapchain_layer_name,
1714                                  "vkCreateSwapchainKHR() called with a non-supported pCreateInfo->imageArrayLayers (i.e. %d).  "
1715                                  "Minimum value is 1, maximum value is %d.",
1716                                  pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
1717         }
1718         // Validate pCreateInfo->imageUsage against
1719         // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
1720         if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
1721             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1722                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
1723                                  swapchain_layer_name,
1724                                  "vkCreateSwapchainKHR() called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x).  "
1725                                  "Supported flag bits are 0x%08x.",
1726                                  pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
1727         }
1728     }
1729 
1730     // Validate pCreateInfo values with the results of
1731     // vkGetPhysicalDeviceSurfaceFormatsKHR():
1732     if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
1733         skip_call |=
1734             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1735                     reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, swapchain_layer_name,
1736                     "vkCreateSwapchainKHR() called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().");
1737     } else if (pCreateInfo) {
1738         // Validate pCreateInfo->imageFormat against
1739         // VkSurfaceFormatKHR::format:
1740         bool foundFormat = false;
1741         bool foundColorSpace = false;
1742         bool foundMatch = false;
1743         for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
1744             if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1745                 // Validate pCreateInfo->imageColorSpace against
1746                 // VkSurfaceFormatKHR::colorSpace:
1747                 foundFormat = true;
1748                 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1749                     foundMatch = true;
1750                     break;
1751                 }
1752             } else {
1753                 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1754                     foundColorSpace = true;
1755                 }
1756             }
1757         }
1758         if (!foundMatch) {
1759             if (!foundFormat) {
1760                 if (!foundColorSpace) {
1761                     skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1762                                          VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, reinterpret_cast<uint64_t>(device), __LINE__,
1763                                          SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, swapchain_layer_name,
1764                                          "vkCreateSwapchainKHR() called with neither a supported pCreateInfo->imageFormat "
1765                                          "(i.e. %d) nor a supported "
1766                                          "pCreateInfo->imageColorSpace (i.e. %d).",
1767                                          pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
1768                 } else {
1769                     skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1770                                          VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, reinterpret_cast<uint64_t>(device), __LINE__,
1771                                          SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, swapchain_layer_name,
1772                                          "vkCreateSwapchainKHR() called with a non-supported pCreateInfo->imageFormat (i.e. %d)",
1773                                          pCreateInfo->imageFormat);
1774                 }
1775             } else if (!foundColorSpace) {
1776                 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1777                                      reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
1778                                      swapchain_layer_name,
1779                                      "vkCreateSwapchainKHR() called with a non-supported pCreateInfo->imageColorSpace (i.e. %d).",
1780                                      pCreateInfo->imageColorSpace);
1781             }
1782         }
1783     }
1784 
1785     // Validate pCreateInfo values with the results of
1786     // vkGetPhysicalDeviceSurfacePresentModesKHR():
1787     if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
1788         if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1789             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1790                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1791                                  swapchain_layer_name, "vkCreateSwapchainKHR() called before calling "
1792                                                        "vkGetPhysicalDeviceSurfacePresentModesKHR().");
1793         }
1794     } else if (pCreateInfo) {
1795         // Validate pCreateInfo->presentMode against
1796         // vkGetPhysicalDeviceSurfacePresentModesKHR():
1797         bool foundMatch = false;
1798         for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
1799             if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1800                 foundMatch = true;
1801                 break;
1802             }
1803         }
1804         if (!foundMatch) {
1805             skip_call |=
1806                 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1807                         reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, swapchain_layer_name,
1808                         "vkCreateSwapchainKHR() called with a non-supported pCreateInfo->presentMode (i.e. %s).",
1809                         presentModeStr(pCreateInfo->presentMode));
1810         }
1811     }
1812 
1813     // Validate pCreateInfo->imageSharingMode and related values:
1814     if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
1815         if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
1816             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1817                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES,
1818                                  swapchain_layer_name,
1819                                  "vkCreateSwapchainKHR() called with a supported pCreateInfo->sharingMode of (i.e. %s), but with a "
1820                                  "bad value(s) for pCreateInfo->queueFamilyIndexCount or pCreateInfo->pQueueFamilyIndices).",
1821                                  sharingModeStr(pCreateInfo->imageSharingMode));
1822         }
1823     } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
1824         skip_call |=
1825             log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1826                     reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE, swapchain_layer_name,
1827                     "vkCreateSwapchainKHR() called with a non-supported pCreateInfo->imageSharingMode (i.e. %s).",
1828                     sharingModeStr(pCreateInfo->imageSharingMode));
1829     }
1830 
1831     // Validate pCreateInfo->clipped:
1832     if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1833         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1834                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_BAD_BOOL, swapchain_layer_name,
1835                              "vkCreateSwapchainKHR() called with a VkBool32 value that is neither VK_TRUE nor VK_FALSE, but "
1836                              "has the numeric value of %d.",
1837                              pCreateInfo->clipped);
1838     }
1839 
1840     return skip_call;
1841 }
1842 
CreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchain)1843 VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1844                                                   const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
1845     VkResult result = VK_SUCCESS;
1846     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1847     std::unique_lock<std::mutex> lock(global_lock);
1848     bool skip_call = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
1849     lock.unlock();
1850 
1851     if (!skip_call) {
1852         // Call down the call chain:
1853         result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
1854         lock.lock();
1855 
1856         if (result == VK_SUCCESS) {
1857             // Remember the swapchain's handle, and link it to the device:
1858             SwpDevice *pDevice = NULL;
1859             {
1860                 auto it = my_data->deviceMap.find(device);
1861                 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1862             }
1863 
1864             my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1865             if (pDevice) {
1866                 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
1867             }
1868             my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1869             my_data->swapchainMap[*pSwapchain].imageCount = 0;
1870             // Store a pointer to the surface
1871             SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1872             SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
1873             layer_data *my_instance_data =
1874                 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
1875             SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
1876             my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1877             if (pSurface) {
1878                 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
1879             }
1880         }
1881         lock.unlock();
1882 
1883         return result;
1884     }
1885     return VK_ERROR_VALIDATION_FAILED_EXT;
1886 }
1887 
DestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)1888 VKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
1889     // TODOs:
1890     //
1891     // - Implement a check for validity language that reads: All uses of
1892     //   presentable images acquired from pname:swapchain must: have completed
1893     //   execution
1894     bool skip_call = false;
1895     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1896     std::unique_lock<std::mutex> lock(global_lock);
1897     SwpDevice *pDevice = NULL;
1898     {
1899         auto it = my_data->deviceMap.find(device);
1900         pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1901     }
1902 
1903     // Validate that the swapchain extension was enabled:
1904     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1905         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1906                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
1907                              "vkDestroySwapchainKHR() called even though the %s extension was not enabled for this VkDevice.",
1908                              VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1909     }
1910 
1911     // Regardless of skip_call value, do some internal cleanup:
1912     SwpSwapchain *pSwapchain = NULL;
1913     {
1914         auto it = my_data->swapchainMap.find(swapchain);
1915         pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1916     }
1917     if (pSwapchain) {
1918         // Delete the SwpSwapchain associated with this swapchain:
1919         if (pSwapchain->pDevice) {
1920             pSwapchain->pDevice->swapchains.erase(swapchain);
1921         }
1922         if (pSwapchain->pSurface) {
1923             pSwapchain->pSurface->swapchains.erase(swapchain);
1924         }
1925         if (pSwapchain->imageCount) {
1926             pSwapchain->images.clear();
1927         }
1928         my_data->swapchainMap.erase(swapchain);
1929     }
1930     lock.unlock();
1931 
1932     if (!skip_call) {
1933         // Call down the call chain:
1934         my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
1935     }
1936 }
1937 
GetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages)1938 VKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
1939                                                      VkImage *pSwapchainImages) {
1940     VkResult result = VK_SUCCESS;
1941     bool skip_call = false;
1942     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1943     std::unique_lock<std::mutex> lock(global_lock);
1944     SwpDevice *pDevice = NULL;
1945     {
1946         auto it = my_data->deviceMap.find(device);
1947         pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1948     }
1949 
1950     // Validate that the swapchain extension was enabled:
1951     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1952         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1953                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
1954                              "vkGetSwapchainImagesKHR() called even though the %s extension was not enabled for this VkDevice.",
1955                              VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1956     }
1957     SwpSwapchain *pSwapchain = NULL;
1958     {
1959         auto it = my_data->swapchainMap.find(swapchain);
1960         pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1961     }
1962     if (pSwapchain && pSwapchainImages) {
1963         // Compare the preliminary value of *pSwapchainImageCount with the value this time:
1964         if (pSwapchain->imageCount == 0) {
1965             // Since we haven't recorded a preliminary value of *pSwapchainImageCount, that likely means that the application didn't
1966             // previously call this function with a NULL value of pSwapchainImages:
1967             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1968                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_PRIOR_COUNT, swapchain_layer_name,
1969                                  "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount; but no prior positive "
1970                                  "value has been seen for pSwapchainImages.");
1971         } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
1972             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1973                                  reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_INVALID_COUNT, swapchain_layer_name,
1974                                  "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount, and with "
1975                                  "pSwapchainImages set to a value (%d) that is greater than the value (%d) that was returned when "
1976                                  "pSwapchainImageCount was NULL.",
1977                                  *pSwapchainImageCount, pSwapchain->imageCount);
1978         }
1979     }
1980     lock.unlock();
1981 
1982     if (!skip_call) {
1983         // Call down the call chain:
1984         result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
1985         lock.lock();
1986 
1987         // Obtain this pointer again after locking:
1988         {
1989             auto it = my_data->swapchainMap.find(swapchain);
1990             pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1991         }
1992         if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
1993             // Record the result of this preliminary query:
1994             pSwapchain->imageCount = *pSwapchainImageCount;
1995         } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages && pSwapchainImageCount &&
1996                    (*pSwapchainImageCount > 0)) {
1997             // Record the images and their state:
1998             pSwapchain->imageCount = *pSwapchainImageCount;
1999             for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
2000                 pSwapchain->images[i].image = pSwapchainImages[i];
2001                 pSwapchain->images[i].pSwapchain = pSwapchain;
2002                 pSwapchain->images[i].acquiredByApp = false;
2003             }
2004         }
2005         lock.unlock();
2006 
2007         return result;
2008     }
2009     return VK_ERROR_VALIDATION_FAILED_EXT;
2010 }
2011 
AcquireNextImageKHR(VkDevice device,VkSwapchainKHR swapchain,uint64_t timeout,VkSemaphore semaphore,VkFence fence,uint32_t * pImageIndex)2012 VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
2013                                                    VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
2014     // TODOs:
2015     //
2016     // - Address the timeout.  Possibilities include looking at the state of the
2017     //   swapchain's images, depending on the timeout value.
2018     // - Implement a check for validity language that reads: If pname:semaphore is
2019     //   not sname:VK_NULL_HANDLE it must: be unsignalled
2020     // - Implement a check for validity language that reads: If pname:fence is not
2021     //   sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2022     //   with any other queue command that has not yet completed execution on that
2023     //   queue
2024     // - Record/update the state of the swapchain, in case an error occurs
2025     //   (e.g. VK_ERROR_OUT_OF_DATE_KHR).
2026     VkResult result = VK_SUCCESS;
2027     bool skip_call = false;
2028     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2029     std::unique_lock<std::mutex> lock(global_lock);
2030     SwpDevice *pDevice = NULL;
2031     {
2032         auto it = my_data->deviceMap.find(device);
2033         pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2034     }
2035 
2036     // Validate that the swapchain extension was enabled:
2037     if (pDevice && !pDevice->swapchainExtensionEnabled) {
2038         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2039                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
2040                              "vkAcquireNextImageKHR() called even though the %s extension was not enabled for this VkDevice.",
2041                              VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2042     }
2043     SwpSwapchain *pSwapchain = NULL;
2044     {
2045         auto it = my_data->swapchainMap.find(swapchain);
2046         pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2047     }
2048     SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
2049     if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
2050         // Look to see if the application has already acquired the maximum
2051         // number of images, and this will push it past the spec-defined
2052         // limits:
2053         uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
2054         uint32_t imagesAcquiredByApp = 0;
2055         for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
2056             if (pSwapchain->images[i].acquiredByApp) {
2057                 imagesAcquiredByApp++;
2058             }
2059         }
2060         if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
2061             skip_call |= log_msg(
2062                 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2063                 reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES, swapchain_layer_name,
2064                 "vkAcquireNextImageKHR() called when it cannot succeed.  The application has acquired %d image(s) that have not "
2065                 "yet "
2066                 "been presented.  The maximum number of images that the application can simultaneously acquire from this swapchain "
2067                 "(including this call to vkCreateSwapchainKHR()) is %d.  That value is derived by subtracting "
2068                 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number of images in the swapchain (%d) and adding 1.",
2069                 imagesAcquiredByApp, (pSwapchain->imageCount - minImageCount + 1), minImageCount, pSwapchain->imageCount);
2070         }
2071     }
2072     lock.unlock();
2073 
2074     if (!skip_call) {
2075         // Call down the call chain:
2076         result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
2077         lock.lock();
2078 
2079         // Obtain this pointer again after locking:
2080         {
2081             auto it = my_data->swapchainMap.find(swapchain);
2082             pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2083         }
2084         if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
2085             // Change the state of the image (now acquired by the application):
2086             pSwapchain->images[*pImageIndex].acquiredByApp = true;
2087         }
2088         lock.unlock();
2089 
2090         return result;
2091     }
2092     return VK_ERROR_VALIDATION_FAILED_EXT;
2093 }
2094 
QueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * pPresentInfo)2095 VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
2096     // TODOs:
2097     //
2098     // - Implement a check for validity language that reads: Any given element of
2099     //   sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2100     //   of that sname:VkSemaphore that won't be consumed by any other wait on that
2101     //   semaphore
2102     // - Record/update the state of the swapchain, in case an error occurs
2103     //   (e.g. VK_ERROR_OUT_OF_DATE_KHR).
2104     VkResult result = VK_SUCCESS;
2105     bool skip_call = false;
2106     layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
2107 
2108     // Note: pPresentInfo->pResults is allowed to be NULL
2109 
2110     std::unique_lock<std::mutex> lock(global_lock);
2111     for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
2112         SwpSwapchain *pSwapchain = NULL;
2113         {
2114             auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2115             pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2116         }
2117         if (pSwapchain) {
2118             if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
2119                 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2120                                      reinterpret_cast<uint64_t>(pSwapchain->pDevice->device), __LINE__,
2121                                      SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
2122                                      "vkQueuePresentKHR() called even though the %s extension was not enabled for this VkDevice.",
2123                                      VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2124             }
2125             SwpQueue *pQueue = NULL;
2126             {
2127                 auto it = my_data->queueMap.find(queue);
2128                 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2129             }
2130             SwpSurface *pSurface = pSwapchain->pSurface;
2131             if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2132                 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2133                 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2134                 // and the 2nd test is the validation check:
2135                 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2136                     (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
2137                     skip_call |=
2138                         log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2139                                 reinterpret_cast<const uint64_t &>(pPresentInfo->pSwapchains[i]), __LINE__,
2140                                 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, swapchain_layer_name,
2141                                 "vkQueuePresentKHR() called with a swapchain whose surface is not supported for presention "
2142                                 "on this device with the queueFamilyIndex (i.e. %d) of the given queue.",
2143                                 queueFamilyIndex);
2144                 }
2145             }
2146         }
2147     }
2148     lock.unlock();
2149 
2150     if (!skip_call) {
2151         // Call down the call chain:
2152         result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
2153         lock.lock();
2154 
2155         if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2156             for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
2157                 int index = pPresentInfo->pImageIndices[i];
2158                 SwpSwapchain *pSwapchain = NULL;
2159                 {
2160                     auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2161                     pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2162                 }
2163                 if (pSwapchain) {
2164                     // Change the state of the image (no longer acquired by the
2165                     // application):
2166                     pSwapchain->images[index].acquiredByApp = false;
2167                 }
2168             }
2169         }
2170         lock.unlock();
2171 
2172         return result;
2173     }
2174     return VK_ERROR_VALIDATION_FAILED_EXT;
2175 }
2176 
CreateSharedSwapchainsKHR(VkDevice device,uint32_t swapchainCount,const VkSwapchainCreateInfoKHR * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchains)2177 VKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
2178                                                          const VkSwapchainCreateInfoKHR *pCreateInfos,
2179                                                          const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
2180     VkResult result = VK_SUCCESS;
2181     bool skip_call = false;
2182     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2183     std::unique_lock<std::mutex> lock(global_lock);
2184     SwpDevice *pDevice = nullptr;
2185     {
2186         auto it = my_data->deviceMap.find(device);
2187         pDevice = (it == my_data->deviceMap.end()) ? nullptr : &it->second;
2188     }
2189 
2190     // Validate that the swapchain extension was enabled:
2191     if (pDevice && !pDevice->displaySwapchainExtensionEnabled) {
2192         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2193                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, swapchain_layer_name,
2194                              "vkCreateSharedSwapchainsKHR() called even though the %s extension was not enabled for this VkDevice.",
2195                              VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME);
2196     }
2197     if (!pCreateInfos || !pSwapchains) {
2198         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2199                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_NULL_POINTER, swapchain_layer_name,
2200                              "vkCreateSharedSwapchainsKHR() called with NULL pointer");
2201     }
2202     if (swapchainCount == 0) {
2203         skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2204                              reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_INVALID_COUNT, swapchain_layer_name,
2205                              "vkCreateSharedSwapchainsKHR() called with invalid swapchain count of %d.", swapchainCount);
2206     } else {
2207         SwpSwapchain *pSwapchain = nullptr;
2208         for (uint32_t iii = 0; iii < swapchainCount; iii++) {
2209             if (pCreateInfos[iii].sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
2210                 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2211                                      reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_WRONG_STYPE, swapchain_layer_name,
2212                                      "vkCreateSharedSwapchainsKHR() called with invalid stype in pCreateInfos[%d].", iii);
2213             }
2214             auto it = my_data->swapchainMap.find(pSwapchains[iii]);
2215             pSwapchain = (it == my_data->swapchainMap.end()) ? nullptr : &it->second;
2216             if (nullptr == pSwapchain) {
2217                 skip_call |=
2218                     log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2219                             reinterpret_cast<uint64_t>(device), __LINE__, SWAPCHAIN_INVALID_HANDLE, swapchain_layer_name,
2220                             "vkCreateSharedSwapchainsKHR() called with invalid Swapchain Handle in pCreateInfos[%d].", iii);
2221             }
2222         }
2223     }
2224     lock.unlock();
2225 
2226     if (!skip_call) {
2227         // Call down the call chain:
2228         result = my_data->device_dispatch_table->CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator,
2229                                                                            pSwapchains);
2230         return result;
2231     }
2232     return VK_ERROR_VALIDATION_FAILED_EXT;
2233 }
2234 
2235 VKAPI_ATTR void VKAPI_CALL
GetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)2236 GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
2237     bool skip_call = false;
2238     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2239 
2240     if (!skip_call) {
2241         // Call down the call chain:
2242         my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
2243 
2244         // Remember the queue's handle, and link it to the device:
2245         std::lock_guard<std::mutex> lock(global_lock);
2246         SwpDevice *pDevice = NULL;
2247         {
2248             auto it = my_data->deviceMap.find(device);
2249             pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2250         }
2251         my_data->queueMap[&pQueue].queue = *pQueue;
2252         if (pDevice) {
2253             pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2254         }
2255         my_data->queueMap[&pQueue].pDevice = pDevice;
2256         my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2257     }
2258 }
2259 
CreateDebugReportCallbackEXT(VkInstance instance,const VkDebugReportCallbackCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDebugReportCallbackEXT * pMsgCallback)2260 VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
2261                                                             const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2262                                                             const VkAllocationCallbacks *pAllocator,
2263                                                             VkDebugReportCallbackEXT *pMsgCallback) {
2264     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2265     VkResult result =
2266         my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
2267     if (VK_SUCCESS == result) {
2268         std::lock_guard<std::mutex> lock(global_lock);
2269         result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
2270     }
2271     return result;
2272 }
2273 
DestroyDebugReportCallbackEXT(VkInstance instance,VkDebugReportCallbackEXT msgCallback,const VkAllocationCallbacks * pAllocator)2274 VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback,
2275                                                          const VkAllocationCallbacks *pAllocator) {
2276     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2277     my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
2278     std::lock_guard<std::mutex> lock(global_lock);
2279     layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2280 }
2281 
DebugReportMessageEXT(VkInstance instance,VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objType,uint64_t object,size_t location,int32_t msgCode,const char * pLayerPrefix,const char * pMsg)2282 VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
2283                                                  VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
2284                                                  int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
2285     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2286     my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2287                                                             pMsg);
2288 }
2289 
EnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)2290 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2291     return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2292 }
2293 
EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pCount,VkLayerProperties * pProperties)2294 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
2295                                                               VkLayerProperties *pProperties) {
2296     return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2297 }
2298 
EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)2299 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
2300                                                                     VkExtensionProperties *pProperties) {
2301     if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2302         return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2303 
2304     return VK_ERROR_LAYER_NOT_PRESENT;
2305 }
2306 
EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)2307 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
2308                                                                   uint32_t *pCount, VkExtensionProperties *pProperties) {
2309     if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2310         return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
2311 
2312     assert(physicalDevice);
2313 
2314     dispatch_key key = get_dispatch_key(physicalDevice);
2315     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2316     return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
2317 }
2318 
2319 static PFN_vkVoidFunction intercept_core_instance_command(const char *name);
2320 
2321 static PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance);
2322 
2323 static PFN_vkVoidFunction intercept_core_device_command(const char *name);
2324 
2325 static PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev);
2326 
GetDeviceProcAddr(VkDevice device,const char * funcName)2327 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2328     PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2329     if (proc)
2330         return proc;
2331 
2332     assert(device);
2333 
2334     layer_data *my_data;
2335 
2336     my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2337     VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
2338 
2339     proc = intercept_khr_swapchain_command(funcName, device);
2340     if (proc)
2341         return proc;
2342 
2343     if (pDisp->GetDeviceProcAddr == NULL)
2344         return NULL;
2345     return pDisp->GetDeviceProcAddr(device, funcName);
2346 }
2347 
GetInstanceProcAddr(VkInstance instance,const char * funcName)2348 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
2349     PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
2350     if (!proc)
2351         proc = intercept_core_device_command(funcName);
2352     if (!proc)
2353         proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
2354     if (proc)
2355         return proc;
2356 
2357     assert(instance);
2358 
2359     layer_data *my_data;
2360     my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2361     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
2362 
2363     proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2364     if (!proc)
2365         proc = intercept_khr_surface_command(funcName, instance);
2366     if (proc)
2367         return proc;
2368 
2369     if (pTable->GetInstanceProcAddr == NULL)
2370         return NULL;
2371     return pTable->GetInstanceProcAddr(instance, funcName);
2372 }
2373 
intercept_core_instance_command(const char * name)2374 static PFN_vkVoidFunction intercept_core_instance_command(const char *name) {
2375     static const struct {
2376         const char *name;
2377         PFN_vkVoidFunction proc;
2378     } core_instance_commands[] = {
2379         {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr)},
2380         {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance)},
2381         {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)},
2382         {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice)},
2383         {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices)},
2384         {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties)},
2385         {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties)},
2386         {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties)},
2387         {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties)},
2388         {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties)},
2389     };
2390 
2391     for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2392         if (!strcmp(core_instance_commands[i].name, name))
2393             return core_instance_commands[i].proc;
2394     }
2395 
2396     return nullptr;
2397 }
2398 
intercept_khr_surface_command(const char * name,VkInstance instance)2399 static PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance) {
2400     static const struct {
2401         const char *name;
2402         PFN_vkVoidFunction proc;
2403     } khr_surface_commands[] = {
2404 #ifdef VK_USE_PLATFORM_ANDROID_KHR
2405         {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR)},
2406 #endif // VK_USE_PLATFORM_ANDROID_KHR
2407 #ifdef VK_USE_PLATFORM_MIR_KHR
2408         {"vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR)},
2409         {"vkGetPhysicalDeviceMirPresentationSupportKHR",
2410          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR)},
2411 #endif // VK_USE_PLATFORM_MIR_KHR
2412 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
2413         {"vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR)},
2414         {"vkGetPhysicalDeviceWaylandPresentationSupportKHR",
2415          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR)},
2416 #endif // VK_USE_PLATFORM_WAYLAND_KHR
2417 #ifdef VK_USE_PLATFORM_WIN32_KHR
2418         {"vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR)},
2419         {"vkGetPhysicalDeviceWin32PresentationSupportKHR",
2420          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR)},
2421 #endif // VK_USE_PLATFORM_WIN32_KHR
2422 #ifdef VK_USE_PLATFORM_XCB_KHR
2423         {"vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR)},
2424         {"vkGetPhysicalDeviceXcbPresentationSupportKHR",
2425          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR)},
2426 #endif // VK_USE_PLATFORM_XCB_KHR
2427 #ifdef VK_USE_PLATFORM_XLIB_KHR
2428         {"vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR)},
2429         {"vkGetPhysicalDeviceXlibPresentationSupportKHR",
2430          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR)},
2431 #endif // VK_USE_PLATFORM_XLIB_KHR
2432         {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR)},
2433         {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR)},
2434         {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
2435          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR)},
2436         {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR)},
2437         {"vkGetPhysicalDeviceSurfacePresentModesKHR",
2438          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR)},
2439         {"vkGetPhysicalDeviceDisplayPropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPropertiesKHR)},
2440         {"vkGetPhysicalDeviceDisplayPlanePropertiesKHR",
2441          reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPlanePropertiesKHR)},
2442         {"vkGetDisplayPlaneSupportedDisplaysKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneSupportedDisplaysKHR)},
2443         {"vkGetDisplayModePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayModePropertiesKHR)},
2444         {"vkCreateDisplayModeKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayModeKHR)},
2445         {"vkGetDisplayPlaneCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneCapabilitiesKHR)},
2446         {"vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR)},
2447     };
2448 
2449     // do not check if VK_KHR_*_surface is enabled (why?)
2450 
2451     for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2452         if (!strcmp(khr_surface_commands[i].name, name))
2453             return khr_surface_commands[i].proc;
2454     }
2455 
2456     return nullptr;
2457 }
2458 
intercept_core_device_command(const char * name)2459 static PFN_vkVoidFunction intercept_core_device_command(const char *name) {
2460     static const struct {
2461         const char *name;
2462         PFN_vkVoidFunction proc;
2463     } core_device_commands[] = {
2464         {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)},
2465         {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)},
2466         {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)},
2467     };
2468 
2469     for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2470         if (!strcmp(core_device_commands[i].name, name))
2471             return core_device_commands[i].proc;
2472     }
2473 
2474     return nullptr;
2475 }
2476 
intercept_khr_swapchain_command(const char * name,VkDevice dev)2477 static PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2478     static const struct {
2479         const char *name;
2480         PFN_vkVoidFunction proc;
2481     } khr_swapchain_commands[] = {
2482         {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR)},
2483         {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR)},
2484         {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR)},
2485         {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR)},
2486         {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR)},
2487     };
2488 
2489     // do not check if VK_KHR_swapchain is enabled (why?)
2490 
2491     for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2492         if (!strcmp(khr_swapchain_commands[i].name, name))
2493             return khr_swapchain_commands[i].proc;
2494     }
2495 
2496     return nullptr;
2497 }
2498 
2499 } // namespace swapchain
2500 
2501 // vk_layer_logging.h expects these to be defined
2502 
vkCreateDebugReportCallbackEXT(VkInstance instance,const VkDebugReportCallbackCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDebugReportCallbackEXT * pMsgCallback)2503 VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance,
2504                                                               const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2505                                                               const VkAllocationCallbacks *pAllocator,
2506                                                               VkDebugReportCallbackEXT *pMsgCallback) {
2507     return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
2508 }
2509 
vkDestroyDebugReportCallbackEXT(VkInstance instance,VkDebugReportCallbackEXT msgCallback,const VkAllocationCallbacks * pAllocator)2510 VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback,
2511                                                            const VkAllocationCallbacks *pAllocator) {
2512     swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
2513 }
2514 
vkDebugReportMessageEXT(VkInstance instance,VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objType,uint64_t object,size_t location,int32_t msgCode,const char * pLayerPrefix,const char * pMsg)2515 VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
2516                                                    VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
2517                                                    int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
2518     swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
2519 }
2520 
2521 // loader-layer interface v0, just wrappers since there is only a layer
2522 
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)2523 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
2524                                                                                       VkExtensionProperties *pProperties) {
2525     return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
2526 }
2527 
vkEnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)2528 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
2529                                                                                   VkLayerProperties *pProperties) {
2530     return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
2531 }
2532 
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pCount,VkLayerProperties * pProperties)2533 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
2534                                                                                 VkLayerProperties *pProperties) {
2535     // the layer command handles VK_NULL_HANDLE just fine internally
2536     assert(physicalDevice == VK_NULL_HANDLE);
2537     return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
2538 }
2539 
vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)2540 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2541                                                                                     const char *pLayerName, uint32_t *pCount,
2542                                                                                     VkExtensionProperties *pProperties) {
2543     // the layer command handles VK_NULL_HANDLE just fine internally
2544     assert(physicalDevice == VK_NULL_HANDLE);
2545     return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
2546 }
2547 
vkGetDeviceProcAddr(VkDevice dev,const char * funcName)2548 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
2549     return swapchain::GetDeviceProcAddr(dev, funcName);
2550 }
2551 
vkGetInstanceProcAddr(VkInstance instance,const char * funcName)2552 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
2553     return swapchain::GetInstanceProcAddr(instance, funcName);
2554 }
2555